^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Non-physical true random number generator based on timing jitter --
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Jitter RNG standalone code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright Stephan Mueller <smueller@chronox.de>, 2015 - 2020
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Design
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * ======
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * See https://www.chronox.de/jent.html
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * License
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * =======
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Redistribution and use in source and binary forms, with or without
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * modification, are permitted provided that the following conditions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * are met:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * 1. Redistributions of source code must retain the above copyright
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * notice, and the entire permission notice in its entirety,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * including the disclaimer of warranties.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * 2. Redistributions in binary form must reproduce the above copyright
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * notice, this list of conditions and the following disclaimer in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * documentation and/or other materials provided with the distribution.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * 3. The name of the author may not be used to endorse or promote
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * products derived from this software without specific prior
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * written permission.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * ALTERNATIVELY, this product may be distributed under the terms of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * the GNU General Public License, in which case the provisions of the GPL2 are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * required INSTEAD OF the above restrictions. (This clause is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * necessary due to a potential bad interaction between the GPL and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * the restrictions contained in a BSD-style copyright.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * DAMAGE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * This Jitterentropy RNG is based on the jitterentropy library
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * version 2.2.0 provided at https://www.chronox.de/jent.html
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #ifdef __OPTIMIZE__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #error "The CPU Jitter random number generator must not be compiled with optimizations. See documentation. Use the compiler switch -O0 for compiling jitterentropy.c."
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) typedef unsigned long long __u64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) typedef long long __s64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) typedef unsigned int __u32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define NULL ((void *) 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) /* The entropy pool */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) struct rand_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /* all data values that are vital to maintain the security
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * of the RNG are marked as SENSITIVE. A user must not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * access that information while the RNG executes its loops to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * calculate the next random value. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) __u64 data; /* SENSITIVE Actual random number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) __u64 old_data; /* SENSITIVE Previous random number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) __u64 prev_time; /* SENSITIVE Previous time stamp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define DATA_SIZE_BITS ((sizeof(__u64)) * 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) __u64 last_delta; /* SENSITIVE stuck test */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) __s64 last_delta2; /* SENSITIVE stuck test */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) unsigned int osr; /* Oversample rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define JENT_MEMORY_BLOCKS 64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define JENT_MEMORY_BLOCKSIZE 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define JENT_MEMORY_ACCESSLOOPS 128
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define JENT_MEMORY_SIZE (JENT_MEMORY_BLOCKS*JENT_MEMORY_BLOCKSIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) unsigned char *mem; /* Memory access location with size of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * memblocks * memblocksize */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) unsigned int memlocation; /* Pointer to byte in *mem */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) unsigned int memblocks; /* Number of memory blocks in *mem */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) unsigned int memblocksize; /* Size of one memory block in bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) unsigned int memaccessloops; /* Number of memory accesses per random
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * bit generation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) /* Repetition Count Test */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) int rct_count; /* Number of stuck values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /* Adaptive Proportion Test for a significance level of 2^-30 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define JENT_APT_CUTOFF 325 /* Taken from SP800-90B sec 4.4.2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define JENT_APT_WINDOW_SIZE 512 /* Data window size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) /* LSB of time stamp to process */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define JENT_APT_LSB 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define JENT_APT_WORD_MASK (JENT_APT_LSB - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) unsigned int apt_observations; /* Number of collected observations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) unsigned int apt_count; /* APT counter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) unsigned int apt_base; /* APT base reference */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) unsigned int apt_base_set:1; /* APT base reference set? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) unsigned int health_failure:1; /* Permanent health failure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) /* Flags that can be used to initialize the RNG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define JENT_DISABLE_MEMORY_ACCESS (1<<2) /* Disable memory access for more
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * entropy, saves MEMORY_SIZE RAM for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * entropy collector */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) /* -- error codes for init function -- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define JENT_ENOTIME 1 /* Timer service not available */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define JENT_ECOARSETIME 2 /* Timer too coarse for RNG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #define JENT_ENOMONOTONIC 3 /* Timer is not monotonic increasing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #define JENT_EVARVAR 5 /* Timer does not produce variations of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * variations (2nd derivation of time is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * zero). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define JENT_ESTUCK 8 /* Too many stuck results during init. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #define JENT_EHEALTH 9 /* Health test failed during initialization */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #define JENT_ERCT 10 /* RCT failed during initialization */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #include "jitterentropy.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) /***************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * Adaptive Proportion Test
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * This test complies with SP800-90B section 4.4.2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) ***************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * Reset the APT counter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * @ec [in] Reference to entropy collector
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static void jent_apt_reset(struct rand_data *ec, unsigned int delta_masked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) /* Reset APT counter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) ec->apt_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) ec->apt_base = delta_masked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) ec->apt_observations = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * Insert a new entropy event into APT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * @ec [in] Reference to entropy collector
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * @delta_masked [in] Masked time delta to process
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) static void jent_apt_insert(struct rand_data *ec, unsigned int delta_masked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) /* Initialize the base reference */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (!ec->apt_base_set) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) ec->apt_base = delta_masked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) ec->apt_base_set = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (delta_masked == ec->apt_base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) ec->apt_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) if (ec->apt_count >= JENT_APT_CUTOFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) ec->health_failure = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) ec->apt_observations++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) if (ec->apt_observations >= JENT_APT_WINDOW_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) jent_apt_reset(ec, delta_masked);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) /***************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * Stuck Test and its use as Repetition Count Test
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * The Jitter RNG uses an enhanced version of the Repetition Count Test
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * (RCT) specified in SP800-90B section 4.4.1. Instead of counting identical
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * back-to-back values, the input to the RCT is the counting of the stuck
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * values during the generation of one Jitter RNG output block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * The RCT is applied with an alpha of 2^{-30} compliant to FIPS 140-2 IG 9.8.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * During the counting operation, the Jitter RNG always calculates the RCT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * cut-off value of C. If that value exceeds the allowed cut-off value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) * the Jitter RNG output block will be calculated completely but discarded at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) * the end. The caller of the Jitter RNG is informed with an error code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) ***************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * Repetition Count Test as defined in SP800-90B section 4.4.1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) * @ec [in] Reference to entropy collector
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) * @stuck [in] Indicator whether the value is stuck
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) static void jent_rct_insert(struct rand_data *ec, int stuck)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * If we have a count less than zero, a previous RCT round identified
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * a failure. We will not overwrite it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (ec->rct_count < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (stuck) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) ec->rct_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) * The cutoff value is based on the following consideration:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) * alpha = 2^-30 as recommended in FIPS 140-2 IG 9.8.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) * In addition, we require an entropy value H of 1/OSR as this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) * is the minimum entropy required to provide full entropy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * Note, we collect 64 * OSR deltas for inserting them into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * the entropy pool which should then have (close to) 64 bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * of entropy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * Note, ec->rct_count (which equals to value B in the pseudo
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * code of SP800-90B section 4.4.1) starts with zero. Hence
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * we need to subtract one from the cutoff value as calculated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) * following SP800-90B.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) if ((unsigned int)ec->rct_count >= (31 * ec->osr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) ec->rct_count = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) ec->health_failure = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) ec->rct_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) * Is there an RCT health test failure?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * @ec [in] Reference to entropy collector
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) * @return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) * 0 No health test failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * 1 Permanent health test failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) static int jent_rct_failure(struct rand_data *ec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (ec->rct_count < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) static inline __u64 jent_delta(__u64 prev, __u64 next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) #define JENT_UINT64_MAX (__u64)(~((__u64) 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) return (prev < next) ? (next - prev) :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) (JENT_UINT64_MAX - prev + 1 + next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) * Stuck test by checking the:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) * 1st derivative of the jitter measurement (time delta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) * 2nd derivative of the jitter measurement (delta of time deltas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) * 3rd derivative of the jitter measurement (delta of delta of time deltas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * All values must always be non-zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * @ec [in] Reference to entropy collector
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) * @current_delta [in] Jitter time delta
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) * @return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) * 0 jitter measurement not stuck (good bit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) * 1 jitter measurement stuck (reject bit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) static int jent_stuck(struct rand_data *ec, __u64 current_delta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) __u64 delta2 = jent_delta(ec->last_delta, current_delta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) __u64 delta3 = jent_delta(ec->last_delta2, delta2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) ec->last_delta = current_delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) ec->last_delta2 = delta2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) * Insert the result of the comparison of two back-to-back time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) * deltas.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) jent_apt_insert(ec, current_delta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (!current_delta || !delta2 || !delta3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) /* RCT with a stuck bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) jent_rct_insert(ec, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) /* RCT with a non-stuck bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) jent_rct_insert(ec, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * Report any health test failures
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) * @ec [in] Reference to entropy collector
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) * @return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) * 0 No health test failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) * 1 Permanent health test failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) static int jent_health_failure(struct rand_data *ec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) /* Test is only enabled in FIPS mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (!jent_fips_enabled())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) return ec->health_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) /***************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) * Noise sources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) ***************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) * Update of the loop count used for the next round of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) * an entropy collection.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) * Input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) * @ec entropy collector struct -- may be NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) * @bits is the number of low bits of the timer to consider
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) * @min is the number of bits we shift the timer value to the right at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) * the end to make sure we have a guaranteed minimum value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) * @return Newly calculated loop counter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) static __u64 jent_loop_shuffle(struct rand_data *ec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) unsigned int bits, unsigned int min)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) __u64 time = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) __u64 shuffle = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) unsigned int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) unsigned int mask = (1<<bits) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) jent_get_nstime(&time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) * Mix the current state of the random number into the shuffle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) * calculation to balance that shuffle a bit more.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (ec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) time ^= ec->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) * We fold the time value as much as possible to ensure that as many
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) * bits of the time stamp are included as possible.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) for (i = 0; ((DATA_SIZE_BITS + bits - 1) / bits) > i; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) shuffle ^= time & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) time = time >> bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) * We add a lower boundary value to ensure we have a minimum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) * RNG loop count.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) return (shuffle + (1<<min));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) * CPU Jitter noise source -- this is the noise source based on the CPU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) * execution time jitter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) * This function injects the individual bits of the time value into the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) * entropy pool using an LFSR.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) * The code is deliberately inefficient with respect to the bit shifting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) * and shall stay that way. This function is the root cause why the code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) * shall be compiled without optimization. This function not only acts as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) * folding operation, but this function's execution is used to measure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) * the CPU execution time jitter. Any change to the loop in this function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) * implies that careful retesting must be done.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) * @ec [in] entropy collector struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) * @time [in] time stamp to be injected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) * @loop_cnt [in] if a value not equal to 0 is set, use the given value as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) * number of loops to perform the folding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) * @stuck [in] Is the time stamp identified as stuck?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) * Output:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) * updated ec->data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) * @return Number of loops the folding operation is performed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) static void jent_lfsr_time(struct rand_data *ec, __u64 time, __u64 loop_cnt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) int stuck)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) __u64 j = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) __u64 new = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) #define MAX_FOLD_LOOP_BIT 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) #define MIN_FOLD_LOOP_BIT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) __u64 fold_loop_cnt =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) jent_loop_shuffle(ec, MAX_FOLD_LOOP_BIT, MIN_FOLD_LOOP_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) * testing purposes -- allow test app to set the counter, not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) * needed during runtime
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) if (loop_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) fold_loop_cnt = loop_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) for (j = 0; j < fold_loop_cnt; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) new = ec->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) for (i = 1; (DATA_SIZE_BITS) >= i; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) __u64 tmp = time << (DATA_SIZE_BITS - i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) tmp = tmp >> (DATA_SIZE_BITS - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) * Fibonacci LSFR with polynomial of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) * x^64 + x^61 + x^56 + x^31 + x^28 + x^23 + 1 which is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) * primitive according to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) * http://poincare.matf.bg.ac.rs/~ezivkovm/publications/primpol1.pdf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) * (the shift values are the polynomial values minus one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) * due to counting bits from 0 to 63). As the current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) * position is always the LSB, the polynomial only needs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) * to shift data in from the left without wrap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) tmp ^= ((new >> 63) & 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) tmp ^= ((new >> 60) & 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) tmp ^= ((new >> 55) & 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) tmp ^= ((new >> 30) & 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) tmp ^= ((new >> 27) & 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) tmp ^= ((new >> 22) & 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) new <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) new ^= tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) * If the time stamp is stuck, do not finally insert the value into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) * the entropy pool. Although this operation should not do any harm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) * even when the time stamp has no entropy, SP800-90B requires that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) * any conditioning operation (SP800-90B considers the LFSR to be a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) * conditioning operation) to have an identical amount of input
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) * data according to section 3.1.5.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (!stuck)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) ec->data = new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) * Memory Access noise source -- this is a noise source based on variations in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) * memory access times
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) * This function performs memory accesses which will add to the timing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) * variations due to an unknown amount of CPU wait states that need to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) * added when accessing memory. The memory size should be larger than the L1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) * caches as outlined in the documentation and the associated testing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) * The L1 cache has a very high bandwidth, albeit its access rate is usually
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) * slower than accessing CPU registers. Therefore, L1 accesses only add minimal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) * variations as the CPU has hardly to wait. Starting with L2, significant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) * variations are added because L2 typically does not belong to the CPU any more
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) * and therefore a wider range of CPU wait states is necessary for accesses.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) * L3 and real memory accesses have even a wider range of wait states. However,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) * to reliably access either L3 or memory, the ec->mem memory must be quite
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) * large which is usually not desirable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) * @ec [in] Reference to the entropy collector with the memory access data -- if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) * the reference to the memory block to be accessed is NULL, this noise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) * source is disabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) * @loop_cnt [in] if a value not equal to 0 is set, use the given value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) * number of loops to perform the LFSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) static void jent_memaccess(struct rand_data *ec, __u64 loop_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) unsigned int wrap = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) __u64 i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) #define MAX_ACC_LOOP_BIT 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) #define MIN_ACC_LOOP_BIT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) __u64 acc_loop_cnt =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) jent_loop_shuffle(ec, MAX_ACC_LOOP_BIT, MIN_ACC_LOOP_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) if (NULL == ec || NULL == ec->mem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) wrap = ec->memblocksize * ec->memblocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) * testing purposes -- allow test app to set the counter, not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) * needed during runtime
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (loop_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) acc_loop_cnt = loop_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) for (i = 0; i < (ec->memaccessloops + acc_loop_cnt); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) unsigned char *tmpval = ec->mem + ec->memlocation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) * memory access: just add 1 to one byte,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) * wrap at 255 -- memory access implies read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) * from and write to memory location
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) *tmpval = (*tmpval + 1) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) * Addition of memblocksize - 1 to pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) * with wrap around logic to ensure that every
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) * memory location is hit evenly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) ec->memlocation = ec->memlocation + ec->memblocksize - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) ec->memlocation = ec->memlocation % wrap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) /***************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) * Start of entropy processing logic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) ***************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) * This is the heart of the entropy generation: calculate time deltas and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) * use the CPU jitter in the time deltas. The jitter is injected into the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) * entropy pool.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) * WARNING: ensure that ->prev_time is primed before using the output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) * of this function! This can be done by calling this function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) * and not using its result.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) * @ec [in] Reference to entropy collector
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) * @return result of stuck test
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) static int jent_measure_jitter(struct rand_data *ec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) __u64 time = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) __u64 current_delta = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) int stuck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) /* Invoke one noise source before time measurement to add variations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) jent_memaccess(ec, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) * Get time stamp and calculate time delta to previous
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) * invocation to measure the timing variations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) jent_get_nstime(&time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) current_delta = jent_delta(ec->prev_time, time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) ec->prev_time = time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) /* Check whether we have a stuck measurement. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) stuck = jent_stuck(ec, current_delta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) /* Now call the next noise sources which also injects the data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) jent_lfsr_time(ec, current_delta, 0, stuck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) return stuck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) * Generator of one 64 bit random number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) * Function fills rand_data->data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) * @ec [in] Reference to entropy collector
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) static void jent_gen_entropy(struct rand_data *ec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) unsigned int k = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) /* priming of the ->prev_time value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) jent_measure_jitter(ec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) /* If a stuck measurement is received, repeat measurement */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) if (jent_measure_jitter(ec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) * We multiply the loop value with ->osr to obtain the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) * oversampling rate requested by the caller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (++k >= (DATA_SIZE_BITS * ec->osr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) * Entry function: Obtain entropy for the caller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) * This function invokes the entropy gathering logic as often to generate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) * as many bytes as requested by the caller. The entropy gathering logic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) * creates 64 bit per invocation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) * This function truncates the last 64 bit entropy value output to the exact
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) * size specified by the caller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) * @ec [in] Reference to entropy collector
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) * @data [in] pointer to buffer for storing random data -- buffer must already
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) * exist
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) * @len [in] size of the buffer, specifying also the requested number of random
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) * in bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) * @return 0 when request is fulfilled or an error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) * The following error codes can occur:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) * -1 entropy_collector is NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) * -2 RCT failed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) * -3 APT test failed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) int jent_read_entropy(struct rand_data *ec, unsigned char *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) unsigned int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) unsigned char *p = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) if (!ec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) while (0 < len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) unsigned int tocopy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) jent_gen_entropy(ec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) if (jent_health_failure(ec)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) if (jent_rct_failure(ec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) ret = -2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) ret = -3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) * Re-initialize the noise source
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) * If the health test fails, the Jitter RNG remains
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) * in failure state and will return a health failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) * during next invocation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) if (jent_entropy_init())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) /* Set APT to initial state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) jent_apt_reset(ec, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) ec->apt_base_set = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) /* Set RCT to initial state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) ec->rct_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) /* Re-enable Jitter RNG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) ec->health_failure = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) * Return the health test failure status to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) * caller as the generated value is not appropriate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) if ((DATA_SIZE_BITS / 8) < len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) tocopy = (DATA_SIZE_BITS / 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) tocopy = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) jent_memcpy(p, &ec->data, tocopy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) len -= tocopy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) p += tocopy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) /***************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) * Initialization logic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) ***************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) struct rand_data *jent_entropy_collector_alloc(unsigned int osr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) unsigned int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) struct rand_data *entropy_collector;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) entropy_collector = jent_zalloc(sizeof(struct rand_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) if (!entropy_collector)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) if (!(flags & JENT_DISABLE_MEMORY_ACCESS)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) /* Allocate memory for adding variations based on memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) * access
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) entropy_collector->mem = jent_zalloc(JENT_MEMORY_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) if (!entropy_collector->mem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) jent_zfree(entropy_collector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) entropy_collector->memblocksize = JENT_MEMORY_BLOCKSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) entropy_collector->memblocks = JENT_MEMORY_BLOCKS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) entropy_collector->memaccessloops = JENT_MEMORY_ACCESSLOOPS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) /* verify and set the oversampling rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) if (0 == osr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) osr = 1; /* minimum sampling rate is 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) entropy_collector->osr = osr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) /* fill the data pad with non-zero values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) jent_gen_entropy(entropy_collector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) return entropy_collector;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) void jent_entropy_collector_free(struct rand_data *entropy_collector)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) jent_zfree(entropy_collector->mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) entropy_collector->mem = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) jent_zfree(entropy_collector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) int jent_entropy_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) __u64 delta_sum = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) __u64 old_delta = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) unsigned int nonstuck = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) int time_backwards = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) int count_mod = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) int count_stuck = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) struct rand_data ec = { 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) /* Required for RCT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) ec.osr = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) /* We could perform statistical tests here, but the problem is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) * that we only have a few loop counts to do testing. These
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) * loop counts may show some slight skew and we produce
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) * false positives.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) * Moreover, only old systems show potentially problematic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) * jitter entropy that could potentially be caught here. But
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) * the RNG is intended for hardware that is available or widely
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) * used, but not old systems that are long out of favor. Thus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) * no statistical tests.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) * We could add a check for system capabilities such as clock_getres or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) * check for CONFIG_X86_TSC, but it does not make much sense as the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) * following sanity checks verify that we have a high-resolution
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) * timer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) * TESTLOOPCOUNT needs some loops to identify edge systems. 100 is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) * definitely too little.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) * SP800-90B requires at least 1024 initial test cycles.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) #define TESTLOOPCOUNT 1024
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) #define CLEARCACHE 100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) for (i = 0; (TESTLOOPCOUNT + CLEARCACHE) > i; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) __u64 time = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) __u64 time2 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) __u64 delta = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) unsigned int lowdelta = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) int stuck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) /* Invoke core entropy collection logic */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) jent_get_nstime(&time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) ec.prev_time = time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) jent_lfsr_time(&ec, time, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) jent_get_nstime(&time2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) /* test whether timer works */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) if (!time || !time2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) return JENT_ENOTIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) delta = jent_delta(time, time2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) * test whether timer is fine grained enough to provide
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) * delta even when called shortly after each other -- this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) * implies that we also have a high resolution timer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) if (!delta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) return JENT_ECOARSETIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) stuck = jent_stuck(&ec, delta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) * up to here we did not modify any variable that will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) * evaluated later, but we already performed some work. Thus we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) * already have had an impact on the caches, branch prediction,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) * etc. with the goal to clear it to get the worst case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) * measurements.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) if (CLEARCACHE > i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) if (stuck)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) count_stuck++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) nonstuck++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) * Ensure that the APT succeeded.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) * With the check below that count_stuck must be less
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) * than 10% of the overall generated raw entropy values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) * it is guaranteed that the APT is invoked at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) * floor((TESTLOOPCOUNT * 0.9) / 64) == 14 times.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) if ((nonstuck % JENT_APT_WINDOW_SIZE) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) jent_apt_reset(&ec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) delta & JENT_APT_WORD_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) if (jent_health_failure(&ec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) return JENT_EHEALTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) /* Validate RCT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) if (jent_rct_failure(&ec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) return JENT_ERCT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) /* test whether we have an increasing timer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) if (!(time2 > time))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) time_backwards++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) /* use 32 bit value to ensure compilation on 32 bit arches */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) lowdelta = time2 - time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) if (!(lowdelta % 100))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) count_mod++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) * ensure that we have a varying delta timer which is necessary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) * for the calculation of entropy -- perform this check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) * only after the first loop is executed as we need to prime
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) * the old_data value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) if (delta > old_delta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) delta_sum += (delta - old_delta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) delta_sum += (old_delta - delta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) old_delta = delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) * we allow up to three times the time running backwards.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) * CLOCK_REALTIME is affected by adjtime and NTP operations. Thus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) * if such an operation just happens to interfere with our test, it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) * should not fail. The value of 3 should cover the NTP case being
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) * performed during our test run.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) if (3 < time_backwards)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) return JENT_ENOMONOTONIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) * Variations of deltas of time must on average be larger
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) * than 1 to ensure the entropy estimation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) * implied with 1 is preserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) if ((delta_sum) <= 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) return JENT_EVARVAR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) * Ensure that we have variations in the time stamp below 10 for at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) * least 10% of all checks -- on some platforms, the counter increments
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) * in multiples of 100, but not always
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) if ((TESTLOOPCOUNT/10 * 9) < count_mod)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) return JENT_ECOARSETIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) * If we have more than 90% stuck results, then this Jitter RNG is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) * likely to not work well.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) if ((TESTLOOPCOUNT/10 * 9) < count_stuck)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) return JENT_ESTUCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) }