summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2017-06-23 09:11:47 +0200
committerWerner Koch <wk@gnupg.org>2017-06-23 09:11:47 +0200
commit8dfae89ecd3e9ae0967586cb38d12ef9111fc7cd (patch)
treead08019807856b3734afa1d77323d679c2d9d95c
parent27148e60ba15b0cb73b47a75c688fcb48a1a3444 (diff)
downloadlibgcrypt-8dfae89ecd3e9ae0967586cb38d12ef9111fc7cd.tar.gz
random: Update jitterentropy to 2.1.0.
* random/rndjent.c (jent_get_nstime, jent_zfree) (jent_fips_enabled, jent_zalloc): Move functions and macros to ... * random/jitterentropy-base-user.h: this file. That files was not used before. * random/Makefile.am (EXTRA_librandom_la_SOURCES): Add jitterentropy-base-user. * random/jitterentropy-base.c: Update to version 2.1.0. * random/jitterentropy.h: Ditto. -- The files jitterentropy-base.c and jitterentropy.h are are now verbatim copies of the upstream source using a private copy received prior to a push to the upstream repo. Though, 3 white spaces issues were fixed. Signed-off-by: Werner Koch <wk@gnupg.org>
-rw-r--r--random/Makefile.am2
-rw-r--r--random/jitterentropy-base-user.h119
-rw-r--r--random/jitterentropy-base.c1019
-rw-r--r--random/jitterentropy.h157
-rw-r--r--random/rndjent.c203
5 files changed, 711 insertions, 789 deletions
diff --git a/random/Makefile.am b/random/Makefile.am
index aaf205ee..a3c5dd59 100644
--- a/random/Makefile.am
+++ b/random/Makefile.am
@@ -50,7 +50,7 @@ rndegd.c \
rndunix.c \
rndw32.c \
rndw32ce.c \
-jitterentropy-base.c jitterentropy.h
+jitterentropy-base.c jitterentropy.h jitterentropy-base-user.c
# The rndjent module needs to be compiled without optimization. */
diff --git a/random/jitterentropy-base-user.h b/random/jitterentropy-base-user.h
index 2aecf3b4..75dd7681 100644
--- a/random/jitterentropy-base-user.h
+++ b/random/jitterentropy-base-user.h
@@ -39,65 +39,96 @@
* DAMAGE.
*/
-#ifndef _JITTERENTROPY_BASE_X86_H
-#define _JITTERENTROPY_BASE_X86_H
+#ifndef GCRYPT_JITTERENTROPY_BASE_USER_H
+#define GCRYPT_JITTERENTROPY_BASE_USER_H
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
+/*
+ * This is Libgcrypt specific platform dependent code. We use a
+ * separate file because jitterentropy.h expects such a file.
+ */
-#include <config.h>
-#include "g10lib.h"
+#ifndef USE_JENT
+# error This file expects to be included from rndjent.c (via jitterentropy.h)
+#endif
+#ifndef HAVE_STDINT_H
+# error This module needs stdint.h - try ./configure --disable-jent-support
+#endif
-typedef uint64_t __u64;
-#define RdTSC __asm _emit 0x0f __asm _emit 0x31
+/* 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))
-static void jent_get_nstime(__u64 *out)
-{
- __u64 ret = 0;
- _asm {
- RdTSC
- mov DWORD PTR ret, eax
- mov DWORD PTR[ret + 4], edx
- }
- *out = ret;
-}
-static inline void *jent_zalloc(size_t len)
+static void
+jent_get_nstime(u64 *out)
{
- void *tmp = NULL;
-
- /* 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 CONFIG_CRYPTO_CPU_JITTERENTROPY_SECURE_MEMORY
- tmp = gcry_xmalloc_secure(len);
- if(NULL != tmp)
- memset(tmp, 0, len);
- return tmp;
-}
+#if USE_JENT == JENT_USES_RDTSC
-static inline void jent_zfree(void *ptr, unsigned int len)
-{
- memset(ptr, 0, len);
- gcry_free(ptr);
+ 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);
+
+#elif USE_JENT == JENT_USES_GETTIME
+
+ struct timespec tv;
+ u64 tmp;
+
+ /* On Linux we could use CLOCK_MONOTONIC(_RAW), but with
+ * CLOCK_REALTIME we get some nice extra entropy once in a while
+ * from the NTP actions that we want to use as well... though, we do
+ * not rely on that extra little entropy. */
+ if (!clock_gettime (CLOCK_REALTIME, &tv))
+ {
+ tmp = time.tv_sec;
+ tmp = tmp << 32;
+ tmp = tmp | time.tv_nsec;
+ }
+ else
+ tmp = 0;
+ *out = tmp;
+
+#elif USE_JENT == JENT_USES_READ_REAL_TIME
+
+ /* clock_gettime() on AIX returns a timer value that increments in
+ * steps of 1000. */
+ u64 tmp = 0;
+
+ timebasestruct_t aixtime;
+ read_real_time (&aixtime, TIMEBASE_SZ);
+ tmp = aixtime.tb_high;
+ tmp = tmp << 32;
+ tmp = tmp | aixtime.tb_low;
+ *out = tmp;
+
+#else
+# error No clock available in jent_get_nstime
+#endif
}
-static inline int jent_fips_enabled(void)
+
+static GPGRT_INLINE void
+jent_zfree (void *ptr, unsigned int len)
{
- return fips_mode();
+ if (ptr)
+ {
+ wipememory (ptr, len);
+ _gcry_free (ptr);
+ }
}
-/* --- helpers needed in user space -- */
-
-/* note: these helper functions are shamelessly stolen from the kernel :-) */
-static inline __u64 rol64(__u64 word, unsigned int shift)
+static GPGRT_INLINE int
+jent_fips_enabled(void)
{
- return (word << shift) | (word >> (64 - shift));
+ return fips_mode();
}
-#endif /* _JITTERENTROPY_BASE_X86_H */
+#endif /* GCRYPT_JITTERENTROPY_BASE_USER_H */
diff --git a/random/jitterentropy-base.c b/random/jitterentropy-base.c
index 2701e90e..4f3de10c 100644
--- a/random/jitterentropy-base.c
+++ b/random/jitterentropy-base.c
@@ -1,7 +1,7 @@
/*
* Non-physical true random number generator based on timing jitter.
*
- * Copyright Stephan Mueller <smueller@chronox.de>, 2014
+ * Copyright Stephan Mueller <smueller@chronox.de>, 2014 - 2017
*
* Design
* ======
@@ -49,6 +49,9 @@
* DAMAGE.
*/
+#undef _FORTIFY_SOURCE
+#pragma GCC optimize ("O0")
+
#include "jitterentropy.h"
#ifndef CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT
@@ -59,14 +62,14 @@
#endif
#define MAJVERSION 2 /* API / ABI incompatible changes, functional changes that
- * require consumer to be updated (as long as this number
- * is zero, the API is not considered stable and can
- * change without a bump of the major version) */
-#define MINVERSION 0 /* API compatible, ABI may change, functional
- * enhancements only, consumer can be left unchanged if
- * enhancements are not considered */
+ * require consumer to be updated (as long as this number
+ * is zero, the API is not considered stable and can
+ * change without a bump of the major version) */
+#define MINVERSION 1 /* API compatible, ABI may change, functional
+ * enhancements only, consumer can be left unchanged if
+ * enhancements are not considered */
#define PATCHLEVEL 0 /* API / ABI compatible, no functional changes, no
- * enhancements, bug fixes only */
+ * enhancements, bug fixes only */
/**
* jent_version() - Return machine-usable version number of jent library
@@ -81,15 +84,16 @@
*
* Return: Version number of kcapi library
*/
-static unsigned int jent_version(void)
+JENT_PRIVATE_STATIC
+unsigned int jent_version(void)
{
- unsigned int version = 0;
+ unsigned int version = 0;
- version = MAJVERSION * 1000000;
- version += MINVERSION * 10000;
- version += PATCHLEVEL * 100;
+ version = MAJVERSION * 1000000;
+ version += MINVERSION * 10000;
+ version += PATCHLEVEL * 100;
- return version;
+ return version;
}
/**
@@ -100,39 +104,39 @@ static unsigned int jent_version(void)
* @ec entropy collector struct -- may be NULL
* @bits is the number of low bits of the timer to consider
* @min is the number of bits we shift the timer value to the right at
- * the end to make sure we have a guaranteed minimum value
+ * the end to make sure we have a guaranteed minimum value
*
* @return Newly calculated loop counter
*/
-static u64 jent_loop_shuffle(struct rand_data *ec,
- unsigned int bits, unsigned int min)
+static uint64_t jent_loop_shuffle(struct rand_data *ec,
+ unsigned int bits, unsigned int min)
{
- u64 time = 0;
- u64 shuffle = 0;
- unsigned int i = 0;
- unsigned int mask = (1<<bits) - 1;
-
- jent_get_nstime(&time);
- /*
- * Mix the current state of the random number into the shuffle
- * calculation to balance that shuffle a bit more.
- */
- if (ec)
- time ^= ec->data;
- /*
- * We fold the time value as much as possible to ensure that as many
- * bits of the time stamp are included as possible.
- */
- for (i = 0; (DATA_SIZE_BITS / bits) > i; i++) {
- shuffle ^= time & mask;
- time = time >> bits;
- }
-
- /*
- * We add a lower boundary value to ensure we have a minimum
- * RNG loop count.
- */
- return (shuffle + (1<<min));
+ uint64_t time = 0;
+ uint64_t shuffle = 0;
+ unsigned int i = 0;
+ unsigned int mask = (1<<bits) - 1;
+
+ jent_get_nstime(&time);
+ /*
+ * Mix the current state of the random number into the shuffle
+ * calculation to balance that shuffle a bit more.
+ */
+ if (ec)
+ time ^= ec->data;
+ /*
+ * We fold the time value as much as possible to ensure that as many
+ * bits of the time stamp are included as possible.
+ */
+ for (i = 0; (DATA_SIZE_BITS / bits) > i; i++) {
+ shuffle ^= time & mask;
+ time = time >> bits;
+ }
+
+ /*
+ * We add a lower boundary value to ensure we have a minimum
+ * RNG loop count.
+ */
+ return (shuffle + (1<<min));
}
/***************************************************************************
@@ -141,7 +145,7 @@ static u64 jent_loop_shuffle(struct rand_data *ec,
/**
* CPU Jitter noise source -- this is the noise source based on the CPU
- * execution time jitter
+ * execution time jitter
*
* This function injects the individual bits of the time value into the
* entropy pool using an LFSR.
@@ -157,65 +161,65 @@ static u64 jent_loop_shuffle(struct rand_data *ec,
* @ec entropy collector struct -- may be NULL
* @time time stamp to be injected
* @loop_cnt if a value not equal to 0 is set, use the given value as number of
- * loops to perform the folding
+ * loops to perform the folding
*
* Output:
* updated ec->data
*
* @return Number of loops the folding operation is performed
*/
-static u64 jent_lfsr_time(struct rand_data *ec, u64 time,
- u64 loop_cnt)
+static uint64_t jent_lfsr_time(struct rand_data *ec, uint64_t time,
+ uint64_t loop_cnt)
{
- unsigned int i;
- u64 j = 0;
- u64 new = 0;
+ unsigned int i;
+ uint64_t j = 0;
+ uint64_t new = 0;
#define MAX_FOLD_LOOP_BIT 4
#define MIN_FOLD_LOOP_BIT 0
- u64 fold_loop_cnt =
- jent_loop_shuffle(ec, MAX_FOLD_LOOP_BIT, MIN_FOLD_LOOP_BIT);
-
- /*
- * testing purposes -- allow test app to set the counter, not
- * needed during runtime
- */
- if (loop_cnt)
- fold_loop_cnt = loop_cnt;
- for (j = 0; j < fold_loop_cnt; j++) {
- new = ec->data;
- for (i = 1; (DATA_SIZE_BITS) >= i; i++) {
- u64 tmp = time << (DATA_SIZE_BITS - i);
-
- tmp = tmp >> (DATA_SIZE_BITS - 1);
-
- /*
- * Fibonacci LSFR with polynomial of
- * x^64 + x^61 + x^56 + x^31 + x^28 + x^23 + 1 which is
- * primitive according to
- * http://poincare.matf.bg.ac.rs/~ezivkovm/publications/primpol1.pdf
- * (the shift values are the polynomial values minus one
- * due to counting bits from 0 to 63). As the current
- * position is always the LSB, the polynomial only needs
- * to shift data in from the left without wrap.
- */
- new ^= tmp;
- new ^= ((new >> 63) & 1);
- new ^= ((new >> 60) & 1);
- new ^= ((new >> 55) & 1);
- new ^= ((new >> 30) & 1);
- new ^= ((new >> 27) & 1);
- new ^= ((new >> 22) & 1);
- new = rol64(new, 1);
- }
- }
- ec->data = new;
-
- return fold_loop_cnt;
+ uint64_t fold_loop_cnt =
+ jent_loop_shuffle(ec, MAX_FOLD_LOOP_BIT, MIN_FOLD_LOOP_BIT);
+
+ /*
+ * testing purposes -- allow test app to set the counter, not
+ * needed during runtime
+ */
+ if (loop_cnt)
+ fold_loop_cnt = loop_cnt;
+ for (j = 0; j < fold_loop_cnt; j++) {
+ new = ec->data;
+ for (i = 1; (DATA_SIZE_BITS) >= i; i++) {
+ uint64_t tmp = time << (DATA_SIZE_BITS - i);
+
+ tmp = tmp >> (DATA_SIZE_BITS - 1);
+
+ /*
+ * Fibonacci LSFR with polynomial of
+ * x^64 + x^61 + x^56 + x^31 + x^28 + x^23 + 1 which is
+ * primitive according to
+ * http://poincare.matf.bg.ac.rs/~ezivkovm/publications/primpol1.pdf
+ * (the shift values are the polynomial values minus one
+ * due to counting bits from 0 to 63). As the current
+ * position is always the LSB, the polynomial only needs
+ * to shift data in from the left without wrap.
+ */
+ new ^= tmp;
+ new ^= ((new >> 63) & 1);
+ new ^= ((new >> 60) & 1);
+ new ^= ((new >> 55) & 1);
+ new ^= ((new >> 30) & 1);
+ new ^= ((new >> 27) & 1);
+ new ^= ((new >> 22) & 1);
+ new = rol64(new, 1);
+ }
+ }
+ ec->data = new;
+
+ return fold_loop_cnt;
}
/**
* Memory Access noise source -- this is a noise source based on variations in
- * memory access times
+ * memory access times
*
* This function performs memory accesses which will add to the timing
* variations due to an unknown amount of CPU wait states that need to be
@@ -236,47 +240,47 @@ static u64 jent_lfsr_time(struct rand_data *ec, u64 time,
* the reference to the memory block to be accessed is NULL, this noise
* source is disabled
* @loop_cnt if a value not equal to 0 is set, use the given value as number of
- * loops to perform the folding
+ * loops to perform the folding
*
* @return Number of memory access operations
*/
-static unsigned int jent_memaccess(struct rand_data *ec, u64 loop_cnt)
+static unsigned int jent_memaccess(struct rand_data *ec, uint64_t loop_cnt)
{
- unsigned int wrap = 0;
- u64 i = 0;
+ unsigned int wrap = 0;
+ uint64_t i = 0;
#define MAX_ACC_LOOP_BIT 7
#define MIN_ACC_LOOP_BIT 0
- u64 acc_loop_cnt =
- jent_loop_shuffle(ec, MAX_ACC_LOOP_BIT, MIN_ACC_LOOP_BIT);
-
- if (NULL == ec || NULL == ec->mem)
- return 0;
- wrap = ec->memblocksize * ec->memblocks;
-
- /*
- * testing purposes -- allow test app to set the counter, not
- * needed during runtime
- */
- if (loop_cnt)
- acc_loop_cnt = loop_cnt;
-
- for (i = 0; i < (ec->memaccessloops + acc_loop_cnt); i++) {
- unsigned char *tmpval = ec->mem + ec->memlocation;
- /*
- * memory access: just add 1 to one byte,
- * wrap at 255 -- memory access implies read
- * from and write to memory location
- */
- *tmpval = (*tmpval + 1) & 0xff;
- /*
- * Addition of memblocksize - 1 to pointer
- * with wrap around logic to ensure that every
- * memory location is hit evenly
- */
- ec->memlocation = ec->memlocation + ec->memblocksize - 1;
- ec->memlocation = ec->memlocation % wrap;
- }
- return i;
+ uint64_t acc_loop_cnt =
+ jent_loop_shuffle(ec, MAX_ACC_LOOP_BIT, MIN_ACC_LOOP_BIT);
+
+ if (NULL == ec || NULL == ec->mem)
+ return 0;
+ wrap = ec->memblocksize * ec->memblocks;
+
+ /*
+ * testing purposes -- allow test app to set the counter, not
+ * needed during runtime
+ */
+ if (loop_cnt)
+ acc_loop_cnt = loop_cnt;
+
+ for (i = 0; i < (ec->memaccessloops + acc_loop_cnt); i++) {
+ unsigned char *tmpval = ec->mem + ec->memlocation;
+ /*
+ * memory access: just add 1 to one byte,
+ * wrap at 255 -- memory access implies read
+ * from and write to memory location
+ */
+ *tmpval = (*tmpval + 1) & 0xff;
+ /*
+ * Addition of memblocksize - 1 to pointer
+ * with wrap around logic to ensure that every
+ * memory location is hit evenly
+ */
+ ec->memlocation = ec->memlocation + ec->memblocksize - 1;
+ ec->memlocation = ec->memlocation % wrap;
+ }
+ return i;
}
/***************************************************************************
@@ -285,9 +289,9 @@ static unsigned int jent_memaccess(struct rand_data *ec, u64 loop_cnt)
/**
* Stuck test by checking the:
- * 1st derivation of the jitter measurement (time delta)
- * 2nd derivation of the jitter measurement (delta of time deltas)
- * 3rd derivation of the jitter measurement (delta of delta of time deltas)
+ * 1st derivation of the jitter measurement (time delta)
+ * 2nd derivation of the jitter measurement (delta of time deltas)
+ * 3rd derivation of the jitter measurement (delta of delta of time deltas)
*
* All values must always be non-zero.
*
@@ -296,21 +300,21 @@ static unsigned int jent_memaccess(struct rand_data *ec, u64 loop_cnt)
* @current_delta Jitter time delta
*
* @return
- * 0 jitter measurement not stuck (good bit)
- * 1 jitter measurement stuck (reject bit)
+ * 0 jitter measurement not stuck (good bit)
+ * 1 jitter measurement stuck (reject bit)
*/
-static int jent_stuck(struct rand_data *ec, u64 current_delta)
+static int jent_stuck(struct rand_data *ec, uint64_t current_delta)
{
- int64_t delta2 = ec->last_delta - current_delta;
- int64_t delta3 = delta2 - ec->last_delta2;
+ int64_t delta2 = ec->last_delta - current_delta;
+ int64_t delta3 = delta2 - ec->last_delta2;
- ec->last_delta = current_delta;
- ec->last_delta2 = delta2;
+ ec->last_delta = current_delta;
+ ec->last_delta2 = delta2;
- if (!current_delta || !delta2 || !delta3)
- return 1;
+ if (!current_delta || !delta2 || !delta3)
+ return 1;
- return 0;
+ return 0;
}
/**
@@ -319,8 +323,8 @@ static int jent_stuck(struct rand_data *ec, u64 current_delta)
* entropy pool.
*
* WARNING: ensure that ->prev_time is primed before using the output
- * of this function! This can be done by calling this function
- * and not using its result.
+ * of this function! This can be done by calling this function
+ * and not using its result.
*
* Input:
* @entropy_collector Reference to entropy collector
@@ -329,40 +333,40 @@ static int jent_stuck(struct rand_data *ec, u64 current_delta)
*/
static int jent_measure_jitter(struct rand_data *ec)
{
- u64 time = 0;
- u64 current_delta = 0;
- int stuck;
-
- /* Invoke one noise source before time measurement to add variations */
- jent_memaccess(ec, 0);
-
- /*
- * Get time stamp and calculate time delta to previous
- * invocation to measure the timing variations
- */
- jent_get_nstime(&time);
- current_delta = time - ec->prev_time;
- ec->prev_time = time;
-
- /* Now call the next noise sources which also injects the data */
- jent_lfsr_time(ec, current_delta, 0);
-
- /* Check whether we have a stuck measurement. */
- stuck = jent_stuck(ec, current_delta);
-
- /*
- * Rotate the data buffer by a prime number (any odd number would
- * do) to ensure that every bit position of the input time stamp
- * has an even chance of being merged with a bit position in the
- * entropy pool. We do not use one here as the adjacent bits in
- * successive time deltas may have some form of dependency. The
- * chosen value of 7 implies that the low 7 bits of the next
- * time delta value is concatenated with the current time delta.
- */
- if (!stuck)
- ec->data = rol64(ec->data, 7);
-
- return stuck;
+ uint64_t time = 0;
+ uint64_t current_delta = 0;
+ int stuck;
+
+ /* Invoke one noise source before time measurement to add variations */
+ jent_memaccess(ec, 0);
+
+ /*
+ * Get time stamp and calculate time delta to previous
+ * invocation to measure the timing variations
+ */
+ jent_get_nstime(&time);
+ current_delta = time - ec->prev_time;
+ ec->prev_time = time;
+
+ /* Now call the next noise sources which also injects the data */
+ jent_lfsr_time(ec, current_delta, 0);
+
+ /* Check whether we have a stuck measurement. */
+ stuck = jent_stuck(ec, current_delta);
+
+ /*
+ * Rotate the data buffer by a prime number (any odd number would
+ * do) to ensure that every bit position of the input time stamp
+ * has an even chance of being merged with a bit position in the
+ * entropy pool. We do not use one here as the adjacent bits in
+ * successive time deltas may have some form of dependency. The
+ * chosen value of 7 implies that the low 7 bits of the next
+ * time delta value is concatenated with the current time delta.
+ */
+ if (!stuck)
+ ec->data = rol64(ec->data, 7);
+
+ return stuck;
}
/**
@@ -384,54 +388,54 @@ static int jent_measure_jitter(struct rand_data *ec)
*/
static void jent_stir_pool(struct rand_data *entropy_collector)
{
- /*
- * to shut up GCC on 32 bit, we have to initialize the 64 variable
- * with two 32 bit variables
- */
- union c {
- u64 u64;
- u32 u32[2];
- };
- /*
- * This constant is derived from the first two 32 bit initialization
- * vectors of SHA-1 as defined in FIPS 180-4 section 5.3.1
- */
- union c constant;
- /*
- * The start value of the mixer variable is derived from the third
- * and fourth 32 bit initialization vector of SHA-1 as defined in
- * FIPS 180-4 section 5.3.1
- */
- union c mixer;
- unsigned int i = 0;
-
- /* Ensure that the function implements a constant time operation. */
- union c throw_away;
-
- /*
- * Store the SHA-1 constants in reverse order to make up the 64 bit
- * value -- this applies to a little endian system, on a big endian
- * system, it reverses as expected. But this really does not matter
- * as we do not rely on the specific numbers. We just pick the SHA-1
- * constants as they have a good mix of bit set and unset.
- */
- constant.u32[1] = 0x67452301;
- constant.u32[0] = 0xefcdab89;
- mixer.u32[1] = 0x98badcfe;
- mixer.u32[0] = 0x10325476;
-
- for (i = 0; i < DATA_SIZE_BITS; i++) {
- /*
- * get the i-th bit of the input random number and only XOR
- * the constant into the mixer value when that bit is set
- */
- if ((entropy_collector->data >> i) & 1)
- mixer.u64 ^= constant.u64;
- else
- throw_away.u64 ^= constant.u64;
- mixer.u64 = rol64(mixer.u64, 1);
- }
- entropy_collector->data ^= mixer.u64;
+ /*
+ * to shut up GCC on 32 bit, we have to initialize the 64 variable
+ * with two 32 bit variables
+ */
+ union c {
+ uint64_t uint64;
+ uint32_t uint32[2];
+ };
+ /*
+ * This constant is derived from the first two 32 bit initialization
+ * vectors of SHA-1 as defined in FIPS 180-4 section 5.3.1
+ */
+ union c constant;
+ /*
+ * The start value of the mixer variable is derived from the third
+ * and fourth 32 bit initialization vector of SHA-1 as defined in
+ * FIPS 180-4 section 5.3.1
+ */
+ union c mixer;
+ unsigned int i = 0;
+
+ /* Ensure that the function implements a constant time operation. */
+ union c throw_away;
+
+ /*
+ * Store the SHA-1 constants in reverse order to make up the 64 bit
+ * value -- this applies to a little endian system, on a big endian
+ * system, it reverses as expected. But this really does not matter
+ * as we do not rely on the specific numbers. We just pick the SHA-1
+ * constants as they have a good mix of bit set and unset.
+ */
+ constant.uint32[1] = 0x67452301;
+ constant.uint32[0] = 0xefcdab89;
+ mixer.uint32[1] = 0x98badcfe;
+ mixer.uint32[0] = 0x10325476;
+
+ for (i = 0; i < DATA_SIZE_BITS; i++) {
+ /*
+ * get the i-th bit of the input random number and only XOR
+ * the constant into the mixer value when that bit is set
+ */
+ if ((entropy_collector->data >> i) & 1)
+ mixer.uint64 ^= constant.uint64;
+ else
+ throw_away.uint64 ^= constant.uint64;
+ mixer.uint64 = rol64(mixer.uint64, 1);
+ }
+ entropy_collector->data ^= mixer.uint64;
}
/**
@@ -443,30 +447,60 @@ static void jent_stir_pool(struct rand_data *entropy_collector)
*/
static void jent_gen_entropy(struct rand_data *ec)
{
- unsigned int k = 0;
-
- /* priming of the ->prev_time value */
- jent_measure_jitter(ec);
-
- while (1) {
- u64 prev_data = ec->data;
-
- /* If a stuck measurement is received, repeat measurement */
- if (jent_measure_jitter(ec))
- continue;
-
- /* statistics testing only */
- jent_bit_count(ec, prev_data);
-
- /*
- * We multiply the loop value with ->osr to obtain the
- * oversampling rate requested by the caller
- */
- if (++k >= (DATA_SIZE_BITS * ec->osr))
- break;
- }
- if (ec->stir)
- jent_stir_pool(ec);
+ unsigned int k = 0;
+
+ /* priming of the ->prev_time value */
+ jent_measure_jitter(ec);
+
+ while (1) {
+ /* If a stuck measurement is received, repeat measurement */
+ if (jent_measure_jitter(ec))
+ continue;
+
+ /*
+ * We multiply the loop value with ->osr to obtain the
+ * oversampling rate requested by the caller
+ */
+ if (++k >= (DATA_SIZE_BITS * ec->osr))
+ break;
+ }
+ if (ec->stir)
+ jent_stir_pool(ec);
+}
+
+/**
+ * The continuous test required by FIPS 140-2 -- the function automatically
+ * primes the test if needed.
+ *
+ * Return:
+ * 0 if FIPS test passed
+ * < 0 if FIPS test failed
+ */
+static int jent_fips_test(struct rand_data *ec)
+{
+ if (ec->fips_enabled == -1)
+ return 0;
+
+ if (ec->fips_enabled == 0) {
+ if (!jent_fips_enabled()) {
+ ec->fips_enabled = -1;
+ return 0;
+ } else
+ ec->fips_enabled = 1;
+ }
+
+ /* prime the FIPS test */
+ if (!ec->old_data) {
+ ec->old_data = ec->data;
+ jent_gen_entropy(ec);
+ }
+
+ if (ec->data == ec->old_data)
+ return -1;
+
+ ec->old_data = ec->data;
+
+ return 0;
}
/**
@@ -489,241 +523,246 @@ static void jent_gen_entropy(struct rand_data *ec)
* @return number of bytes returned when request is fulfilled or an error
*
* The following error codes can occur:
- * -1 entropy_collector is NULL
+ * -1 entropy_collector is NULL
+ * -2 FIPS test failed
*/
-static int jent_read_entropy(struct rand_data *ec, char *data, size_t len)
+JENT_PRIVATE_STATIC
+ssize_t jent_read_entropy(struct rand_data *ec, char *data, size_t len)
{
- char *p = data;
- size_t orig_len = len;
-
- if (NULL == ec)
- return -1;
-
- while (0 < len) {
- size_t tocopy;
- jent_gen_entropy(ec);
- if ((DATA_SIZE_BITS / 8) < len)
- tocopy = (DATA_SIZE_BITS / 8);
- else
- tocopy = len;
- memcpy(p, &ec->data, tocopy);
-
- len -= tocopy;
- p += tocopy;
- }
-
- /*
- * To be on the safe side, we generate one more round of entropy
- * which we do not give out to the caller. That round shall ensure
- * that in case the calling application crashes, memory dumps, pages
- * out, or due to the CPU Jitter RNG lingering in memory for long
- * time without being moved and an attacker cracks the application,
- * all he reads in the entropy pool is a value that is NEVER EVER
- * being used for anything. Thus, he does NOT see the previous value
- * that was returned to the caller for cryptographic purposes.
- */
- /*
- * If we use secured memory, do not use that precaution as the secure
- * memory protects the entropy pool. Moreover, note that using this
- * call reduces the speed of the RNG by up to half
- */
+ char *p = data;
+ size_t orig_len = len;
+
+ if (NULL == ec)
+ return -1;
+
+ while (0 < len) {
+ size_t tocopy;
+
+ jent_gen_entropy(ec);
+ if (jent_fips_test(ec))
+ return -2;
+
+ if ((DATA_SIZE_BITS / 8) < len)
+ tocopy = (DATA_SIZE_BITS / 8);
+ else
+ tocopy = len;
+ memcpy(p, &ec->data, tocopy);
+
+ len -= tocopy;
+ p += tocopy;
+ }
+
+ /*
+ * To be on the safe side, we generate one more round of entropy
+ * which we do not give out to the caller. That round shall ensure
+ * that in case the calling application crashes, memory dumps, pages
+ * out, or due to the CPU Jitter RNG lingering in memory for long
+ * time without being moved and an attacker cracks the application,
+ * all he reads in the entropy pool is a value that is NEVER EVER
+ * being used for anything. Thus, he does NOT see the previous value
+ * that was returned to the caller for cryptographic purposes.
+ */
+ /*
+ * If we use secured memory, do not use that precaution as the secure
+ * memory protects the entropy pool. Moreover, note that using this
+ * call reduces the speed of the RNG by up to half
+ */
#ifndef CONFIG_CRYPTO_CPU_JITTERENTROPY_SECURE_MEMORY
- jent_gen_entropy(ec);
+ jent_gen_entropy(ec);
#endif
- return orig_len;
+ return orig_len;
}
-#if defined(__KERNEL__) && !defined(MODULE)
-EXPORT_SYMBOL(jent_read_entropy);
-#endif
/***************************************************************************
* Initialization logic
***************************************************************************/
-static struct rand_data *jent_entropy_collector_alloc(unsigned int osr,
- unsigned int flags)
+JENT_PRIVATE_STATIC
+struct rand_data *jent_entropy_collector_alloc(unsigned int osr,
+ unsigned int flags)
{
- struct rand_data *entropy_collector;
-
- entropy_collector = jent_zalloc(sizeof(struct rand_data));
- if (NULL == entropy_collector)
- return NULL;
-
- if (!(flags & JENT_DISABLE_MEMORY_ACCESS)) {
- /* Allocate memory for adding variations based on memory
- * access
- */
- entropy_collector->mem =
- (unsigned char *)jent_zalloc(JENT_MEMORY_SIZE);
- if (NULL == entropy_collector->mem) {
- jent_zfree(entropy_collector, sizeof(struct rand_data));
- return NULL;
- }
- entropy_collector->memblocksize = JENT_MEMORY_BLOCKSIZE;
- entropy_collector->memblocks = JENT_MEMORY_BLOCKS;
- entropy_collector->memaccessloops = JENT_MEMORY_ACCESSLOOPS;
- }
-
- /* verify and set the oversampling rate */
- if (0 == osr)
- osr = 1; /* minimum sampling rate is 1 */
- entropy_collector->osr = osr;
-
- entropy_collector->stir = 1;
- if (flags & JENT_DISABLE_STIR)
- entropy_collector->stir = 0;
- if (flags & JENT_DISABLE_UNBIAS)
- entropy_collector->disable_unbias = 1;
-
- /* fill the data pad with non-zero values */
- jent_gen_entropy(entropy_collector);
-
- return entropy_collector;
+ struct rand_data *entropy_collector;
+
+ entropy_collector = jent_zalloc(sizeof(struct rand_data));
+ if (NULL == entropy_collector)
+ return NULL;
+
+ if (!(flags & JENT_DISABLE_MEMORY_ACCESS)) {
+ /* Allocate memory for adding variations based on memory
+ * access
+ */
+ entropy_collector->mem =
+ (unsigned char *)jent_zalloc(JENT_MEMORY_SIZE);
+ if (NULL == entropy_collector->mem) {
+ jent_zfree(entropy_collector, sizeof(struct rand_data));
+ return NULL;
+ }
+ entropy_collector->memblocksize = JENT_MEMORY_BLOCKSIZE;
+ entropy_collector->memblocks = JENT_MEMORY_BLOCKS;
+ entropy_collector->memaccessloops = JENT_MEMORY_ACCESSLOOPS;
+ }
+
+ /* verify and set the oversampling rate */
+ if (0 == osr)
+ osr = 1; /* minimum sampling rate is 1 */
+ entropy_collector->osr = osr;
+
+ entropy_collector->stir = 1;
+ if (flags & JENT_DISABLE_STIR)
+ entropy_collector->stir = 0;
+ if (flags & JENT_DISABLE_UNBIAS)
+ entropy_collector->disable_unbias = 1;
+
+ /* fill the data pad with non-zero values */
+ jent_gen_entropy(entropy_collector);
+
+ return entropy_collector;
}
-#if defined(__KERNEL__) && !defined(MODULE)
-EXPORT_SYMBOL(jent_entropy_collector_alloc);
-#endif
-static void jent_entropy_collector_free(struct rand_data *entropy_collector)
+JENT_PRIVATE_STATIC
+void jent_entropy_collector_free(struct rand_data *entropy_collector)
{
- if (NULL != entropy_collector) {
- if (NULL != entropy_collector->mem) {
- jent_zfree(entropy_collector->mem, JENT_MEMORY_SIZE);
- entropy_collector->mem = NULL;
- }
- jent_zfree(entropy_collector, sizeof(struct rand_data));
- }
+ if (NULL != entropy_collector) {
+ if (NULL != entropy_collector->mem) {
+ jent_zfree(entropy_collector->mem, JENT_MEMORY_SIZE);
+ entropy_collector->mem = NULL;
+ }
+ jent_zfree(entropy_collector, sizeof(struct rand_data));
+ }
}
-#if defined(__KERNEL__) && !defined(MODULE)
-EXPORT_SYMBOL(jent_entropy_collector_free);
-#endif
-static int jent_entropy_init(void)
+JENT_PRIVATE_STATIC
+int jent_entropy_init(void)
{
- int i;
- u64 delta_sum = 0;
- u64 old_delta = 0;
- int time_backwards = 0;
- int count_var = 0;
- int count_mod = 0;
- struct rand_data ec;
-
- /* We could perform statistical tests here, but the problem is
- * that we only have a few loop counts to do testing. These
- * loop counts may show some slight skew and we produce
- * false positives.
- *
- * Moreover, only old systems show potentially problematic
- * jitter entropy that could potentially be caught here. But
- * the RNG is intended for hardware that is available or widely
- * used, but not old systems that are long out of favor. Thus,
- * no statistical tests.
- */
-
- /*
- * We could add a check for system capabilities such as clock_getres or
- * check for CONFIG_X86_TSC, but it does not make much sense as the
- * following sanity checks verify that we have a high-resolution
- * timer.
- */
- /*
- * TESTLOOPCOUNT needs some loops to identify edge systems. 100 is
- * definitely too little.
- */
+ int i;
+ uint64_t delta_sum = 0;
+ uint64_t old_delta = 0;
+ int time_backwards = 0;
+ int count_mod = 0;
+ int count_stuck = 0;
+ struct rand_data ec;
+
+ /* We could perform statistical tests here, but the problem is
+ * that we only have a few loop counts to do testing. These
+ * loop counts may show some slight skew and we produce
+ * false positives.
+ *
+ * Moreover, only old systems show potentially problematic
+ * jitter entropy that could potentially be caught here. But
+ * the RNG is intended for hardware that is available or widely
+ * used, but not old systems that are long out of favor. Thus,
+ * no statistical tests.
+ */
+
+ /*
+ * We could add a check for system capabilities such as clock_getres or
+ * check for CONFIG_X86_TSC, but it does not make much sense as the
+ * following sanity checks verify that we have a high-resolution
+ * timer.
+ */
+ /*
+ * TESTLOOPCOUNT needs some loops to identify edge systems. 100 is
+ * definitely too little.
+ */
#define TESTLOOPCOUNT 300
#define CLEARCACHE 100
- for (i = 0; (TESTLOOPCOUNT + CLEARCACHE) > i; i++) {
- u64 time = 0;
- u64 time2 = 0;
- u64 delta = 0;
- unsigned int lowdelta = 0;
-
- jent_get_nstime(&time);
- jent_lfsr_time(&ec, time, 1<<MIN_FOLD_LOOP_BIT);
- jent_get_nstime(&time2);
-
- /* test whether timer works */
- if (!time || !time2)
- return ENOTIME;
- delta = time2 - time;
- /*
- * test whether timer is fine grained enough to provide
- * delta even when called shortly after each other -- this
- * implies that we also have a high resolution timer
- */
- if (!delta)
- return ECOARSETIME;
-
- /*
- * up to here we did not modify any variable that will be
- * evaluated later, but we already performed some work. Thus we
- * already have had an impact on the caches, branch prediction,
- * etc. with the goal to clear it to get the worst case
- * measurements.
- */
- if (CLEARCACHE > i)
- continue;
-
- /* test whether we have an increasing timer */
- if (!(time2 > time))
- time_backwards++;
-
- /* use 32 bit value to ensure compilation on 32 bit arches */
- lowdelta = time2 - time;
- if (!(lowdelta % 100))
- count_mod++;
-
- /*
- * ensure that we have a varying delta timer which is necessary
- * for the calculation of entropy -- perform this check
- * only after the first loop is executed as we need to prime
- * the old_data value
- */
- if (i) {
- if (delta != old_delta)
- count_var++;
- if (delta > old_delta)
- delta_sum += (delta - old_delta);
- else
- delta_sum += (old_delta - delta);
- }
- old_delta = delta;
- }
-
- /*
- * we allow up to three times the time running backwards.
- * CLOCK_REALTIME is affected by adjtime and NTP operations. Thus,
- * if such an operation just happens to interfere with our test, it
- * should not fail. The value of 3 should cover the NTP case being
- * performed during our test run.
- */
- if (3 < time_backwards)
- return ENOMONOTONIC;
- /* Error if the time variances are always identical */
- if (!delta_sum)
- return EVARVAR;
-
- /*
- * Variations of deltas of time must on average be larger
- * than 1 to ensure the entropy estimation
- * implied with 1 is preserved
- */
- if ((delta_sum) <= 1)
- return EMINVARVAR;
-
- /*
- * Ensure that we have variations in the time stamp below 10 for at least
- * 10% of all checks -- on some platforms, the counter increments in
- * multiples of 100, but not always
- */
- if ((TESTLOOPCOUNT/10 * 9) < count_mod)
- return ECOARSETIME;
-
- return 0;
+ for (i = 0; (TESTLOOPCOUNT + CLEARCACHE) > i; i++) {
+ uint64_t time = 0;
+ uint64_t time2 = 0;
+ uint64_t delta = 0;
+ unsigned int lowdelta = 0;
+ int stuck;
+
+ /* Invoke core entropy collection logic */
+ jent_get_nstime(&time);
+ ec.prev_time = time;
+ jent_lfsr_time(&ec, time, 0);
+ jent_get_nstime(&time2);
+
+ /* test whether timer works */
+ if (!time || !time2)
+ return ENOTIME;
+ delta = time2 - time;
+ /*
+ * test whether timer is fine grained enough to provide
+ * delta even when called shortly after each other -- this
+ * implies that we also have a high resolution timer
+ */
+ if (!delta)
+ return ECOARSETIME;
+
+ stuck = jent_stuck(&ec, delta);
+
+ /*
+ * up to here we did not modify any variable that will be
+ * evaluated later, but we already performed some work. Thus we
+ * already have had an impact on the caches, branch prediction,
+ * etc. with the goal to clear it to get the worst case
+ * measurements.
+ */
+ if (CLEARCACHE > i)
+ continue;
+
+ if (stuck)
+ count_stuck++;
+
+ /* test whether we have an increasing timer */
+ if (!(time2 > time))
+ time_backwards++;
+
+ /* use 32 bit value to ensure compilation on 32 bit arches */
+ lowdelta = time2 - time;
+ if (!(lowdelta % 100))
+ count_mod++;
+
+ /*
+ * ensure that we have a varying delta timer which is necessary
+ * for the calculation of entropy -- perform this check
+ * only after the first loop is executed as we need to prime
+ * the old_data value
+ */
+ if (delta > old_delta)
+ delta_sum += (delta - old_delta);
+ else
+ delta_sum += (old_delta - delta);
+ old_delta = delta;
+ }
+
+ /*
+ * we allow up to three times the time running backwards.
+ * CLOCK_REALTIME is affected by adjtime and NTP operations. Thus,
+ * if such an operation just happens to interfere with our test, it
+ * should not fail. The value of 3 should cover the NTP case being
+ * performed during our test run.
+ */
+ if (3 < time_backwards)
+ return ENOMONOTONIC;
+
+ /*
+ * Variations of deltas of time must on average be larger
+ * than 1 to ensure the entropy estimation
+ * implied with 1 is preserved
+ */
+ if ((delta_sum) <= 1)
+ return EMINVARVAR;
+
+ /*
+ * Ensure that we have variations in the time stamp below 10 for at least
+ * 10% of all checks -- on some platforms, the counter increments in
+ * multiples of 100, but not always
+ */
+ if ((TESTLOOPCOUNT/10 * 9) < count_mod)
+ return ECOARSETIME;
+
+ /*
+ * If we have more than 90% stuck results, then this Jitter RNG is
+ * likely to not work well.
+ */
+ if (JENT_STUCK_INIT_THRES(TESTLOOPCOUNT) < count_stuck)
+ return ESTUCK;
+
+ return 0;
}
-#if defined(__KERNEL__) && !defined(MODULE)
-EXPORT_SYMBOL(jent_entropy_init);
-#endif
/***************************************************************************
* Statistical test logic not compiled for regular operation
@@ -731,54 +770,20 @@ EXPORT_SYMBOL(jent_entropy_init);
#ifdef CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT
/*
- * Statistical tests: invoke the entropy collector and sample time results
- * for it, the random data is never returned - every call to this function
- * generates one random number.
- * This function is only meant for statistical analysis purposes and not
- * for general use
- */
-void jent_gen_entropy_stat(struct rand_data *entropy_collector,
- struct entropy_stat *stat)
-{
- /* caller is allowed to set the entropy collection loop to a fixed
- * value -- we still call shuffle for the time measurements */
- jent_init_statistic(entropy_collector);
- jent_gen_entropy(entropy_collector);
- jent_calc_statistic(entropy_collector, stat, DATA_SIZE_BITS);
-}
-
-/*
- * Statistical test: obtain the distribution of the LFSR state value from
- * jent_lfsr_time
- */
-void jent_lfsr_time_stat(struct rand_data *ec, u64 *fold, u64 *loop_cnt)
-{
- u64 time = 0;
- u64 time2 = 0;
- jent_get_nstime(&time);
- jent_memaccess(ec, 0);
- /* implement the priming logic */
- jent_lfsr_time(ec, time, 0);
- jent_get_nstime(&time2);
- time2 = time2 - time;
- *loop_cnt = jent_lfsr_time(ec, time2, 0);
- *fold = ec->data;
-}
-
-/*
* Statistical test: return the time duration for the folding operation. If min
- * is set, perform the given number of foldings. Otherwise, allow the
- * loop count shuffling to define the number of foldings.
+ * is set, perform the given number of LFSR ops. Otherwise, allow the
+ * loop count shuffling to define the number of LFSR ops.
*/
-u64 jent_lfsr_var_stat(struct rand_data *ec, unsigned int min)
+JENT_PRIVATE_STATIC
+uint64_t jent_lfsr_var_stat(struct rand_data *ec, unsigned int min)
{
- u64 time = 0;
- u64 time2 = 0;
-
- jent_get_nstime(&time);
- jent_memaccess(ec, min);
- jent_lfsr_time(ec, time, min);
- jent_get_nstime(&time2);
- return ((time2 - time));
+ uint64_t time = 0;
+ uint64_t time2 = 0;
+
+ jent_get_nstime(&time);
+ jent_memaccess(ec, min);
+ jent_lfsr_time(ec, time, min);
+ jent_get_nstime(&time2);
+ return ((time2 - time));
}
#endif /* CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT */
diff --git a/random/jitterentropy.h b/random/jitterentropy.h
index 2c33256a..28859f5f 100644
--- a/random/jitterentropy.h
+++ b/random/jitterentropy.h
@@ -39,139 +39,110 @@
* DAMAGE.
*/
-#ifndef GCRYPT_JITTERENTROPY_H
-#define GCRYPT_JITTERENTROPY_H
-
-/* #ifdef __KERNEL__ */
-/* #include "jitterentropy-base-kernel.h" */
-/* #else */
-/* #include "jitterentropy-base-user.h" */
-/* #endif /\* __KERNEL__ *\/ */
-
-/* Statistical data from the entropy source */
-struct entropy_stat {
- unsigned int bitslot[64]; /* Counter for the bits set per bit
- position in ->data */
- unsigned int bitvar[64]; /* Counter for the number of bit
- variations per bit position in
- ->data */
- unsigned int enable_bit_test; /* enable bit test
- this flag is vital for the accuracy
- of the statistic tests: when we
- do the time measurements, we want
- the observed entropy collection
- loop executed as fast as the
- unmeasured loop, i.e. without
- the bit statistic logic; on the
- other hand, the bit statistics
- test is not interested in exact
- timing */
- u64 collection_begin; /* timer for beginning of one
- entropy collection round */
- u64 collection_end; /* timer for end of one round */
- u64 old_delta; /* Time delta of previous round to
- calculate delta of deltas */
- unsigned int setbits; /* see _jent_calc_statistic */
- unsigned int varbits; /* see _jent_calc_statistic */
- unsigned int obsbits; /* see _jent_calc_statistic */
- unsigned int collection_loop_cnt; /* Collection loop counter */
-};
+#ifndef _JITTERENTROPY_H
+#define _JITTERENTROPY_H
+
+#ifdef __KERNEL__
+#include "jitterentropy-base-kernel.h"
+#else
+#include "jitterentropy-base-user.h"
+#endif /* __KERNEL__ */
/* The entropy pool */
struct rand_data
{
- /* all data values that are vital to maintain the security
- * of the RNG are marked as SENSITIVE. A user must not
- * access that information while the RNG executes its loops to
- * calculate the next random value. */
- u64 data; /* SENSITIVE Actual random number */
- u64 prev_time; /* SENSITIVE Previous time stamp */
-#define DATA_SIZE_BITS ((sizeof(u64)) * 8)
- u64 last_delta; /* SENSITIVE stuck test */
- int64_t last_delta2; /* SENSITIVE stuck test */
- unsigned int osr; /* Oversample rate */
- unsigned int stir:1; /* Post-processing stirring */
- unsigned int disable_unbias:1; /* Deactivate Von-Neuman unbias */
+ /* all data values that are vital to maintain the security
+ * of the RNG are marked as SENSITIVE. A user must not
+ * access that information while the RNG executes its loops to
+ * calculate the next random value. */
+ uint64_t data; /* SENSITIVE Actual random number */
+ uint64_t old_data; /* SENSITIVE Previous random number */
+ uint64_t prev_time; /* SENSITIVE Previous time stamp */
+#define DATA_SIZE_BITS ((sizeof(uint64_t)) * 8)
+ uint64_t last_delta; /* SENSITIVE stuck test */
+ int64_t last_delta2; /* SENSITIVE stuck test */
+ unsigned int osr; /* Oversample rate */
+ int fips_enabled; /* FIPS enabled? */
+ unsigned int stir:1; /* Post-processing stirring */
+ unsigned int disable_unbias:1; /* Deactivate Von-Neuman unbias */
#define JENT_MEMORY_BLOCKS 64
#define JENT_MEMORY_BLOCKSIZE 32
#define JENT_MEMORY_ACCESSLOOPS 128
#define JENT_MEMORY_SIZE (JENT_MEMORY_BLOCKS*JENT_MEMORY_BLOCKSIZE)
- unsigned char *mem; /* Memory access location with size of
- * memblocks * memblocksize */
- unsigned int memlocation; /* Pointer to byte in *mem */
- unsigned int memblocks; /* Number of memory blocks in *mem */
- unsigned int memblocksize; /* Size of one memory block in bytes */
- unsigned int memaccessloops; /* Number of memory accesses per random
- * bit generation */
-#ifdef CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT
- struct entropy_stat entropy_stat;
-#endif
+ unsigned char *mem; /* Memory access location with size of
+ * memblocks * memblocksize */
+ unsigned int memlocation; /* Pointer to byte in *mem */
+ unsigned int memblocks; /* Number of memory blocks in *mem */
+ unsigned int memblocksize; /* Size of one memory block in bytes */
+ unsigned int memaccessloops; /* Number of memory accesses per random
+ * bit generation */
};
/* Flags that can be used to initialize the RNG */
#define JENT_DISABLE_STIR (1<<0) /* Disable stirring the entropy pool */
#define JENT_DISABLE_UNBIAS (1<<1) /* Disable the Von-Neuman Unbiaser */
#define JENT_DISABLE_MEMORY_ACCESS (1<<2) /* Disable memory access for more
- entropy, saves MEMORY_SIZE RAM for
- entropy collector */
-
-#define DRIVER_NAME "jitterentropy"
+ entropy, saves MEMORY_SIZE RAM for
+ entropy collector */
/* -- BEGIN Main interface functions -- */
+#ifndef JENT_STUCK_INIT_THRES
+/*
+ * Per default, not more than 90% of all measurements during initialization
+ * are allowed to be stuck.
+ *
+ * It is allowed to change this value as required for the intended environment.
+ */
+#define JENT_STUCK_INIT_THRES(x) (x/10 * 9)
+#endif
+
+#ifdef JENT_PRIVATE_COMPILE
+# define JENT_PRIVATE_STATIC static
+#else /* JENT_PRIVATE_COMPILE */
+# define JENT_PRIVATE_STATIC
+#endif
+
/* Number of low bits of the time value that we want to consider */
/* get raw entropy */
-static int jent_read_entropy (struct rand_data *ec,
- char *data, size_t len);
-
+JENT_PRIVATE_STATIC
+ssize_t jent_read_entropy(struct rand_data *ec, char *data, size_t len);
/* initialize an instance of the entropy collector */
-static struct rand_data *jent_entropy_collector_alloc (unsigned int osr,
- unsigned int flags);
-
+JENT_PRIVATE_STATIC
+struct rand_data *jent_entropy_collector_alloc(unsigned int osr,
+ unsigned int flags);
/* clearing of entropy collector */
-static void jent_entropy_collector_free (struct rand_data *ent_coll);
+JENT_PRIVATE_STATIC
+void jent_entropy_collector_free(struct rand_data *entropy_collector);
/* initialization of entropy collector */
-static int jent_entropy_init (void);
+JENT_PRIVATE_STATIC
+int jent_entropy_init(void);
/* return version number of core library */
-/* unsigned int jent_version(void); */
+JENT_PRIVATE_STATIC
+unsigned int jent_version(void);
/* -- END of Main interface functions -- */
/* -- BEGIN error codes for init function -- */
-/* FIXME!!! */
-#define ENOTIME 1 /* Timer service not available */
+#define ENOTIME 1 /* Timer service not available */
#define ECOARSETIME 2 /* Timer too coarse for RNG */
#define ENOMONOTONIC 3 /* Timer is not monotonic increasing */
#define EMINVARIATION 4 /* Timer variations too small for RNG */
#define EVARVAR 5 /* Timer does not produce variations of variations
- (2nd derivation of time is zero) */
+ (2nd derivation of time is zero) */
#define EMINVARVAR 6 /* Timer variations of variations is too small */
#define EPROGERR 7 /* Programming error */
+#define ESTUCK 8 /* Too many stuck results during init. */
/* -- BEGIN statistical test functions only complied with CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT -- */
#ifdef CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT
-
-static void jent_init_statistic(struct rand_data *entropy_collector);
-static void jent_calc_statistic(struct rand_data *entropy_collector,
- struct entropy_stat *stat, unsigned int loop_cnt);
-static void jent_bit_count (struct rand_data *entropy_collector, u64 prev_data);
-
-static void jent_gen_entropy_stat (struct rand_data *entropy_collector,
- struct entropy_stat *stat);
-static void jent_lfsr_time_stat(struct rand_data *ec, u64 *fold, u64 *loop_cnt);
-static u64 jent_lfsr_var_stat(struct rand_data *ec, unsigned int min);
-
-#else /* CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT */
-
-# define jent_init_statistic(x) do { } while (0)
-# define jent_calc_statistic(x, y, z) do { } while (0)
-# define jent_bit_count(x,y) do { (void)(y); } while (0)
-
+JENT_PRIVATE_STATIC
+uint64_t jent_lfsr_var_stat(struct rand_data *ec, unsigned int min);
#endif /* CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT */
/* -- END of statistical test function -- */
-#endif /* GCRYPT_JITTERENTROPY_H */
+#endif /* _JITTERENTROPY_H */
diff --git a/random/rndjent.c b/random/rndjent.c
index dd7ad04e..b1432e45 100644
--- a/random/rndjent.c
+++ b/random/rndjent.c
@@ -71,103 +71,18 @@
#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)
-{
-#if USE_JENT == JENT_USES_RDTSC
-
- 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);
-
-#elif USE_JENT == JENT_USES_GETTIME
-
- struct timespec tv;
- u64 tmp;
-
- /* On Linux we could use CLOCK_MONOTONIC(_RAW), but with
- * CLOCK_REALTIME we get some nice extra entropy once in a while
- * from the NTP actions that we want to use as well... though, we do
- * not rely on that extra little entropy. */
- if (!clock_gettime (CLOCK_REALTIME, &tv))
- {
- tmp = time.tv_sec;
- tmp = tmp << 32;
- tmp = tmp | time.tv_nsec;
- }
- else
- tmp = 0;
- *out = tmp;
-
-#elif USE_JENT == JENT_USES_READ_REAL_TIME
-
- /* clock_gettime() on AIX returns a timer value that increments in
- * steps of 1000. */
- u64 tmp = 0;
-
- timebasestruct_t aixtime;
- read_real_time (&aixtime, TIMEBASE_SZ);
- tmp = aixtime.tb_high;
- tmp = tmp << 32;
- tmp = tmp | aixtime.tb_low;
- *out = tmp;
-
-#else
-# error No clock available in jent_get_nstime
-#endif
-}
-
-
-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
+/* Note that we source include the actual jitter entropy code.
+ * Platform dependent code is indirectly included from our own
+ * jitterentropy-user-base.h file. */
+
+/* Tell jitterentropy* that all functions shall be static. */
+#define JENT_PRIVATE_COMPILE 1
+
#include "jitterentropy-base.c"
@@ -199,52 +114,52 @@ static unsigned long jent_rng_totalbytes;
static void
jent_init_statistic (struct rand_data *rand_data)
{
- int i;
- struct entropy_stat *stat = &rand_data->entropy_stat;
+ /* int i; */
+ /* struct entropy_stat *stat = &rand_data->entropy_stat; */
- for (i = 0; i < 64; i++)
- {
- stat->bitslot[i] = 0;
- stat->bitvar[i] = 0;
- }
+ /* for (i = 0; i < 64; i++) */
+ /* { */
+ /* stat->bitslot[i] = 0; */
+ /* stat->bitvar[i] = 0; */
+ /* } */
- jent_get_nstime (&stat->collection_begin);
+ /* jent_get_nstime (&stat->collection_begin); */
}
static void
jent_bit_count (struct rand_data *rand_data, u64 prev_data)
{
- int i;
-
- if (!rand_data->entropy_stat.enable_bit_test)
- return;
-
- for (i = 0; i < 64; i++)
- {
- /* collect the count of set bits per bit position in the
- * current ->data field */
- rand_data->entropy_stat.bitslot[i] += (rand_data->data & 1<<i) ? 1:0;
-
- /* collect the count of bit changes between the current
- * and the previous random data value per bit position */
- if ((rand_data->data & 1<<i) != (prev_data & 1<<i))
- rand_data->entropy_stat.bitvar[i] += 1;
- }
+ /* int i; */
+
+ /* if (!rand_data->entropy_stat.enable_bit_test) */
+ /* return; */
+
+ /* for (i = 0; i < 64; i++) */
+ /* { */
+ /* /\* collect the count of set bits per bit position in the */
+ /* * current ->data field *\/ */
+ /* rand_data->entropy_stat.bitslot[i] += (rand_data->data & 1<<i) ? 1:0; */
+
+ /* /\* collect the count of bit changes between the current */
+ /* * and the previous random data value per bit position *\/ */
+ /* if ((rand_data->data & 1<<i) != (prev_data & 1<<i)) */
+ /* rand_data->entropy_stat.bitvar[i] += 1; */
+ /* } */
}
static void
jent_statistic_copy_stat (struct entropy_stat *src, struct entropy_stat *dst)
{
- /* not copying bitslot and bitvar as they are not needed for
- * statistic printout */
- dst->collection_begin = src->collection_begin;
- dst->collection_end = src->collection_end;
- dst->old_delta = src->old_delta;
- dst->setbits = src->setbits;
- dst->varbits = src->varbits;
- dst->obsbits = src->obsbits;
- dst->collection_loop_cnt= src->collection_loop_cnt;
+ /* /\* not copying bitslot and bitvar as they are not needed for */
+ /* * statistic printout *\/ */
+ /* dst->collection_begin = src->collection_begin; */
+ /* dst->collection_end = src->collection_end; */
+ /* dst->old_delta = src->old_delta; */
+ /* dst->setbits = src->setbits; */
+ /* dst->varbits = src->varbits; */
+ /* dst->obsbits = src->obsbits; */
+ /* dst->collection_loop_cnt= src->collection_loop_cnt; */
}
@@ -259,30 +174,30 @@ static void
jent_calc_statistic (struct rand_data *rand_data,
struct entropy_stat *target, unsigned int loop_cnt)
{
- int i;
- struct entropy_stat *stat = &rand_data->entropy_stat;
+ /* int i; */
+ /* struct entropy_stat *stat = &rand_data->entropy_stat; */
- jent_get_nstime(&stat->collection_end);
+ /* jent_get_nstime(&stat->collection_end); */
- stat->collection_loop_cnt = loop_cnt;
+ /* stat->collection_loop_cnt = loop_cnt; */
- stat->setbits = 0;
- stat->varbits = 0;
- stat->obsbits = 0;
+ /* stat->setbits = 0; */
+ /* stat->varbits = 0; */
+ /* stat->obsbits = 0; */
- for (i = 0; i < DATA_SIZE_BITS; i++)
- {
- stat->setbits += stat->bitslot[i];
- stat->varbits += stat->bitvar[i];
+ /* for (i = 0; i < DATA_SIZE_BITS; i++) */
+ /* { */
+ /* stat->setbits += stat->bitslot[i]; */
+ /* stat->varbits += stat->bitvar[i]; */
- /* This is the sum of set bits in the current observation
- * of the random data. */
- stat->obsbits += (rand_data->data & 1<<i) ? 1:0;
- }
+ /* /\* This is the sum of set bits in the current observation */
+ /* * of the random data. *\/ */
+ /* stat->obsbits += (rand_data->data & 1<<i) ? 1:0; */
+ /* } */
- jent_statistic_copy_stat(stat, target);
+ /* jent_statistic_copy_stat(stat, target); */
- stat->old_delta = (stat->collection_end - stat->collection_begin);
+ /* stat->old_delta = (stat->collection_end - stat->collection_begin); */
}
#endif /*CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT*/
@@ -438,8 +353,8 @@ void
_gcry_rndjent_dump_stats (void)
{
/* In theory we would need to lock the stats here. However this
- function is usually called during cleanup and then we _might_ run
- into problems. */
+ * function is usually called during cleanup and then we _might_ run
+ * into problems. */
#ifdef USE_JENT
if ( is_rng_available () )