2009-04-29 01:27:40

by Jarod Wilson

[permalink] [raw]
Subject: [PATCH 0/2] 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

--
Jarod Wilson
[email protected]


2009-04-29 01:28:19

by Jarod Wilson

[permalink] [raw]
Subject: [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.

Signed-off-by: Jarod Wilson <[email protected]>

---
crypto/testmgr.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
crypto/testmgr.h | 12 +++++++
2 files changed, 101 insertions(+), 0 deletions(-)

diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index d0cc85c..6330081 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -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[] = {
{
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 5add651..13d5a61 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -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];

/*


--
Jarod Wilson
[email protected]

2009-04-29 01:32:19

by Jarod Wilson

[permalink] [raw]
Subject: [PATCH 2/2] add ansi_cprng test vectors

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.

Signed-off-by: Jarod Wilson <[email protected]>

---
crypto/tcrypt.c | 4 ++
crypto/testmgr.c | 9 +++++
crypto/testmgr.h | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 109 insertions(+), 0 deletions(-)

diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index 0452036..ea3b8a8 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -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);
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 6330081..a0af8b8 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -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 = {
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 13d5a61..c1c709b 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -6208,6 +6208,102 @@ static struct aead_testvec aes_ccm_rfc4309_dec_tv_template[] = {
},
};

+/*
+ * ANSI X9.31 Continuous Pseudo-Random Number Generator (AES mode)
+ * test vectors, taken from Appendix B.2.9 and B.2.10:
+ * http://csrc.nist.gov/groups/STM/cavp/documents/rng/RNGVS.pdf
+ * Only AES-128 is supported at this time.
+ */
+#define ANSI_CPRNG_AES_TEST_VECTORS 6
+
+static struct cprng_testvec ansi_cprng_aes_tv_template[] = {
+ {
+ .key = "\xf3\xb1\x66\x6d\x13\x60\x72\x42"
+ "\xed\x06\x1c\xab\xb8\xd4\x62\x02",
+ .klen = 16,
+ .dt = "\xe6\xb3\xbe\x78\x2a\x23\xfa\x62"
+ "\xd7\x1d\x4a\xfb\xb0\xe9\x22\xf9",
+ .dtlen = 16,
+ .v = "\x80\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .vlen = 16,
+ .result = "\x59\x53\x1e\xd1\x3b\xb0\xc0\x55"
+ "\x84\x79\x66\x85\xc1\x2f\x76\x41",
+ .rlen = 16,
+ .loops = 1,
+ }, {
+ .key = "\xf3\xb1\x66\x6d\x13\x60\x72\x42"
+ "\xed\x06\x1c\xab\xb8\xd4\x62\x02",
+ .klen = 16,
+ .dt = "\xe6\xb3\xbe\x78\x2a\x23\xfa\x62"
+ "\xd7\x1d\x4a\xfb\xb0\xe9\x22\xfa",
+ .dtlen = 16,
+ .v = "\xc0\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .vlen = 16,
+ .result = "\x7c\x22\x2c\xf4\xca\x8f\xa2\x4c"
+ "\x1c\x9c\xb6\x41\xa9\xf3\x22\x0d",
+ .rlen = 16,
+ .loops = 1,
+ }, {
+ .key = "\xf3\xb1\x66\x6d\x13\x60\x72\x42"
+ "\xed\x06\x1c\xab\xb8\xd4\x62\x02",
+ .klen = 16,
+ .dt = "\xe6\xb3\xbe\x78\x2a\x23\xfa\x62"
+ "\xd7\x1d\x4a\xfb\xb0\xe9\x22\xfb",
+ .dtlen = 16,
+ .v = "\xe0\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .vlen = 16,
+ .result = "\x8a\xaa\x00\x39\x66\x67\x5b\xe5"
+ "\x29\x14\x28\x81\xa9\x4d\x4e\xc7",
+ .rlen = 16,
+ .loops = 1,
+ }, {
+ .key = "\xf3\xb1\x66\x6d\x13\x60\x72\x42"
+ "\xed\x06\x1c\xab\xb8\xd4\x62\x02",
+ .klen = 16,
+ .dt = "\xe6\xb3\xbe\x78\x2a\x23\xfa\x62"
+ "\xd7\x1d\x4a\xfb\xb0\xe9\x22\xfc",
+ .dtlen = 16,
+ .v = "\xf0\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .vlen = 16,
+ .result = "\x88\xdd\xa4\x56\x30\x24\x23\xe5"
+ "\xf6\x9d\xa5\x7e\x7b\x95\xc7\x3a",
+ .rlen = 16,
+ .loops = 1,
+ }, {
+ .key = "\xf3\xb1\x66\x6d\x13\x60\x72\x42"
+ "\xed\x06\x1c\xab\xb8\xd4\x62\x02",
+ .klen = 16,
+ .dt = "\xe6\xb3\xbe\x78\x2a\x23\xfa\x62"
+ "\xd7\x1d\x4a\xfb\xb0\xe9\x22\xfd",
+ .dtlen = 16,
+ .v = "\xf8\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .vlen = 16,
+ .result = "\x05\x25\x92\x46\x61\x79\xd2\xcb"
+ "\x78\xc4\x0b\x14\x0a\x5a\x9a\xc8",
+ .rlen = 16,
+ .loops = 1,
+ }, { /* Monte Carlo Test */
+ .key = "\x9f\x5b\x51\x20\x0b\xf3\x34\xb5"
+ "\xd8\x2b\xe8\xc3\x72\x55\xc8\x48",
+ .klen = 16,
+ .dt = "\x63\x76\xbb\xe5\x29\x02\xba\x3b"
+ "\x67\xc9\x25\xfa\x70\x1f\x11\xac",
+ .dtlen = 16,
+ .v = "\x57\x2c\x8e\x76\x87\x26\x47\x97"
+ "\x7e\x74\xfb\xdd\xc4\x95\x01\xd1",
+ .vlen = 16,
+ .result = "\x48\xe9\xbd\x0d\x06\xee\x18\xfb"
+ "\xe4\x57\x90\xd5\xc3\xfc\x9b\x73",
+ .rlen = 16,
+ .loops = 10000,
+ },
+};
+
/* Cast5 test vectors from RFC 2144 */
#define CAST5_ENC_TEST_VECTORS 3
#define CAST5_DEC_TEST_VECTORS 3


--
Jarod Wilson
[email protected]

2009-04-29 10:55:09

by Neil Horman

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

On Tue, Apr 28, 2009 at 09:28:13PM -0400, Jarod Wilson wrote:
> 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.
>
> Signed-off-by: Jarod Wilson <[email protected]>
>
Thanks Jarod!
Acked-by: Neil Horman <[email protected]>


2009-04-29 10:56:24

by Neil Horman

[permalink] [raw]
Subject: Re: [PATCH 2/2] add ansi_cprng test vectors

On Tue, Apr 28, 2009 at 09:32:10PM -0400, Jarod Wilson wrote:
> 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.
>
> Signed-off-by: Jarod Wilson <[email protected]>
>
Acked-by: Neil Horman <[email protected]>
>

2009-05-04 11:48:08

by Herbert Xu

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

On Wed, Apr 29, 2009 at 06:55:01AM -0400, Neil Horman wrote:
> On Tue, Apr 28, 2009 at 09:28:13PM -0400, Jarod Wilson wrote:
> > 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.
> >
> > Signed-off-by: Jarod Wilson <[email protected]>
> >
> Thanks Jarod!
> Acked-by: Neil Horman <[email protected]>

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,
--
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