diff options
author | Werner Koch <wk@gnupg.org> | 2017-06-23 09:11:47 +0200 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2017-06-23 09:11:47 +0200 |
commit | 8dfae89ecd3e9ae0967586cb38d12ef9111fc7cd (patch) | |
tree | ad08019807856b3734afa1d77323d679c2d9d95c | |
parent | 27148e60ba15b0cb73b47a75c688fcb48a1a3444 (diff) | |
download | libgcrypt-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.am | 2 | ||||
-rw-r--r-- | random/jitterentropy-base-user.h | 119 | ||||
-rw-r--r-- | random/jitterentropy-base.c | 1019 | ||||
-rw-r--r-- | random/jitterentropy.h | 157 | ||||
-rw-r--r-- | random/rndjent.c | 203 |
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 () ) |