Skip to contentSkip to conversation

crypto: ansi_cprng self-test infra and vectors

PATCH In review Jarod Wilson 3 participants 6 messages Apr 29, 2009 – May 4, 2009

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover crypto: ansi_cprng self-test infra and vectors

To be able to use ansi_cprng in fips mode, we need to run ansi_cprng self-tests before it can be used.

[PATCH 1/2] add infrastructure for ansi_cprng self-tests [PATCH 2/2] add ansi_cprng test vectors

Signature · 2 lines
Jarod Wilson
[email protected]
#1 lore raw

PATCH 1/2 add infrastructure for ansi_cprng self-tests

Add some necessary infrastructure to make it possible to run self-tests for ansi_cprng. The bits are likely very specific to the ANSI X9.31 CPRNG in AES mode, and thus perhaps should be named more specifically if/when we grow additional CPRNG support...

Successfully tested against the cryptodev-2.6 tree and a Red Hat Enterprise Linux 5.x kernel with the follow-on patch that adds the actual test vectors.

---
 crypto/testmgr.c |   89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 crypto/testmgr.h |   12 +++++++
 2 files changed, 101 insertions(+), 0 deletions(-)
crypto/testmgr.c +89 -0
index d0cc85c..6330081 100644
@@ -19,6 +19,7 @@
 #include <linux/scatterlist.h>
 #include <linux/slab.h>
 #include <linux/string.h>
+#include <crypto/rng.h>
 
 #include "internal.h"
 #include "testmgr.h"
@@ -84,6 +85,11 @@ struct hash_test_suite {
 	unsigned int count;
 };
 
