Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

random: Add optional continuous repetition test to entropy store based rngs

FIPS-140 requires that all random number generators implement continuous self
tests in which each extracted block of data is compared against the last block
for repetition. The ansi_cprng implements such a test, but it would be nice if
the hw rng's did the same thing. Obviously its not something thats always
needed, but it seems like it would be a nice feature to have on occasion. I've
written the below patch which allows individual entropy stores to be flagged as
desiring a continuous test to be run on them as is extracted. By default this
option is off, but is enabled in the event that fips mode is selected during
bootup.

Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
Acked-by: Matt Mackall <mpm@selenic.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Neil Horman and committed by
Herbert Xu
5b739ef8 b6f34d44

+25 -6
+1 -6
crypto/internal.h
··· 25 25 #include <linux/notifier.h> 26 26 #include <linux/rwsem.h> 27 27 #include <linux/slab.h> 28 - 29 - #ifdef CONFIG_CRYPTO_FIPS 30 - extern int fips_enabled; 31 - #else 32 - #define fips_enabled 0 33 - #endif 28 + #include <linux/fips.h> 34 29 35 30 /* Crypto notification events. */ 36 31 enum {
+14
drivers/char/random.c
··· 240 240 #include <linux/spinlock.h> 241 241 #include <linux/percpu.h> 242 242 #include <linux/cryptohash.h> 243 + #include <linux/fips.h> 243 244 244 245 #ifdef CONFIG_GENERIC_HARDIRQS 245 246 # include <linux/irq.h> ··· 414 413 unsigned add_ptr; 415 414 int entropy_count; 416 415 int input_rotate; 416 + __u8 *last_data; 417 417 }; 418 418 419 419 static __u32 input_pool_data[INPUT_POOL_WORDS]; ··· 854 852 { 855 853 ssize_t ret = 0, i; 856 854 __u8 tmp[EXTRACT_SIZE]; 855 + unsigned long flags; 857 856 858 857 xfer_secondary_pool(r, nbytes); 859 858 nbytes = account(r, nbytes, min, reserved); 860 859 861 860 while (nbytes) { 862 861 extract_buf(r, tmp); 862 + 863 + if (r->last_data) { 864 + spin_lock_irqsave(&r->lock, flags); 865 + if (!memcmp(tmp, r->last_data, EXTRACT_SIZE)) 866 + panic("Hardware RNG duplicated output!\n"); 867 + memcpy(r->last_data, tmp, EXTRACT_SIZE); 868 + spin_unlock_irqrestore(&r->lock, flags); 869 + } 863 870 i = min_t(int, nbytes, EXTRACT_SIZE); 864 871 memcpy(buf, tmp, i); 865 872 nbytes -= i; ··· 951 940 now = ktime_get_real(); 952 941 mix_pool_bytes(r, &now, sizeof(now)); 953 942 mix_pool_bytes(r, utsname(), sizeof(*(utsname()))); 943 + /* Enable continuous test in fips mode */ 944 + if (fips_enabled) 945 + r->last_data = kmalloc(EXTRACT_SIZE, GFP_KERNEL); 954 946 } 955 947 956 948 static int rand_initialize(void)
+10
include/linux/fips.h
··· 1 + #ifndef _FIPS_H 2 + #define _FIPS_H 3 + 4 + #ifdef CONFIG_CRYPTO_FIPS 5 + extern int fips_enabled; 6 + #else 7 + #define fips_enabled 0 8 + #endif 9 + 10 + #endif