diff --git a/random/jitterentropy-base-user.h b/random/jitterentropy-base-user.h index f0fd4842..a05d2114 100644 --- a/random/jitterentropy-base-user.h +++ b/random/jitterentropy-base-user.h @@ -1,301 +1,305 @@ /* * Non-physical true random number generator based on timing jitter. * * Copyright Stephan Mueller , 2013 * * License * ======= * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, and the entire permission notice in its entirety, * including the disclaimer of warranties. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * ALTERNATIVELY, this product may be distributed under the terms of * the GNU General Public License, in which case the provisions of the GPL are * required INSTEAD OF the above restrictions. (This clause is * necessary due to a potential bad interaction between the GPL and * the restrictions contained in a BSD-style copyright.) * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ #ifndef GCRYPT_JITTERENTROPY_BASE_USER_H #define GCRYPT_JITTERENTROPY_BASE_USER_H /* * This is Libgcrypt specific platform dependent code. We use a * separate file because jitterentropy.h expects such a file. */ #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 /* 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) { #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 = tv.tv_sec; tmp = tmp << 32; tmp = tmp | tv.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(); } static inline void jent_memset_secure(void *s, size_t n) { memset(s, 0, n); __asm__ __volatile__("" : : "r" (s) : "memory"); } static inline long jent_ncpu(void) { #ifdef _POSIX_SOURCE long ncpu = sysconf(_SC_NPROCESSORS_ONLN); if (ncpu == -1) return -errno; if (ncpu == 0) return -EFAULT; return ncpu; #else return 1; #endif } #ifdef __linux__ # if defined(_SC_LEVEL1_DCACHE_SIZE) && \ defined(_SC_LEVEL2_CACHE_SIZE) && \ defined(_SC_LEVEL3_CACHE_SIZE) static inline void jent_get_cachesize(long *l1, long *l2, long *l3) { *l1 = sysconf(_SC_LEVEL1_DCACHE_SIZE); *l2 = sysconf(_SC_LEVEL2_CACHE_SIZE); *l3 = sysconf(_SC_LEVEL3_CACHE_SIZE); } # else static inline void jent_get_cachesize(long *l1, long *l2, long *l3) { #define JENT_SYSFS_CACHE_DIR "/sys/devices/system/cpu/cpu0/cache" long val; unsigned int i; char buf[10], file[50]; int fd = 0; /* Iterate over all caches */ for (i = 0; i < 4; i++) { unsigned int shift = 0; char *ext; /* * Check the cache type - we are only interested in Unified * and Data caches. */ memset(buf, 0, sizeof(buf)); snprintf(file, sizeof(file), "%s/index%u/type", JENT_SYSFS_CACHE_DIR, i); fd = open(file, O_RDONLY); if (fd < 0) continue; while (read(fd, buf, sizeof(buf)) < 0 && errno == EINTR); close(fd); buf[sizeof(buf) - 1] = '\0'; if (strncmp(buf, "Data", 4) && strncmp(buf, "Unified", 7)) continue; /* Get size of cache */ memset(buf, 0, sizeof(buf)); snprintf(file, sizeof(file), "%s/index%u/size", JENT_SYSFS_CACHE_DIR, i); fd = open(file, O_RDONLY); if (fd < 0) continue; while (read(fd, buf, sizeof(buf)) < 0 && errno == EINTR); close(fd); buf[sizeof(buf) - 1] = '\0'; ext = strstr(buf, "K"); if (ext) { shift = 10; ext = '\0'; } else { ext = strstr(buf, "M"); if (ext) { shift = 20; ext = '\0'; } } val = strtol(buf, NULL, 10); if (val == LONG_MAX) continue; val <<= shift; if (!*l1) *l1 = val; else if (!*l2) *l2 = val; else { *l3 = val; break; } } #undef JENT_SYSFS_CACHE_DIR } # endif static inline uint32_t jent_cache_size_roundup(void) { static int checked = 0; static uint32_t cache_size = 0; if (!checked) { long l1 = 0, l2 = 0, l3 = 0; jent_get_cachesize(&l1, &l2, &l3); checked = 1; /* Cache size reported by system */ if (l1 > 0) cache_size += (uint32_t)l1; if (l2 > 0) cache_size += (uint32_t)l2; if (l3 > 0) cache_size += (uint32_t)l3; /* * Force the output_size to be of the form * (bounding_power_of_2 - 1). */ cache_size |= (cache_size >> 1); cache_size |= (cache_size >> 2); cache_size |= (cache_size >> 4); cache_size |= (cache_size >> 8); cache_size |= (cache_size >> 16); if (cache_size == 0) return 0; /* * Make the output_size the smallest power of 2 strictly * greater than cache_size. */ cache_size++; } return cache_size; } #else /* __linux__ */ static inline uint32_t jent_cache_size_roundup(void) { return 0; } #endif /* __linux__ */ +#ifdef JENT_CONF_ENABLE_INTERNAL_TIMER +#include + static inline void jent_yield(void) { sched_yield(); } +#endif #endif /* GCRYPT_JITTERENTROPY_BASE_USER_H */ diff --git a/random/jitterentropy-base.c b/random/jitterentropy-base.c index 30109dc1..5ff6654c 100644 --- a/random/jitterentropy-base.c +++ b/random/jitterentropy-base.c @@ -1,732 +1,734 @@ /* * Non-physical true random number generator based on timing jitter. * * Copyright Stephan Mueller , 2014 - 2021 * * Design * ====== * * See documentation in doc/ folder. * * Interface * ========= * * See documentation in jitterentropy(3) man page. * * License: see LICENSE file in root directory * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ #include "jitterentropy.h" #include "jitterentropy-base.h" #include "jitterentropy-gcd.h" #include "jitterentropy-health.h" #include "jitterentropy-noise.h" #include "jitterentropy-timer.h" #include "jitterentropy-sha3.h" #define MAJVERSION 3 /* 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 3 /* 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 */ /*************************************************************************** * Jitter RNG Static Definitions * * None of the following should be altered ***************************************************************************/ #ifdef __OPTIMIZE__ #error "The CPU Jitter random number generator must not be compiled with optimizations. See documentation. Use the compiler switch -O0 for compiling jitterentropy.c." #endif /* * JENT_POWERUP_TESTLOOPCOUNT needs some loops to identify edge * systems. 100 is definitely too little. * * SP800-90B requires at least 1024 initial test cycles. */ #define JENT_POWERUP_TESTLOOPCOUNT 1024 /** * jent_version() - Return machine-usable version number of jent library * * The function returns a version number that is monotonic increasing * for newer versions. The version numbers are multiples of 100. For example, * version 1.2.3 is converted to 1020300 -- the last two digits are reserved * for future use. * * The result of this function can be used in comparing the version number * in a calling program if version-specific calls need to be make. * * @return Version number of jitterentropy library */ JENT_PRIVATE_STATIC unsigned int jent_version(void) { unsigned int version = 0; version = MAJVERSION * 1000000; version += MINVERSION * 10000; version += PATCHLEVEL * 100; return version; } /*************************************************************************** * Helper ***************************************************************************/ /* Calculate log2 of given value assuming that the value is a power of 2 */ static inline unsigned int jent_log2_simple(unsigned int val) { unsigned int idx = 0; while (val >>= 1) idx++; return idx; } /* Increase the memory size by one step */ static inline unsigned int jent_update_memsize(unsigned int flags) { unsigned int global_max = JENT_FLAGS_TO_MAX_MEMSIZE( JENT_MAX_MEMSIZE_MAX); unsigned int max; max = JENT_FLAGS_TO_MAX_MEMSIZE(flags); if (!max) { /* * The safe starting value is the amount of memory we allocated * last round. */ max = jent_log2_simple(JENT_MEMORY_SIZE); /* Adjust offset */ max = (max > JENT_MAX_MEMSIZE_OFFSET) ? max - JENT_MAX_MEMSIZE_OFFSET : 0; } else { max++; } max = (max > global_max) ? global_max : max; /* Clear out the max size */ flags &= ~JENT_MAX_MEMSIZE_MASK; /* Set the freshly calculated max size */ flags |= JENT_MAX_MEMSIZE_TO_FLAGS(max); return flags; } /*************************************************************************** * Random Number Generation ***************************************************************************/ /** * Entry function: Obtain entropy for the caller. * * This function invokes the entropy gathering logic as often to generate * as many bytes as requested by the caller. The entropy gathering logic * creates 64 bit per invocation. * * This function truncates the last 64 bit entropy value output to the exact * size specified by the caller. * * @ec [in] Reference to entropy collector * @data [out] pointer to buffer for storing random data -- buffer must * already exist * @len [in] size of the buffer, specifying also the requested number of random * in bytes * * @return number of bytes returned when request is fulfilled or an error * * The following error codes can occur: * -1 entropy_collector is NULL * -2 RCT failed * -3 APT test failed * -4 The timer cannot be initialized * -5 LAG failure */ 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; int ret = 0; if (NULL == ec) return -1; if (jent_notime_settick(ec)) return -4; while (len > 0) { size_t tocopy; unsigned int health_test_result; jent_random_data(ec); if ((health_test_result = jent_health_failure(ec))) { if (health_test_result & JENT_RCT_FAILURE) ret = -2; else if (health_test_result & JENT_APT_FAILURE) ret = -3; else ret = -5; goto err; } 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_random_data(ec); #endif err: jent_notime_unsettick(ec); return ret ? ret : (ssize_t)orig_len; } static struct rand_data *_jent_entropy_collector_alloc(unsigned int osr, unsigned int flags); /** * Entry function: Obtain entropy for the caller. * * This is a service function to jent_read_entropy() with the difference * that it automatically re-allocates the entropy collector if a health * test failure is observed. Before reallocation, a new power-on health test * is performed. The allocation of the new entropy collector automatically * increases the OSR by one. This is done based on the idea that a health * test failure indicates that the assumed entropy rate is too high. * * Note the function returns with an health test error if the OSR is * getting too large. If an error is returned by this function, the Jitter RNG * is not safe to be used on the current system. * * @ec [in] Reference to entropy collector - this is a double pointer as * The entropy collector may be freed and reallocated. * @data [out] pointer to buffer for storing random data -- buffer must * already exist * @len [in] size of the buffer, specifying also the requested number of random * in bytes * * @return see jent_read_entropy() */ JENT_PRIVATE_STATIC ssize_t jent_read_entropy_safe(struct rand_data **ec, char *data, size_t len) { char *p = data; size_t orig_len = len; ssize_t ret = 0; if (!ec) return -1; while (len > 0) { unsigned int osr, flags, max_mem_set; ret = jent_read_entropy(*ec, p, len); switch (ret) { case -1: case -4: return ret; case -2: case -3: case -5: osr = (*ec)->osr + 1; flags = (*ec)->flags; max_mem_set = (*ec)->max_mem_set; /* generic arbitrary cutoff */ if (osr > 20) return ret; /* * If the caller did not set any specific maximum value * let the Jitter RNG increase the maximum memory by * one step. */ if (!max_mem_set) flags = jent_update_memsize(flags); /* * re-allocate entropy collector with higher OSR and * memory size */ jent_entropy_collector_free(*ec); /* Perform new health test with updated OSR */ if (jent_entropy_init_ex(osr, flags)) return -1; *ec = _jent_entropy_collector_alloc(osr, flags); if (!*ec) return -1; /* Remember whether caller configured memory size */ (*ec)->max_mem_set = !!max_mem_set; break; default: len -= (size_t)ret; p += (size_t)ret; } } return (ssize_t)orig_len; } /*************************************************************************** * Initialization logic ***************************************************************************/ /* * Obtain memory size to allocate for memory access variations. * * The maximum variations we can get from the memory access is when we allocate * a bit more memory than we have as data cache. But allocating as much * memory as we have as data cache might strain the resources on the system * more than necessary. * * On a lot of systems it is not necessary to need so much memory as the * variations coming from the general Jitter RNG execution commonly provide * large amount of variations. * * Thus, the default is: * * min(JENT_MEMORY_SIZE, data cache size) * * In case the data cache size cannot be obtained, use JENT_MEMORY_SIZE. * * If the caller provides a maximum memory size, use * min(provided max memory, data cache size). */ static inline uint32_t jent_memsize(unsigned int flags) { uint32_t memsize, max_memsize; max_memsize = JENT_FLAGS_TO_MAX_MEMSIZE(flags); if (max_memsize == 0) { max_memsize = JENT_MEMORY_SIZE; } else { max_memsize = UINT32_C(1) << (max_memsize + JENT_MAX_MEMSIZE_OFFSET); } /* Allocate memory for adding variations based on memory access */ memsize = jent_cache_size_roundup(); /* Limit the memory as defined by caller */ memsize = (memsize > max_memsize) ? max_memsize : memsize; /* Set a value if none was found */ if (!memsize) memsize = JENT_MEMORY_SIZE; return memsize; } static int jent_selftest_run = 0; static struct rand_data *jent_entropy_collector_alloc_internal(unsigned int osr, unsigned int flags) { struct rand_data *entropy_collector; /* * Requesting disabling and forcing of internal timer * makes no sense. */ if ((flags & JENT_DISABLE_INTERNAL_TIMER) && (flags & JENT_FORCE_INTERNAL_TIMER)) return NULL; /* Force the self test to be run */ if (!jent_selftest_run && jent_entropy_init_ex(osr, flags)) return NULL; /* * If the initial test code concludes to force the internal timer * and the user requests it not to be used, do not allocate * the Jitter RNG instance. */ if (jent_notime_forced() && (flags & JENT_DISABLE_INTERNAL_TIMER)) return NULL; entropy_collector = jent_zalloc(sizeof(struct rand_data)); if (NULL == entropy_collector) return NULL; if (!(flags & JENT_DISABLE_MEMORY_ACCESS)) { uint32_t memsize = jent_memsize(flags); entropy_collector->mem = (unsigned char *)jent_zalloc(memsize); #ifdef JENT_RANDOM_MEMACCESS /* * Transform the size into a mask - it is assumed that size is * a power of 2. */ entropy_collector->memmask = memsize - 1; #else /* JENT_RANDOM_MEMACCESS */ entropy_collector->memblocksize = memsize / JENT_MEMORY_BLOCKS; entropy_collector->memblocks = JENT_MEMORY_BLOCKS; /* sanity check */ if (entropy_collector->memblocksize * entropy_collector->memblocks != memsize) goto err; #endif /* JENT_RANDOM_MEMACCESS */ if (entropy_collector->mem == NULL) goto err; entropy_collector->memaccessloops = JENT_MEMORY_ACCESSLOOPS; } /* verify and set the oversampling rate */ if (osr < JENT_MIN_OSR) osr = JENT_MIN_OSR; entropy_collector->osr = osr; entropy_collector->flags = flags; if (jent_fips_enabled() || (flags & JENT_FORCE_FIPS)) entropy_collector->fips_enabled = 1; /* Initialize the APT */ jent_apt_init(entropy_collector, osr); /* Initialize the Lag Predictor Test */ jent_lag_init(entropy_collector, osr); /* Was jent_entropy_init run (establishing the common GCD)? */ if (jent_gcd_get(&entropy_collector->jent_common_timer_gcd)) { /* * It was not. This should probably be an error, but this * behavior breaks the test code. Set the gcd to a value that * won't hurt anything. */ entropy_collector->jent_common_timer_gcd = 1; } /* * Use timer-less noise source - note, OSR must be set in * entropy_collector! */ if (!(flags & JENT_DISABLE_INTERNAL_TIMER)) { if (jent_notime_enable(entropy_collector, flags)) goto err; } return entropy_collector; err: if (entropy_collector->mem != NULL) jent_zfree(entropy_collector->mem, JENT_MEMORY_SIZE); jent_zfree(entropy_collector, sizeof(struct rand_data)); return NULL; } static struct rand_data *_jent_entropy_collector_alloc(unsigned int osr, unsigned int flags) { struct rand_data *ec = jent_entropy_collector_alloc_internal(osr, flags); if (!ec) return ec; /* fill the data pad with non-zero values */ if (jent_notime_settick(ec)) { jent_entropy_collector_free(ec); return NULL; } jent_random_data(ec); jent_notime_unsettick(ec); return ec; } JENT_PRIVATE_STATIC struct rand_data *jent_entropy_collector_alloc(unsigned int osr, unsigned int flags) { struct rand_data *ec = _jent_entropy_collector_alloc(osr, flags); /* Remember that the caller provided a maximum size flag */ if (ec) ec->max_mem_set = !!JENT_FLAGS_TO_MAX_MEMSIZE(flags); return ec; } JENT_PRIVATE_STATIC void jent_entropy_collector_free(struct rand_data *entropy_collector) { if (entropy_collector != NULL) { jent_notime_disable(entropy_collector); if (entropy_collector->mem != NULL) { jent_zfree(entropy_collector->mem, jent_memsize(entropy_collector->flags)); entropy_collector->mem = NULL; } jent_zfree(entropy_collector, sizeof(struct rand_data)); } } int jent_time_entropy_init(unsigned int osr, unsigned int flags) { struct rand_data *ec; uint64_t *delta_history; int i, time_backwards = 0, count_stuck = 0, ret = 0; unsigned int health_test_result; delta_history = jent_gcd_init(JENT_POWERUP_TESTLOOPCOUNT); if (!delta_history) return EMEM; if (flags & JENT_FORCE_INTERNAL_TIMER) jent_notime_force(); else flags |= JENT_DISABLE_INTERNAL_TIMER; /* * If the start-up health tests (including the APT and RCT) are not * run, then the entropy source is not 90B compliant. We could test if * fips_enabled should be set using the jent_fips_enabled() function, * but this can be overridden using the JENT_FORCE_FIPS flag, which * isn't passed in yet. It is better to run the tests on the small * amount of data that we have, which should not fail unless things * are really bad. */ flags |= JENT_FORCE_FIPS; ec = jent_entropy_collector_alloc_internal(osr, flags); if (!ec) { ret = EMEM; goto out; } if (jent_notime_settick(ec)) { ret = EMEM; goto out; } /* To initialize the prior time. */ jent_measure_jitter(ec, 0, NULL); /* 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 leading to false positives. */ /* * 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. */ #define CLEARCACHE 100 for (i = -CLEARCACHE; i < JENT_POWERUP_TESTLOOPCOUNT; i++) { uint64_t start_time = 0, end_time = 0, delta = 0; unsigned int stuck; /* Invoke core entropy collection logic */ stuck = jent_measure_jitter(ec, 0, &delta); end_time = ec->prev_time; start_time = ec->prev_time - delta; /* test whether timer works */ if (!start_time || !end_time) { ret = ENOTIME; goto out; } /* * 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 || (end_time == start_time)) { ret = ECOARSETIME; goto out; } /* * 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 (i < 0) continue; if (stuck) count_stuck++; /* test whether we have an increasing timer */ if (!(end_time > start_time)) time_backwards++; /* Watch for common adjacent GCD values */ jent_gcd_add_value(delta_history, delta, i); } /* * 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 (time_backwards > 3) { ret = ENOMONOTONIC; goto out; } /* First, did we encounter a health test failure? */ if ((health_test_result = jent_health_failure(ec))) { ret = (health_test_result & JENT_RCT_FAILURE) ? ERCT : EHEALTH; goto out; } ret = jent_gcd_analyze(delta_history, JENT_POWERUP_TESTLOOPCOUNT); if (ret) goto out; /* * If we have more than 90% stuck results, then this Jitter RNG is * likely to not work well. */ if (JENT_STUCK_INIT_THRES(JENT_POWERUP_TESTLOOPCOUNT) < count_stuck) ret = ESTUCK; out: jent_gcd_fini(delta_history, JENT_POWERUP_TESTLOOPCOUNT); if ((flags & JENT_FORCE_INTERNAL_TIMER) && ec) jent_notime_unsettick(ec); jent_entropy_collector_free(ec); return ret; } static inline int jent_entropy_init_common_pre(void) { int ret; jent_notime_block_switch(); if (sha3_tester()) return EHASH; ret = jent_gcd_selftest(); jent_selftest_run = 1; return ret; } static inline int jent_entropy_init_common_post(int ret) { /* Unmark the execution of the self tests if they failed. */ if (ret) jent_selftest_run = 0; return ret; } JENT_PRIVATE_STATIC int jent_entropy_init(void) { int ret = jent_entropy_init_common_pre(); if (ret) return ret; ret = jent_time_entropy_init(0, JENT_DISABLE_INTERNAL_TIMER); #ifdef JENT_CONF_ENABLE_INTERNAL_TIMER if (ret) ret = jent_time_entropy_init(0, JENT_FORCE_INTERNAL_TIMER); #endif /* JENT_CONF_ENABLE_INTERNAL_TIMER */ return jent_entropy_init_common_post(ret); } JENT_PRIVATE_STATIC int jent_entropy_init_ex(unsigned int osr, unsigned int flags) { int ret = jent_entropy_init_common_pre(); if (ret) return ret; /* Test without internal timer unless caller does not want it */ if (!(flags & JENT_FORCE_INTERNAL_TIMER)) ret = jent_time_entropy_init(osr, flags | JENT_DISABLE_INTERNAL_TIMER); #ifdef JENT_CONF_ENABLE_INTERNAL_TIMER /* Test with internal timer unless caller does not want it */ if (ret && !(flags & JENT_DISABLE_INTERNAL_TIMER)) ret = jent_time_entropy_init(osr, flags | JENT_FORCE_INTERNAL_TIMER); #endif /* JENT_CONF_ENABLE_INTERNAL_TIMER */ return jent_entropy_init_common_post(ret); } +#ifdef JENT_CONF_ENABLE_INTERNAL_TIMER JENT_PRIVATE_STATIC int jent_entropy_switch_notime_impl(struct jent_notime_thread *new_thread) { return jent_notime_switch(new_thread); } +#endif diff --git a/random/jitterentropy.h b/random/jitterentropy.h index 4322c65d..0a91f36a 100644 --- a/random/jitterentropy.h +++ b/random/jitterentropy.h @@ -1,447 +1,449 @@ /* * Non-physical true random number generator based on timing jitter. * * Copyright Stephan Mueller , 2014 - 2021 * * License * ======= * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, and the entire permission notice in its entirety, * including the disclaimer of warranties. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * ALTERNATIVELY, this product may be distributed under the terms of * the GNU General Public License, in which case the provisions of the GPL are * required INSTEAD OF the above restrictions. (This clause is * necessary due to a potential bad interaction between the GPL and * the restrictions contained in a BSD-style copyright.) * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ #ifndef _JITTERENTROPY_H #define _JITTERENTROPY_H /*************************************************************************** * Jitter RNG Configuration Section * * You may alter the following options ***************************************************************************/ /* * Enable timer-less timer support * * In case the hardware is identified to not provide a high-resolution time * stamp, this option enables a built-in high-resolution time stamp mechanism. * * The timer-less noise source is based on threads. This noise source requires * the linking with the POSIX threads library. I.e. the executing environment * must offer POSIX threads. If this option is disabled, no linking * with the POSIX threads library is needed. */ -#define JENT_CONF_ENABLE_INTERNAL_TIMER +#undef JENT_CONF_ENABLE_INTERNAL_TIMER /* * Disable the loop shuffle operation * * The shuffle operation enlarges the timing of the conditioning function * by a variable length defined by the LSB of a time stamp. Some mathematicians * are concerned that this pseudo-random selection of the loop iteration count * may create some form of dependency between the different loop counts * and the associated time duration of the conditioning function. It * also complicates entropy assessment because it effectively combines a bunch * of shifted/scaled copies the same distribution and masks failures from the * health testing. * * By enabling this flag, the loop shuffle operation is disabled and * the entropy collection operates in a way that honor the concerns. * * By enabling this flag, the time of collecting entropy may be enlarged. */ #define JENT_CONF_DISABLE_LOOP_SHUFFLE /* * Shall the LAG predictor health test be enabled? */ #define JENT_HEALTH_LAG_PREDICTOR /* * Shall the jent_memaccess use a (statistically) random selection for the * memory to update? */ #define JENT_RANDOM_MEMACCESS /*************************************************************************** * Jitter RNG State Definition Section ***************************************************************************/ #include "jitterentropy-base-user.h" #define SHA3_256_SIZE_DIGEST_BITS 256 #define SHA3_256_SIZE_DIGEST (SHA3_256_SIZE_DIGEST_BITS >> 3) /* * The output 256 bits can receive more than 256 bits of min entropy, * of course, but the 256-bit output of SHA3-256(M) can only asymptotically * approach 256 bits of min entropy, not attain that bound. Random maps will * tend to have output collisions, which reduces the creditable output entropy * (that is what SP 800-90B Section 3.1.5.1.2 attempts to bound). * * The value "64" is justified in Appendix A.4 of the current 90C draft, * and aligns with NIST's in "epsilon" definition in this document, which is * that a string can be considered "full entropy" if you can bound the min * entropy in each bit of output to at least 1-epsilon, where epsilon is * required to be <= 2^(-32). */ #define ENTROPY_SAFETY_FACTOR 64 /** * Function pointer data structure to register an external thread handler * used for the timer-less mode of the Jitter RNG. * * The external caller provides these function pointers to handle the * management of the timer thread that is spawned by the Jitter RNG. * * @var jent_notime_init This function is intended to initialze the threading * support. All data that is required by the threading code must be * held in the data structure @param ctx. The Jitter RNG maintains the * data structure and uses it for every invocation of the following calls. * * @var jent_notime_fini This function shall terminate the threading support. * The function must dispose of all memory and resources used for the * threading operation. It must also dispose of the @param ctx memory. * * @var jent_notime_start This function is called when the Jitter RNG wants * to start a thread. Besides providing a pointer to the @param ctx * allocated during initialization time, the Jitter RNG provides a * pointer to the function the thread shall execute and the argument * the function shall be invoked with. These two parameters have the * same purpose as the trailing two parameters of pthread_create(3). * * @var jent_notime_stop This function is invoked by the Jitter RNG when the * thread should be stopped. Note, the Jitter RNG intends to start/stop * the thread frequently. * * An example implementation is found in the Jitter RNG itself with its * default thread handler of jent_notime_thread_builtin. * * If the caller wants to register its own thread handler, it must be done * with the API call jent_entropy_switch_notime_impl as the first * call to interact with the Jitter RNG, even before jent_entropy_init. * After jent_entropy_init is called, changing of the threading implementation * is not allowed. */ struct jent_notime_thread { int (*jent_notime_init)(void **ctx); void (*jent_notime_fini)(void *ctx); int (*jent_notime_start)(void *ctx, void *(*start_routine) (void *), void *arg); void (*jent_notime_stop)(void *ctx); }; /* 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. */ uint8_t data[SHA3_256_SIZE_DIGEST]; /* SENSITIVE Actual random number */ uint64_t prev_time; /* SENSITIVE Previous time stamp */ #define DATA_SIZE_BITS (SHA3_256_SIZE_DIGEST_BITS) #ifndef JENT_HEALTH_LAG_PREDICTOR uint64_t last_delta; /* SENSITIVE stuck test */ uint64_t last_delta2; /* SENSITIVE stuck test */ #endif /* JENT_HEALTH_LAG_PREDICTOR */ unsigned int flags; /* Flags used to initialize */ unsigned int osr; /* Oversampling rate */ #ifdef JENT_RANDOM_MEMACCESS /* The step size should be larger than the cacheline size. */ # ifndef JENT_MEMORY_BITS # define JENT_MEMORY_BITS 17 # endif # ifndef JENT_MEMORY_SIZE # define JENT_MEMORY_SIZE (UINT32_C(1)<> JENT_FLAGS_TO_MEMSIZE_SHIFT) #define JENT_MAX_MEMSIZE_TO_FLAGS(val) (val << JENT_FLAGS_TO_MEMSIZE_SHIFT) #define JENT_MAX_MEMSIZE_32kB JENT_MAX_MEMSIZE_TO_FLAGS(UINT32_C( 1)) #define JENT_MAX_MEMSIZE_64kB JENT_MAX_MEMSIZE_TO_FLAGS(UINT32_C( 2)) #define JENT_MAX_MEMSIZE_128kB JENT_MAX_MEMSIZE_TO_FLAGS(UINT32_C( 3)) #define JENT_MAX_MEMSIZE_256kB JENT_MAX_MEMSIZE_TO_FLAGS(UINT32_C( 4)) #define JENT_MAX_MEMSIZE_512kB JENT_MAX_MEMSIZE_TO_FLAGS(UINT32_C( 5)) #define JENT_MAX_MEMSIZE_1MB JENT_MAX_MEMSIZE_TO_FLAGS(UINT32_C( 6)) #define JENT_MAX_MEMSIZE_2MB JENT_MAX_MEMSIZE_TO_FLAGS(UINT32_C( 7)) #define JENT_MAX_MEMSIZE_4MB JENT_MAX_MEMSIZE_TO_FLAGS(UINT32_C( 8)) #define JENT_MAX_MEMSIZE_8MB JENT_MAX_MEMSIZE_TO_FLAGS(UINT32_C( 9)) #define JENT_MAX_MEMSIZE_16MB JENT_MAX_MEMSIZE_TO_FLAGS(UINT32_C(10)) #define JENT_MAX_MEMSIZE_32MB JENT_MAX_MEMSIZE_TO_FLAGS(UINT32_C(11)) #define JENT_MAX_MEMSIZE_64MB JENT_MAX_MEMSIZE_TO_FLAGS(UINT32_C(12)) #define JENT_MAX_MEMSIZE_128MB JENT_MAX_MEMSIZE_TO_FLAGS(UINT32_C(13)) #define JENT_MAX_MEMSIZE_256MB JENT_MAX_MEMSIZE_TO_FLAGS(UINT32_C(14)) #define JENT_MAX_MEMSIZE_512MB JENT_MAX_MEMSIZE_TO_FLAGS(UINT32_C(15)) #define JENT_MAX_MEMSIZE_MAX JENT_MAX_MEMSIZE_512MB #define JENT_MAX_MEMSIZE_MASK JENT_MAX_MEMSIZE_MAX /* We start at 32kB -> offset is log2(32768) */ #define JENT_MAX_MEMSIZE_OFFSET 14 #ifdef JENT_CONF_DISABLE_LOOP_SHUFFLE # define JENT_MIN_OSR 3 #else # define JENT_MIN_OSR 1 #endif #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) /* -- 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*9) / 10) #endif #ifdef JENT_PRIVATE_COMPILE # define JENT_PRIVATE_STATIC static #else /* JENT_PRIVATE_COMPILE */ # define JENT_PRIVATE_STATIC __attribute__((visibility("default"))) #endif /* Number of low bits of the time value that we want to consider */ /* get raw entropy */ JENT_PRIVATE_STATIC ssize_t jent_read_entropy(struct rand_data *ec, char *data, size_t len); JENT_PRIVATE_STATIC ssize_t jent_read_entropy_safe(struct rand_data **ec, char *data, size_t len); /* initialize an instance of the entropy collector */ JENT_PRIVATE_STATIC struct rand_data *jent_entropy_collector_alloc(unsigned int osr, unsigned int flags); /* clearing of entropy collector */ JENT_PRIVATE_STATIC void jent_entropy_collector_free(struct rand_data *entropy_collector); /* initialization of entropy collector */ JENT_PRIVATE_STATIC int jent_entropy_init(void); JENT_PRIVATE_STATIC int jent_entropy_init_ex(unsigned int osr, unsigned int flags); /* return version number of core library */ JENT_PRIVATE_STATIC unsigned int jent_version(void); +#ifdef JENT_CONF_ENABLE_INTERNAL_TIMER /* Set a different thread handling logic for the notimer support */ JENT_PRIVATE_STATIC int jent_entropy_switch_notime_impl(struct jent_notime_thread *new_thread); +#endif /* -- END of Main interface functions -- */ /* -- BEGIN timer-less threading support functions to prevent code dupes -- */ struct jent_notime_ctx { pthread_attr_t notime_pthread_attr; /* pthreads library */ pthread_t notime_thread_id; /* pthreads thread ID */ }; #ifdef JENT_CONF_ENABLE_INTERNAL_TIMER JENT_PRIVATE_STATIC int jent_notime_init(void **ctx); JENT_PRIVATE_STATIC void jent_notime_fini(void *ctx); #else static inline int jent_notime_init(void **ctx) { (void)ctx; return 0; } static inline void jent_notime_fini(void *ctx) { (void)ctx; } #endif /* JENT_CONF_ENABLE_INTERNAL_TIMER */ /* -- END timer-less threading support functions to prevent code dupes -- */ /* -- BEGIN error codes for init function -- */ #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) */ #define EMINVARVAR 6 /* Timer variations of variations is too small */ #define EPROGERR 7 /* Programming error */ #define ESTUCK 8 /* Too many stuck results during init. */ #define EHEALTH 9 /* Health test failed during initialization */ #define ERCT 10 /* RCT failed during initialization */ #define EHASH 11 /* Hash self test failed */ #define EMEM 12 /* Can't allocate memory for initialization */ #define EGCD 13 /* GCD self-test failed */ /* -- END error codes for init function -- */ /* -- BEGIN error masks for health tests -- */ #define JENT_RCT_FAILURE 1 /* Failure in RCT health test. */ #define JENT_APT_FAILURE 2 /* Failure in APT health test. */ #define JENT_LAG_FAILURE 4 /* Failure in Lag predictor health test. */ /* -- END error masks for health tests -- */ /* -- BEGIN statistical test functions only complied with CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT -- */ #ifdef CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT 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 /* _JITTERENTROPY_H */