+struct cprng_test_suite {
+	struct cprng_testvec *vecs;
+	unsigned int count;
+};
+
 struct alg_test_desc {
 	const char *alg;
 	int (*test)(const struct alg_test_desc *desc, const char *driver,
@@ -95,6 +101,7 @@ struct alg_test_desc {
 		struct comp_test_suite comp;
 		struct pcomp_test_suite pcomp;
 		struct hash_test_suite hash;
+		struct cprng_test_suite cprng;
 	} suite;
 };
 
@@ -1089,6 +1096,68 @@ static int test_pcomp(struct crypto_pcomp *tfm,
 	return 0;
 }
 
+
+static int test_cprng(struct crypto_rng *tfm, struct cprng_testvec *template,
+		      unsigned int tcount)
+{
+	const char *algo = crypto_tfm_alg_driver_name(crypto_rng_tfm(tfm));
+	int err, i, j, seedsize;
+	u8 *seed;
+	char result[32];
+
+	seedsize = crypto_rng_seedsize(tfm);
+
+	seed = kmalloc(seedsize, GFP_KERNEL);
+	if (!seed) {
+		printk(KERN_ERR "alg: cprng: Failed to allocate seed space "
+		       "for %s\n", algo);
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < tcount; i++) {
+		memset(result, 0, 32);
+
+		memcpy(seed, template[i].v, template[i].vlen);
+		memcpy(seed + template[i].vlen, template[i].key,
+		       template[i].klen);
+		memcpy(seed + template[i].vlen + template[i].klen,
+		       template[i].dt, template[i].dtlen);
+
+		err = crypto_rng_reset(tfm, seed, seedsize);
+		if (err) {
+			printk(KERN_ERR "alg: cprng: Failed to reset rng "
+			       "for %s\n", algo);
+			goto out;
+		}
+
+		for (j = 0; j < template[i].loops; j++) {
+			err = crypto_rng_get_bytes(tfm, result,
+						   template[i].rlen);
+			if (err != template[i].rlen) {
+				printk(KERN_ERR "alg: cprng: Failed to obtain "
+				       "the correct amount of random data for "
+				       "%s (requested %d, got %d)\n", algo,
+				       template[i].rlen, err);
+				goto out;
+			}
+		}
+
+		err = memcmp(result, template[i].result,
+			     template[i].rlen);
+		if (err) {
+			printk(KERN_ERR "alg: cprng: Test %d failed for %s\n",
+			       i, algo);
+			hexdump(result, template[i].rlen);
+			err = -EINVAL;
+			goto out;
+		}
+	}
+
+out:
+	kfree(seed);
+	return err;
+}
+
 static int alg_test_aead(const struct alg_test_desc *desc, const char *driver,
 			 u32 type, u32 mask)
 {
@@ -1288,6 +1357,26 @@ out:
 	return err;
 }
 
+static int alg_test_cprng(const struct alg_test_desc *desc, const char *driver,
+			  u32 type, u32 mask)
+{
+	struct crypto_rng *rng;
+	int err;
+
+	rng = crypto_alloc_rng(driver, type, mask);
+	if (IS_ERR(rng)) {
+		printk(KERN_ERR "alg: cprng: Failed to load transform for %s: "
+		       "%ld\n", driver, PTR_ERR(rng));
+		return PTR_ERR(rng);
+	}
+
+	err = test_cprng(rng, desc->suite.cprng.vecs, desc->suite.cprng.count);
+
+	crypto_free_rng(rng);
+
+	return err;
+}
+
 /* Please keep this list sorted by algorithm name. */
 static const struct alg_test_desc alg_test_descs[] = {
 	{
crypto/testmgr.h +12 -0
index 5add651..13d5a61 100644
@@ -70,6 +70,18 @@ struct aead_testvec {
 	unsigned short rlen;
 };
 
+struct cprng_testvec {
+	char *key;
+	char *dt;
+	char *v;
+	char *result;
+	unsigned char klen;
+	unsigned short dtlen;
+	unsigned short vlen;
+	unsigned short rlen;
+	unsigned short loops;
+};
+
 static char zeroed_string[48];
 
 /*
Signature · 2 lines
Jarod Wilson
[email protected]
Acked-by on v1 1/2
#2 lore raw

Re: [PATCH 1/2] add infrastructure for ansi_cprng self-tests

Quoted 6 lines · Jarod Wilson

Add some necessary infrastructure to make it possible to run self-tests for ansi_cprng. The bits are likely very specific to the ANSI X9.31 CPRNG in AES mode, and thus perhaps should be named more specifically if/when we grow additional CPRNG support...

Quoted 6 lines

Successfully tested against the cryptodev-2.6 tree and a Red Hat Enterprise Linux 5.x kernel with the follow-on patch that adds the actual test vectors.

Thanks Jarod!

maintainer
#3 lore raw

Re: [PATCH 1/2] add infrastructure for ansi_cprng self-tests

Quoted 7 lines · Neil Horman
Quoted 6 lines · Jarod Wilson

Add some necessary infrastructure to make it possible to run self-tests for ansi_cprng. The bits are likely very specific to the ANSI X9.31 CPRNG in AES mode, and thus perhaps should be named more specifically if/when we grow additional CPRNG support...

Quoted 8 lines
Quoted 6 lines

Successfully tested against the cryptodev-2.6 tree and a Red Hat Enterprise Linux 5.x kernel with the follow-on patch that adds the actual test vectors.

Thanks Jarod!

Both patches applied. Thanks!

In future this should be moved to user-space where we can perform more complicated tests such as entropy testing.

Of course we need to finish the user-space API first :)

Cheers,

Signature · 4 lines
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
#4 lore raw

PATCH 2/2 add ansi_cprng test vectors

In reply to Jarod Wilson

Add ANSI X9.31 Continuous Pseudo-Random Number Generator (AES mode), aka 'ansi_cprng' test vectors, taken from Appendix B.2.9 and B.2.10 of the NIST RNGVS document, found here:
http://csrc.nist.gov/groups/STM/cavp/documents/rng/RNGVS.pdf

Successfully tested against both the cryptodev-2.6 tree and a Red Hat Enterprise Linux 5.4 kernel, via 'modprobe tcrypt mode=150'.

The selection of 150 was semi-arbitrary, didn't seem like it should go any place in particular, so I started a new range for rng tests.

---
 crypto/tcrypt.c  |    4 ++
 crypto/testmgr.c |    9 +++++
 crypto/testmgr.h |   96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 109 insertions(+), 0 deletions(-)
crypto/tcrypt.c +4 -0
index 0452036..ea3b8a8 100644
@@ -707,6 +707,10 @@ static void do_test(int m)
 		tcrypt_test("hmac(rmd160)");
 		break;
 
+	case 150:
+		tcrypt_test("ansi_cprng");
+		break;
+
 	case 200:
 		test_cipher_speed("ecb(aes)", ENCRYPT, sec, NULL, 0,
 				speed_template_16_24_32);
crypto/testmgr.c +9 -0
index 6330081..a0af8b8 100644
@@ -1380,6 +1380,15 @@ static int alg_test_cprng(const struct alg_test_desc *desc, const char *driver,
 /* Please keep this list sorted by algorithm name. */
 static const struct alg_test_desc alg_test_descs[] = {
 	{
+		.alg = "ansi_cprng",
+		.test = alg_test_cprng,
+		.suite = {
+			.cprng = {
+				.vecs = ansi_cprng_aes_tv_template,
+				.count = ANSI_CPRNG_AES_TEST_VECTORS
+			}
+		}
+	}, {
 		.alg = "cbc(aes)",
 		.test = alg_test_skcipher,
 		.suite = {
crypto/testmgr.h +96 -0

102 lines not on this page · raw message

Signature · 2 lines
Jarod Wilson
[email protected]
Acked-by on v1 2/2
#5 lore raw

Re: [PATCH 2/2] add ansi_cprng test vectors

Quoted 5 lines · Jarod Wilson

Add ANSI X9.31 Continuous Pseudo-Random Number Generator (AES mode), aka 'ansi_cprng' test vectors, taken from Appendix B.2.9 and B.2.10 of the NIST RNGVS document, found here:
http://csrc.nist.gov/groups/STM/cavp/documents/rng/RNGVS.pdf

Quoted 8 lines

Successfully tested against both the cryptodev-2.6 tree and a Red Hat Enterprise Linux 5.4 kernel, via 'modprobe tcrypt mode=150'.

The selection of 150 was semi-arbitrary, didn't seem like it should go any place in particular, so I started a new range for rng tests.

Quoted 1 line