crypto: testmgr - fix testing OPTIONAL_KEY hash algorithms
authorEric Biggers <ebiggers@google.com>
Sun, 20 May 2018 05:07:41 +0000 (22:07 -0700)
committerHerbert Xu <herbert@gondor.apana.org.au>
Sat, 26 May 2018 16:12:10 +0000 (00:12 +0800)
Since testmgr uses a single tfm for all tests of each hash algorithm,
once a key is set the tfm won't be unkeyed anymore.  But with crc32 and
crc32c, the key is really the "default initial state" and is optional;
those algorithms should have both keyed and unkeyed test vectors, to
verify that implementations use the correct default key.

Simply listing the unkeyed test vectors first isn't guaranteed to work
yet because testmgr makes multiple passes through the test vectors.
crc32c does have an unkeyed test vector listed first currently, but it
only works by chance because the last crc32c test vector happens to use
a key that is the same as the default key.

Therefore, teach testmgr to split hash test vectors into unkeyed and
keyed sections, and do all the unkeyed ones before the keyed ones.

Signed-off-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
crypto/testmgr.c

index 7e57530ecd521b6011bde27d23d429b33f580a2c..d3335d347e100fa099912dba1359903b51689895 100644 (file)
@@ -1798,8 +1798,9 @@ static int alg_test_comp(const struct alg_test_desc *desc, const char *driver,
        return err;
 }
 
-static int alg_test_hash(const struct alg_test_desc *desc, const char *driver,
-                        u32 type, u32 mask)
+static int __alg_test_hash(const struct hash_testvec *template,
+                          unsigned int tcount, const char *driver,
+                          u32 type, u32 mask)
 {
        struct crypto_ahash *tfm;
        int err;
@@ -1811,16 +1812,51 @@ static int alg_test_hash(const struct alg_test_desc *desc, const char *driver,
                return PTR_ERR(tfm);
        }
 
-       err = test_hash(tfm, desc->suite.hash.vecs,
-                       desc->suite.hash.count, true);
+       err = test_hash(tfm, template, tcount, true);
        if (!err)
-               err = test_hash(tfm, desc->suite.hash.vecs,
-                               desc->suite.hash.count, false);
-
+               err = test_hash(tfm, template, tcount, false);
        crypto_free_ahash(tfm);
        return err;
 }
 
+static int alg_test_hash(const struct alg_test_desc *desc, const char *driver,
+                        u32 type, u32 mask)
+{
+       const struct hash_testvec *template = desc->suite.hash.vecs;
+       unsigned int tcount = desc->suite.hash.count;
+       unsigned int nr_unkeyed, nr_keyed;
+       int err;
+
+       /*
+        * For OPTIONAL_KEY algorithms, we have to do all the unkeyed tests
+        * first, before setting a key on the tfm.  To make this easier, we
+        * require that the unkeyed test vectors (if any) are listed first.
+        */
+
+       for (nr_unkeyed = 0; nr_unkeyed < tcount; nr_unkeyed++) {
+               if (template[nr_unkeyed].ksize)
+                       break;
+       }
+       for (nr_keyed = 0; nr_unkeyed + nr_keyed < tcount; nr_keyed++) {
+               if (!template[nr_unkeyed + nr_keyed].ksize) {
+                       pr_err("alg: hash: test vectors for %s out of order, "
+                              "unkeyed ones must come first\n", desc->alg);
+                       return -EINVAL;
+               }
+       }
+
+       err = 0;
+       if (nr_unkeyed) {
+               err = __alg_test_hash(template, nr_unkeyed, driver, type, mask);
+               template += nr_unkeyed;
+       }
+
+       if (!err && nr_keyed)
+               err = __alg_test_hash(template, nr_keyed, driver, type, mask);
+
+       return err;
+}
+
 static int alg_test_crc32c(const struct alg_test_desc *desc,
                           const char *driver, u32 type, u32 mask)
 {