random: Update jitterentropy to 2.1.0.
authorWerner Koch <wk@gnupg.org>
Fri, 23 Jun 2017 07:11:47 +0000 (09:11 +0200)
committerWerner Koch <wk@gnupg.org>
Fri, 23 Jun 2017 07:11:47 +0000 (09:11 +0200)
* 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>
random/Makefile.am
random/jitterentropy-base-user.h
random/jitterentropy-base.c
random/jitterentropy.h
random/rndjent.c

index aaf205e..a3c5dd5 100644 (file)
@@ -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.  */
index 2aecf3b..75dd768 100644 (file)
  * 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 */
index 2701e90..4f3de10 100644 (file)
@@ -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
 #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
  *
  * 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 */
index 2c33256..28859f5 100644 (file)
  * 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 */
index dd7ad04..b1432e4 100644 (file)
 
 #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))
-
-
-\f
-/*
- * 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 () )