Sophie

Sophie

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

kernel-2.6.18-238.el5.src.rpm

From: Neil Horman <nhorman@redhat.com>
Date: Fri, 23 Jan 2009 13:46:13 -0500
Subject: [crypto] bugfixes to ansi_cprng for fips compliance
Message-id: 20090123184613.GG24153@hmsendeavour.rdu.redhat.com
O-Subject: [RHEL5.4 PATCH] crypto: backport a few bugfixes to ansi_cprng for fips compliance
Bugzilla: 481175 469437
RH-Acked-by: Jarod Wilson <jarod@redhat.com>

Hey all-
	Below is a patch to backport a few upstream fixes to the ansi_cprng to
bring it into fips compliance.  Specifically

Allow the DT value of a cprng instance to be specified when reseeding
Upstream commit 2566578a6feb9d9e39da41326afe8ed6022db3c5

Force a panic if the continuous cprng self test fails
awaiting upstream review/acceptance

Set the NEED_RESET flag on a newly allocated instance of cprng
awaiting upstream rewview/acceptance

Neil

diff --git a/crypto/ansi_cprng.c b/crypto/ansi_cprng.c
index 246a1ba..c858f4f 100644
--- a/crypto/ansi_cprng.c
+++ b/crypto/ansi_cprng.c
@@ -132,10 +132,20 @@ static int _get_more_prng_bytes(struct prng_context *ctx)
 			 */
 			if (!memcmp(ctx->rand_data, ctx->last_rand_data,
 					DEFAULT_BLK_SZ)) {
-				printk(KERN_ERR
-					"ctx %p Failed repetition check!\n",
-					ctx);
-				ctx->flags |= PRNG_NEED_RESET;
+				if (fips_enabled) {
+					/* FIPS 140-2 requires that we disable
+					 * further use of crypto code if we fail
+					 * this test,  easiest way to do that
+					 * is panic the box
+					 */
+					panic("cprng %p failed continuity test",
+						ctx);  
+				} else {
+					printk(KERN_ERR
+						"ctx %p Failed repetition check!\n",
+						ctx);
+					ctx->flags |= PRNG_NEED_RESET;
+				}
 				return -EINVAL;
 			}
 			memcpy(ctx->last_rand_data, ctx->rand_data,
@@ -338,7 +348,16 @@ static int cprng_init(struct ncrypto_tfm *tfm)
 
 	spin_lock_init(&ctx->prng_lock);
 
-	return reset_prng_context(ctx, NULL, DEFAULT_PRNG_KSZ, NULL, NULL);
+	if (reset_prng_context(ctx, NULL, DEFAULT_PRNG_KSZ, NULL, NULL) < 0)
+		return -EINVAL;
+
+	/*
+ 	 * after allocation, we should always force the user to reset
+ 	 * so they don't inadvertently use the insecure default values
+ 	 * without specifying them intentially
+ 	 */
+	ctx->flags |= PRNG_NEED_RESET;
+	return 0;
 }
 
 static void cprng_exit(struct ncrypto_tfm *tfm)
@@ -354,15 +373,25 @@ static int cprng_get_random(struct crypto_rng *tfm, u8 *rdata,
 	return get_prng_bytes(rdata, dlen, prng);
 }
 
+/*
+ *  This is the cprng_registered reset method the seed value is
+ *  interpreted as the tuple { V KEY DT}
+ *  V and KEY are required during reset, and DT is optional, detected
+ *  as being present by testing the length of the seed
+ */
 static int cprng_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen)
 {
 	struct prng_context *prng = crypto_rng_ctx(tfm);
-	u8 *key = seed + DEFAULT_PRNG_KSZ;
+	u8 *key = seed + DEFAULT_BLK_SZ;
+	u8 *dt = NULL;
 
 	if (slen < DEFAULT_PRNG_KSZ + DEFAULT_BLK_SZ)
 		return -EINVAL;
 
-	reset_prng_context(prng, key, DEFAULT_PRNG_KSZ, seed, NULL);
+	if (slen >= (2 * DEFAULT_BLK_SZ + DEFAULT_PRNG_KSZ))
+		dt = key + DEFAULT_PRNG_KSZ;
+
+	reset_prng_context(prng, key, DEFAULT_PRNG_KSZ, seed, dt);
 
 	if (prng->flags & PRNG_NEED_RESET)
 		return -EINVAL;
@@ -394,7 +423,7 @@ static int __init prng_mod_init(void)
 
 	alg->rng_make_random = cprng_get_random;
 	alg->rng_reset = cprng_reset;
-	alg->seedsize = DEFAULT_PRNG_KSZ + DEFAULT_BLK_SZ;
+	alg->seedsize =	DEFAULT_PRNG_KSZ + 2*DEFAULT_BLK_SZ;
 
 	ret = ncrypto_register_alg(&rng_alg);