summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2017-06-14 14:03:05 +0200
committerWerner Koch <wk@gnupg.org>2017-06-14 14:07:23 +0200
commitf5e7763ddca59dcd9ac9f2f4d50cb41b14a34a9e (patch)
treea26b001fcfa77b5442033141a47f750ce76a0fc9
parent6c882fb1fdb6c7cba2215fa7391110d63e24b9dc (diff)
downloadlibgcrypt-f5e7763ddca59dcd9ac9f2f4d50cb41b14a34a9e.tar.gz
random: Add jitter RND based entropy collector.
* random/rndjent.c: New. * random/rndlinux.c (_gcry_rndlinux_gather_random): Use rndjent. * random/rndw32.c (_gcry_rndw32_gather_random): Use rndjent. (slow_gatherer): Fix compiler warning. * random/Makefile.am (librandom_la_SOURCES): Add rndjent.c (EXTRA_librandom_la_SOURCES): Add jitterentropy-base.c and jitterentropy.h. (rndjent.o, rndjent.lo): New rules. * configure.ac: New option --disbale-jent-support (ENABLE_JENT_SUPPORT): New ac-define. Signed-off-by: Werner Koch <wk@gnupg.org>
-rw-r--r--AUTHORS3
-rw-r--r--configure.ac14
-rw-r--r--random/Makefile.am20
-rw-r--r--random/rand-internal.h8
-rw-r--r--random/rndjent.c208
-rw-r--r--random/rndlinux.c15
-rw-r--r--random/rndw32.c12
7 files changed, 274 insertions, 6 deletions
diff --git a/AUTHORS b/AUTHORS
index b80d43e3..c1e813d6 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -30,13 +30,14 @@ List of Copyright holders
Copyright (C) 1996-2006 Peter Gutmann, Matt Thomlinson and Blake Coverett
Copyright (C) 2003 Nikos Mavroyanopoulos
Copyright (C) 2006-2007 NTT (Nippon Telegraph and Telephone Corporation)
- Copyright (C) 2012-2016 g10 Code GmbH
+ Copyright (C) 2012-2017 g10 Code GmbH
Copyright (C) 2012 Simon Josefsson, Niels Möller
Copyright (c) 2012 Intel Corporation
Copyright (C) 2013 Christian Grothoff
Copyright (C) 2013-2016 Jussi Kivilinna
Copyright (C) 2013-2014 Dmitry Eremin-Solenikov
Copyright (C) 2014 Stephan Mueller
+ Copyright (C) 2017 Bundesamt für Sicherheit in der Informationstechnik
Authors with a FSF copyright assignment
diff --git a/configure.ac b/configure.ac
index 7ea0b6a6..d36673f3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -577,6 +577,14 @@ if test "$use_hmac_binary_check" = yes ; then
fi
+# Implementation of the --disable-jent-support switch.
+AC_MSG_CHECKING([whether jitter entropy support is requested])
+AC_ARG_ENABLE(jent-support,
+ AC_HELP_STRING([--disable-jent-support],
+ [Disable support for the Jitter entropy collector]),
+ jentsupport=$enableval,jentsupport=yes)
+AC_MSG_RESULT($jentsupport)
+
# Implementation of the --disable-padlock-support switch.
AC_MSG_CHECKING([whether padlock support is requested])
AC_ARG_ENABLE(padlock-support,
@@ -1185,6 +1193,7 @@ if test "$mpi_cpu_arch" != "x86" ; then
avxsupport="n/a"
avx2support="n/a"
padlocksupport="n/a"
+ jentsupport="n/a"
drngsupport="n/a"
fi
@@ -1980,6 +1989,10 @@ if test x"$armcryptosupport" = xyes ; then
AC_DEFINE(ENABLE_ARM_CRYPTO_SUPPORT,1,
[Enable support for ARMv8 Crypto Extension instructions.])
fi
+if test x"$jentsupport" = xyes ; then
+ AC_DEFINE(ENABLE_JENT_SUPPORT, 1,
+ [Enable support for the jitter entropy collector.])
+fi
if test x"$padlocksupport" = xyes ; then
AC_DEFINE(ENABLE_PADLOCK_SUPPORT, 1,
[Enable support for the PadLock engine.])
@@ -2619,6 +2632,7 @@ GCRY_MSG_WRAP([Enabled digest algorithms:],[$enabled_digests])
GCRY_MSG_WRAP([Enabled kdf algorithms: ],[$enabled_kdfs])
GCRY_MSG_WRAP([Enabled pubkey algorithms:],[$enabled_pubkey_ciphers])
GCRY_MSG_SHOW([Random number generator: ],[$random])
+GCRY_MSG_SHOW([Try using jitter entropy: ],[$jentsupport])
GCRY_MSG_SHOW([Using linux capabilities: ],[$use_capabilities])
GCRY_MSG_SHOW([Try using Padlock crypto: ],[$padlocksupport])
GCRY_MSG_SHOW([Try using AES-NI crypto: ],[$aesnisupport])
diff --git a/random/Makefile.am b/random/Makefile.am
index 92aba201..aaf205ee 100644
--- a/random/Makefile.am
+++ b/random/Makefile.am
@@ -36,6 +36,7 @@ rand-internal.h \
random-csprng.c \
random-drbg.c \
random-system.c \
+rndjent.c \
rndhw.c
if USE_RANDOM_DAEMON
@@ -48,4 +49,21 @@ rndlinux.c \
rndegd.c \
rndunix.c \
rndw32.c \
-rndw32ce.c
+rndw32ce.c \
+jitterentropy-base.c jitterentropy.h
+
+
+# The rndjent module needs to be compiled without optimization. */
+if ENABLE_O_FLAG_MUNGING
+o_flag_munging = sed -e 's/-O\([1-9s][1-9s]*\)/-O0/' -e 's/-Ofast/-O0/g'
+else
+o_flag_munging = cat
+endif
+
+rndjent.o: $(srcdir)/rndjent.c \
+ $(srcdir)/jitterentropy-base.c $(srcdir)/jitterentropy.h
+ `echo $(COMPILE) -c $(srcdir)/rndjent.c | $(o_flag_munging) `
+
+rndjent.lo: $(srcdir)/rndjent.c \
+ $(srcdir)/jitterentropy-base.c $(srcdir)/jitterentropy.h
+ `echo $(LTCOMPILE) -c $(srcdir)/rndjent.c | $(o_flag_munging) `
diff --git a/random/rand-internal.h b/random/rand-internal.h
index 8c8623ed..7a798e98 100644
--- a/random/rand-internal.h
+++ b/random/rand-internal.h
@@ -98,7 +98,7 @@ int _gcry_rndunix_gather_random (void (*add) (const void *, size_t,
enum random_origins origin,
size_t length, int level);
-/*-- rndelg.c --*/
+/*-- rndegd.c --*/
int _gcry_rndegd_gather_random (void (*add) (const void *, size_t,
enum random_origins),
enum random_origins origin,
@@ -123,6 +123,12 @@ void _gcry_rndw32ce_gather_random_fast (void (*add)(const void*, size_t,
enum random_origins),
enum random_origins origin );
+/*-- rndjent.c --*/
+size_t _gcry_rndjent_poll (void (*add)(const void*,
+ size_t, enum random_origins),
+ enum random_origins origin,
+ size_t length);
+
/*-- rndhw.c --*/
int _gcry_rndhw_failed_p (void);
void _gcry_rndhw_poll_fast (void (*add)(const void*, size_t,
diff --git a/random/rndjent.c b/random/rndjent.c
new file mode 100644
index 00000000..fa3bb99a
--- /dev/null
+++ b/random/rndjent.c
@@ -0,0 +1,208 @@
+/* rndjent.c - Driver for the jitterentropy module.
+ * Copyright (C) 2017 g10 Code GmbH
+ * Copyright (C) 2017 Bundesamt für Sicherheit in der Informationstechnik
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+
+#include "types.h"
+#include "g10lib.h"
+#include "../cipher/bithelp.h"
+#include "rand-internal.h"
+
+/*
+ * Decide whether we can support jent at compile time.
+ */
+#undef USE_JENT
+#ifdef ENABLE_JENT_SUPPORT
+# if defined (__i386__) || defined(__x86_64__)
+# define USE_JENT 1
+# endif
+#endif /*ENABLE_JENT_SUPPORT*/
+
+
+#ifdef USE_JENT
+
+/* When using the libgcrypt secure memory mechanism, all precautions
+ * are taken to protect our state. If the user disables secmem during
+ * runtime, it is his decision and we thus try not to overrule his
+ * decision for less memory protection. */
+#define JENT_CPU_JITTERENTROPY_SECURE_MEMORY 1
+#define jent_zalloc(n) _gcry_calloc_secure (1, (n))
+
+
+
+/*
+ * Libgcrypt specific platform dependent functions.
+ */
+
+
+static void
+jent_get_nstime(u64 *out)
+{
+ u32 t_eax, t_edx;
+
+ asm volatile (".byte 0x0f,0x31\n\t"
+ : "=a" (t_eax), "=d" (t_edx)
+ );
+ *out = (((u64)t_edx << 32) | t_eax);
+}
+
+
+static GPGRT_INLINE void
+jent_zfree (void *ptr, unsigned int len)
+{
+ if (ptr)
+ {
+ wipememory (ptr, len);
+ _gcry_free (ptr);
+ }
+}
+
+static GPGRT_INLINE int
+jent_fips_enabled(void)
+{
+ return fips_mode();
+}
+
+
+/*
+ * We source include the actual jitter entropy code. Note that the
+ * included code has been slightly changed from the Linux kernel
+ * version for namespace reasons. We define MODULE so that the
+ * EXPORT_SYMBOL macro will not be used.
+ */
+#undef CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT
+/* Uncomment the next line to build with statistics. */
+/* #define CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT 1 */
+
+#undef MODULE
+#define MODULE 1
+
+#ifndef HAVE_STDINT_H
+# error This module needs stdint.h - try ./configure --disable-jent-support
+#endif
+#include "jitterentropy-base.c"
+
+
+/* This is the lock we use to serialize access to this RNG. The extra
+ * integer variable is only used to check the locking state; that is,
+ * it is not meant to be thread-safe but merely as a failsafe feature
+ * to assert proper locking. */
+GPGRT_LOCK_DEFINE (jent_rng_lock);
+static int jent_rng_is_locked;
+
+/* This flag tracks whether the RNG has been initialized - either
+ * with error or with success. Protected by JENT_RNG_LOCK. */
+static int jent_rng_is_initialized;
+
+/* Our collector. The RNG is in a working state if its value is not
+ * NULL. Protected by JENT_RNG_LOCK. */
+struct rand_data *jent_rng_collector;
+
+
+/* Acquire the jent_rng_lock. */
+static void
+lock_rng (void)
+{
+ gpg_err_code_t rc;
+
+ rc = gpgrt_lock_lock (&jent_rng_lock);
+ if (rc)
+ log_fatal ("failed to acquire the Jent RNG lock: %s\n",
+ gpg_strerror (rc));
+ jent_rng_is_locked = 1;
+}
+
+
+/* Release the jent_rng_lock. */
+static void
+unlock_rng (void)
+{
+ gpg_err_code_t rc;
+
+ jent_rng_is_locked = 0;
+ rc = gpgrt_lock_unlock (&jent_rng_lock);
+ if (rc)
+ log_fatal ("failed to release the Jent RNG lock: %s\n",
+ gpg_strerror (rc));
+}
+
+#endif /* USE_JENT */
+
+
+/*
+ * The API used by the high level code.
+ */
+
+/* Read up to LENGTH bytes from a jitter RNG and return the number of
+ * bytes actually read. */
+size_t
+_gcry_rndjent_poll (void (*add)(const void*, size_t, enum random_origins),
+ enum random_origins origin, size_t length)
+{
+ size_t nbytes = 0;
+
+ (void)add;
+ (void)origin;
+
+#ifdef USE_JENT
+ if ((_gcry_get_hw_features () & HWF_INTEL_RDTSC))
+ {
+ lock_rng ();
+
+ if (!jent_rng_is_initialized)
+ {
+ /* Auto-initialize. */
+ jent_rng_is_initialized = 1;
+ jent_entropy_collector_free (jent_rng_collector);
+ jent_rng_collector = NULL;
+ if (!jent_entropy_init ())
+ jent_rng_collector = jent_entropy_collector_alloc (1, 0);
+ }
+
+ if (jent_rng_collector)
+ {
+ /* We have a working JENT. */
+ char buffer[256];
+
+ while (length)
+ {
+ int rc;
+ size_t n = length < sizeof(buffer)? length : sizeof (buffer);
+
+ rc = jent_read_entropy (jent_rng_collector, buffer, n);
+ if (rc < 0)
+ break;
+ (*add) (buffer, rc, origin);
+ length -= rc;
+ nbytes += rc;
+ }
+ }
+
+ unlock_rng ();
+ }
+#endif
+
+ return nbytes;
+}
diff --git a/random/rndlinux.c b/random/rndlinux.c
index d3a144a4..f1548fbf 100644
--- a/random/rndlinux.c
+++ b/random/rndlinux.c
@@ -158,6 +158,19 @@ _gcry_rndlinux_gather_random (void (*add)(const void*, size_t,
if (length > 1)
length -= n_hw;
+ /* When using a blocking random generator try to get some entropy
+ * from the jitter based RNG. In this case we take up to 50% of the
+ * remaining requested bytes. */
+ if (level >= GCRY_VERY_STRONG_RANDOM)
+ {
+ n_hw = _gcry_rndjent_poll (add, origin, length/2);
+ if (n_hw > length/2)
+ n_hw = length/2;
+ if (length > 1)
+ length -= n_hw;
+ }
+
+
/* Open the requested device. The first time a device is to be
opened we fail with a fatal error if the device does not exists.
In case the device has ever been closed, further open requests
@@ -165,7 +178,7 @@ _gcry_rndlinux_gather_random (void (*add)(const void*, size_t,
that we always require the device to be existent but want a more
graceful behaviour if the rarely needed close operation has been
used and the device needs to be re-opened later. */
- if (level >= 2)
+ if (level >= GCRY_VERY_STRONG_RANDOM)
{
if (fd_random == -1)
{
diff --git a/random/rndw32.c b/random/rndw32.c
index 1dec5a7e..7e9ac50e 100644
--- a/random/rndw32.c
+++ b/random/rndw32.c
@@ -584,8 +584,8 @@ slow_gatherer ( void (*add)(const void*, size_t, enum random_origins),
if (hNetAPI32
&& !pNetStatisticsGet (NULL,
- is_workstation ? L"LanmanWorkstation" :
- L"LanmanServer", 0, 0, &lpBuffer))
+ (LPWSTR)(is_workstation ? L"LanmanWorkstation" :
+ L"LanmanServer"), 0, 0, &lpBuffer))
{
if ( debug_me )
log_debug ("rndw32#slow_gatherer: get netstats\n" );
@@ -776,6 +776,7 @@ _gcry_rndw32_gather_random (void (*add)(const void*, size_t,
size_t length, int level )
{
static int is_initialized;
+ size_t n;
if (!level)
return 0;
@@ -808,6 +809,13 @@ _gcry_rndw32_gather_random (void (*add)(const void*, size_t,
slow_gatherer (add, origin);
+ /* Round requested LENGTH up to full 32 bytes. */
+ n = _gcry_rndjent_poll (add, origin, ((length + 31) / 32) * 32);
+
+ if (debug_me)
+ log_debug ("rndw32#gather_random: jent contributed extra %u bytes\n",
+ (unsigned int)n);
+
return 0;
}