Sophie

Sophie

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

kernel-2.6.18-238.el5.src.rpm

From: Neil Horman <nhorman@redhat.com>
Date: Fri, 11 Sep 2009 16:35:50 -0400
Subject: [misc] fix RNG to not use first generated random block
Message-id: 20090911203550.GO20261@hmsreliant.think-freely.org
O-Subject: [RHEL5]: update RNG to not use first generated random block (bz 522860)
Bugzilla: 522860
RH-Acked-by: Jarod Wilson <jarod@redhat.com>
RH-Acked-by: Prarit Bhargava <prarit@redhat.com>

In FIPS mode, RNG's are required to not return the first block of random data
they generate, but rather save it to seed the repetition check.  This patch
brings our standard RNG into conformance.  Note that it is completely untested,
but it was requested that it go into a test build this weekend.  I'll have test
results for this patch over the weekend or on monday AM.  This is for the
resolution of bz 522860

Neil

diff --git a/drivers/char/random.c b/drivers/char/random.c
index 7b97b3c..3fb4ec7 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -392,6 +392,12 @@ module_param(debug, bool, 0644);
  * storing entropy in an entropy pool.
  *
  **********************************************************************/
+#define EXTRACT_SIZE 10
+#define REP_CHECK_BLOCK_COPIED 1
+struct repetition_check {
+	__u8 last_data[EXTRACT_SIZE];
+	__u8 flags;
+};
 
 struct entropy_store;
 struct entropy_store {
@@ -407,7 +413,7 @@ struct entropy_store {
 	unsigned add_ptr;
 	int entropy_count;
 	int input_rotate;
-	__u8 *last_data;
+	struct repetition_check *rep;
 };
 
 static __u32 input_pool_data[INPUT_POOL_WORDS];
@@ -670,7 +676,6 @@ void add_disk_randomness(struct gendisk *disk)
 
 EXPORT_SYMBOL(add_disk_randomness);
 
-#define EXTRACT_SIZE 10
 
 /*********************************************************************
  *
@@ -810,18 +815,24 @@ static ssize_t extract_entropy(struct entropy_store *r, void * buf,
 	__u8 tmp[EXTRACT_SIZE];
 	unsigned long flags;
 
+repeat_extract:
 	xfer_secondary_pool(r, nbytes);
 	nbytes = account(r, nbytes, min, reserved);
 
 	while (nbytes) {
 		extract_buf(r, tmp);
 
-		if (r->last_data) {
+		if (r->rep) {
 			spin_lock_irqsave(&r->lock, flags);
-			if (!memcmp(tmp, r->last_data, EXTRACT_SIZE))
+			if ((r->rep->flags & REP_CHECK_BLOCK_COPIED) &&
+			    !memcmp(tmp, r->rep->last_data, EXTRACT_SIZE))
 				panic("Hardware RNG duplicated output!\n");
-			memcpy(r->last_data, tmp, EXTRACT_SIZE);
+			memcpy(r->rep->last_data, tmp, EXTRACT_SIZE);
 			spin_unlock_irqrestore(&r->lock, flags);
+			if (!(r->rep->flags & REP_CHECK_BLOCK_COPIED)) {
+				r->rep->flags |= REP_CHECK_BLOCK_COPIED;
+				goto repeat_extract;
+			}
 		}
 		i = min_t(int, nbytes, EXTRACT_SIZE);
 		memcpy(buf, tmp, i);
@@ -910,9 +921,10 @@ static void init_std_data(struct entropy_store *r)
 
 	/* Enable continuous test in fips mode */
 	if (fips_enabled) {
-		r->last_data = kmalloc(EXTRACT_SIZE, GFP_KERNEL);
-		if (!r->last_data)
+		r->rep = kmalloc(sizeof(struct repetition_check), GFP_KERNEL);
+		if (!r->rep)
 			panic("RNG self test failed to init!\n");
+		r->rep->flags = 0;
 	}
 }