Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 506

kernel-2.6.18-238.el5.src.rpm

From: Neil Horman <nhorman@redhat.com>
Date: Sat, 13 Jun 2009 14:19:10 -0400
Subject: [crypto] add continuous test to hw rng in FIPS mode
Message-id: 20090613181910.GB24861@localhost.localdomain
O-Subject: Re: crypto: add continuous test to hw rng in FIPS mode (bz 504218)
Bugzilla: 504218
RH-Acked-by: James Morris <jmorris@redhat.com>
RH-Acked-by: Jarod Wilson <jarod@redhat.com>

Hey All-
        Recent info from atsec indicates that we need a continuous test on
our
hw rng when operating in FIPS mode.  This is a backport of the patch which I
currently have undergoing review upstream.  It provides a continuous test in
which each block of random data extracted from an entropy pool is compared
against the last block extracted, and the system panics if a repetition is
found.  Satisfies bz 504218

Neil

diff --git a/crypto/internal.h b/crypto/internal.h
index c7c68f4..3925f4b 100644
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -23,6 +23,7 @@
 #include <linux/rwsem.h>
 #include <linux/slab.h>
 #include <asm/kmap_types.h>
+#include <linux/fips.h>
 
 /* Crypto notification events. */
 enum {
diff --git a/drivers/char/random.c b/drivers/char/random.c
index b40d73d..7b97b3c 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -239,6 +239,7 @@
 #include <linux/spinlock.h>
 #include <linux/percpu.h>
 #include <linux/cryptohash.h>
+#include <linux/fips.h>
 
 #include <asm/processor.h>
 #include <asm/uaccess.h>
@@ -406,6 +407,7 @@ struct entropy_store {
 	unsigned add_ptr;
 	int entropy_count;
 	int input_rotate;
+	__u8 *last_data;
 };
 
 static __u32 input_pool_data[INPUT_POOL_WORDS];
@@ -806,12 +808,21 @@ static ssize_t extract_entropy(struct entropy_store *r, void * buf,
 {
 	ssize_t ret = 0, i;
 	__u8 tmp[EXTRACT_SIZE];
+	unsigned long flags;
 
 	xfer_secondary_pool(r, nbytes);
 	nbytes = account(r, nbytes, min, reserved);
 
 	while (nbytes) {
 		extract_buf(r, tmp);
+
+		if (r->last_data) {
+			spin_lock_irqsave(&r->lock, flags);
+			if (!memcmp(tmp, r->last_data, EXTRACT_SIZE))
+				panic("Hardware RNG duplicated output!\n");
+			memcpy(r->last_data, tmp, EXTRACT_SIZE);
+			spin_unlock_irqrestore(&r->lock, flags);
+		}
 		i = min_t(int, nbytes, EXTRACT_SIZE);
 		memcpy(buf, tmp, i);
 		nbytes -= i;
@@ -896,6 +907,13 @@ static void init_std_data(struct entropy_store *r)
 	add_entropy_words(r, (__u32 *)&tv, sizeof(tv)/4);
 	add_entropy_words(r, (__u32 *)&system_utsname,
 			  sizeof(system_utsname)/4);
+
+	/* Enable continuous test in fips mode */
+	if (fips_enabled) {
+		r->last_data = kmalloc(EXTRACT_SIZE, GFP_KERNEL);
+		if (!r->last_data)
+			panic("RNG self test failed to init!\n");
+	}
 }
 
 static int __init rand_initialize(void)
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index 0280ec0..c308eed 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -22,14 +22,9 @@
 #include <linux/types.h>
 #include <linux/list.h>
 #include <linux/string.h>
+#include <linux/fips.h>
 #include <asm/page.h>
 
-#ifdef CONFIG_CRYPTO_FIPS
-extern int fips_enabled;
-#else
-#define fips_enabled 0
-#endif
-
 /*
  * Algorithm masks and types.
  */
diff --git a/include/linux/fips.h b/include/linux/fips.h
new file mode 100644
index 0000000..f8fb07b
--- /dev/null
+++ b/include/linux/fips.h
@@ -0,0 +1,10 @@
+#ifndef _FIPS_H
+#define _FIPS_H
+
+#ifdef CONFIG_CRYPTO_FIPS
+extern int fips_enabled;
+#else
+#define fips_enabled 0
+#endif
+
+#endif