crypto: testmgr - Print self-test pass notices in fips mode
[safe/jmp/linux-2.6] / crypto / testmgr.c
index 84f9640..e76af78 100644 (file)
@@ -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,9 +1357,38 @@ 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[] = {
        {
+               .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 = {
@@ -1879,6 +1977,21 @@ static const struct alg_test_desc alg_test_descs[] = {
                        }
                }
        }, {
+               .alg = "rfc4309(ccm(aes))",
+               .test = alg_test_aead,
+               .suite = {
+                       .aead = {
+                               .enc = {
+                                       .vecs = aes_ccm_rfc4309_enc_tv_template,
+                                       .count = AES_CCM_4309_ENC_TEST_VECTORS
+                               },
+                               .dec = {
+                                       .vecs = aes_ccm_rfc4309_dec_tv_template,
+                                       .count = AES_CCM_4309_DEC_TEST_VECTORS
+                               }
+                       }
+               }
+       }, {
                .alg = "rmd128",
                .test = alg_test_hash,
                .suite = {
@@ -2107,7 +2220,8 @@ int alg_test(const char *driver, const char *alg, u32 type, u32 mask)
                if (i < 0)
                        goto notest;
 
-               return alg_test_cipher(alg_test_descs + i, driver, type, mask);
+               rc = alg_test_cipher(alg_test_descs + i, driver, type, mask);
+               goto test_done;
        }
 
        i = alg_find_test(alg);
@@ -2116,9 +2230,14 @@ int alg_test(const char *driver, const char *alg, u32 type, u32 mask)
 
        rc = alg_test_descs[i].test(alg_test_descs + i, driver,
                                      type, mask);
+test_done:
        if (fips_enabled && rc)
                panic("%s: %s alg self test failed in fips mode!\n", driver, alg);
 
+       if (fips_enabled && !rc)
+               printk(KERN_INFO "alg: self-tests for %s (%s) passed\n",
+                      driver, alg);
+
        return rc;
 
 notest: