crypto: tcrypt - Abort and only log if there is an error
[safe/jmp/linux-2.6] / crypto / tcrypt.c
index 2b52df7..97ec2bd 100644 (file)
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * 2007-11-13 Added GCM tests
- * 2007-11-13 Added AEAD support
- * 2007-11-06 Added SHA-224 and SHA-224-HMAC tests
- * 2006-12-07 Added SHA384 HMAC and SHA512 HMAC tests
- * 2004-08-09 Added cipher speed tests (Reyk Floeter <reyk@vantronix.net>)
- * 2003-09-14 Rewritten by Kartikey Mahendra Bhatt
- *
  */
 
+#include <crypto/hash.h>
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/module.h>
@@ -30,7 +24,6 @@
 #include <linux/scatterlist.h>
 #include <linux/string.h>
 #include <linux/crypto.h>
-#include <linux/highmem.h>
 #include <linux/moduleparam.h>
 #include <linux/jiffies.h>
 #include <linux/timex.h>
 #include "tcrypt.h"
 
 /*
- * Need to kmalloc() memory for testing kmap().
+ * Need slab memory for testing (size in number of pages).
  */
-#define TVMEMSIZE      16384
-#define XBUFSIZE       32768
+#define TVMEMSIZE      4
+#define XBUFSIZE       8
 
 /*
  * Indexes into the xbuf to simulate cross-page access.
  */
-#define IDX1           37
+#define IDX1           32
 #define IDX2           32400
 #define IDX3           1
 #define IDX4           8193
@@ -74,17 +67,17 @@ static unsigned int IDX[8] = { IDX1, IDX2, IDX3, IDX4, IDX5, IDX6, IDX7, IDX8 };
 static unsigned int sec;
 
 static int mode;
-static char *xbuf;
-static char *axbuf;
-static char *tvmem;
+static char *xbuf[XBUFSIZE];
+static char *axbuf[XBUFSIZE];
+static char *tvmem[TVMEMSIZE];
 
 static char *check[] = {
        "des", "md5", "des3_ede", "rot13", "sha1", "sha224", "sha256",
        "blowfish", "twofish", "serpent", "sha384", "sha512", "md4", "aes",
        "cast6", "arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea",
-       "arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea",
        "khazad", "wp512", "wp384", "wp256", "tnepres", "xeta",  "fcrypt",
-       "camellia", "seed", "salsa20", "lzo", NULL
+       "camellia", "seed", "salsa20", "rmd128", "rmd160", "rmd256", "rmd320",
+       "lzo", "cts", NULL
 };
 
 static void hexdump(unsigned char *buf, unsigned int len)
@@ -105,170 +98,199 @@ static void tcrypt_complete(struct crypto_async_request *req, int err)
        complete(&res->completion);
 }
 
-static void test_hash(char *algo, struct hash_testvec *template,
-                     unsigned int tcount)
+static int test_hash(char *algo, struct hash_testvec *template,
+                    unsigned int tcount)
 {
        unsigned int i, j, k, temp;
        struct scatterlist sg[8];
        char result[64];
-       struct crypto_hash *tfm;
-       struct hash_desc desc;
-       struct hash_testvec *hash_tv;
-       unsigned int tsize;
+       struct crypto_ahash *tfm;
+       struct ahash_request *req;
+       struct tcrypt_result tresult;
        int ret;
+       void *hash_buff;
 
-       printk("\ntesting %s\n", algo);
-
-       tsize = sizeof(struct hash_testvec);
-       tsize *= tcount;
-
-       if (tsize > TVMEMSIZE) {
-               printk("template (%u) too big for tvmem (%u)\n", tsize, TVMEMSIZE);
-               return;
-       }
-
-       memcpy(tvmem, template, tsize);
-       hash_tv = (void *)tvmem;
+       init_completion(&tresult.completion);
 
-       tfm = crypto_alloc_hash(algo, 0, CRYPTO_ALG_ASYNC);
+       tfm = crypto_alloc_ahash(algo, 0, 0);
        if (IS_ERR(tfm)) {
-               printk("failed to load transform for %s: %ld\n", algo,
-                      PTR_ERR(tfm));
-               return;
+               printk(KERN_ERR "alg: hash: Failed to load transform for %s: "
+                      "%ld\n", algo, PTR_ERR(tfm));
+               return PTR_ERR(tfm);
        }
 
-       desc.tfm = tfm;
-       desc.flags = 0;
+       req = ahash_request_alloc(tfm, GFP_KERNEL);
+       if (!req) {
+               printk(KERN_ERR "alg: hash: Failed to allocate request for "
+                      "%s\n", algo);
+               ret = -ENOMEM;
+               goto out_noreq;
+       }
+       ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+                                  tcrypt_complete, &tresult);
 
        for (i = 0; i < tcount; i++) {
-               printk("test %u:\n", i + 1);
                memset(result, 0, 64);
 
-               sg_init_one(&sg[0], hash_tv[i].plaintext, hash_tv[i].psize);
+               hash_buff = xbuf[0];
+
+               memcpy(hash_buff, template[i].plaintext, template[i].psize);
+               sg_init_one(&sg[0], hash_buff, template[i].psize);
 
-               if (hash_tv[i].ksize) {
-                       ret = crypto_hash_setkey(tfm, hash_tv[i].key,
-                                                hash_tv[i].ksize);
+               if (template[i].ksize) {
+                       crypto_ahash_clear_flags(tfm, ~0);
+                       ret = crypto_ahash_setkey(tfm, template[i].key,
+                                                 template[i].ksize);
                        if (ret) {
-                               printk("setkey() failed ret=%d\n", ret);
+                               printk(KERN_ERR "alg: hash: setkey failed on "
+                                      "test %d for %s: ret=%d\n", i + 1, algo,
+                                      -ret);
                                goto out;
                        }
                }
 
-               ret = crypto_hash_digest(&desc, sg, hash_tv[i].psize, result);
-               if (ret) {
-                       printk("digest () failed ret=%d\n", ret);
+               ahash_request_set_crypt(req, sg, result, template[i].psize);
+               ret = crypto_ahash_digest(req);
+               switch (ret) {
+               case 0:
+                       break;
+               case -EINPROGRESS:
+               case -EBUSY:
+                       ret = wait_for_completion_interruptible(
+                               &tresult.completion);
+                       if (!ret && !(ret = tresult.err)) {
+                               INIT_COMPLETION(tresult.completion);
+                               break;
+                       }
+                       /* fall through */
+               default:
+                       printk(KERN_ERR "alg: hash: digest failed on test %d "
+                              "for %s: ret=%d\n", i + 1, algo, -ret);
                        goto out;
                }
 
-               hexdump(result, crypto_hash_digestsize(tfm));
-               printk("%s\n",
-                      memcmp(result, hash_tv[i].digest,
-                             crypto_hash_digestsize(tfm)) ?
-                      "fail" : "pass");
+               if (memcmp(result, template[i].digest,
+                          crypto_ahash_digestsize(tfm))) {
+                       printk(KERN_ERR "alg: hash: Test %d failed for %s\n",
+                              i + 1, algo);
+                       hexdump(result, crypto_ahash_digestsize(tfm));
+                       ret = -EINVAL;
+                       goto out;
+               }
        }
 
-       printk("testing %s across pages\n", algo);
-
-       /* setup the dummy buffer first */
-       memset(xbuf, 0, XBUFSIZE);
-       memset(axbuf, 0, XBUFSIZE);
-
        j = 0;
        for (i = 0; i < tcount; i++) {
-               if (hash_tv[i].np) {
+               if (template[i].np) {
                        j++;
-                       printk("test %u:\n", j);
                        memset(result, 0, 64);
 
                        temp = 0;
-                       sg_init_table(sg, hash_tv[i].np);
-                       for (k = 0; k < hash_tv[i].np; k++) {
-                               memcpy(&xbuf[IDX[k]],
-                                      hash_tv[i].plaintext + temp,
-                                      hash_tv[i].tap[k]);
-                               temp += hash_tv[i].tap[k];
-                               sg_set_buf(&sg[k], &xbuf[IDX[k]],
-                                           hash_tv[i].tap[k]);
+                       sg_init_table(sg, template[i].np);
+                       for (k = 0; k < template[i].np; k++) {
+                               sg_set_buf(&sg[k],
+                                          memcpy(xbuf[IDX[k] >> PAGE_SHIFT] +
+                                                 offset_in_page(IDX[k]),
+                                                 template[i].plaintext + temp,
+                                                 template[i].tap[k]),
+                                          template[i].tap[k]);
+                               temp += template[i].tap[k];
                        }
 
-                       if (hash_tv[i].ksize) {
-                               ret = crypto_hash_setkey(tfm, hash_tv[i].key,
-                                                        hash_tv[i].ksize);
+                       if (template[i].ksize) {
+                               crypto_ahash_clear_flags(tfm, ~0);
+                               ret = crypto_ahash_setkey(tfm, template[i].key,
+                                                         template[i].ksize);
 
                                if (ret) {
-                                       printk("setkey() failed ret=%d\n", ret);
+                                       printk(KERN_ERR "alg: hash: setkey "
+                                              "failed on chunking test %d "
+                                              "for %s: ret=%d\n", j, algo,
+                                              -ret);
                                        goto out;
                                }
                        }
 
-                       ret = crypto_hash_digest(&desc, sg, hash_tv[i].psize,
-                                                result);
-                       if (ret) {
-                               printk("digest () failed ret=%d\n", ret);
+                       ahash_request_set_crypt(req, sg, result,
+                                               template[i].psize);
+                       ret = crypto_ahash_digest(req);
+                       switch (ret) {
+                       case 0:
+                               break;
+                       case -EINPROGRESS:
+                       case -EBUSY:
+                               ret = wait_for_completion_interruptible(
+                                       &tresult.completion);
+                               if (!ret && !(ret = tresult.err)) {
+                                       INIT_COMPLETION(tresult.completion);
+                                       break;
+                               }
+                               /* fall through */
+                       default:
+                               printk(KERN_ERR "alg: hash: digest failed "
+                                      "on chunking test %d for %s: "
+                                      "ret=%d\n", j, algo, -ret);
                                goto out;
                        }
 
-                       hexdump(result, crypto_hash_digestsize(tfm));
-                       printk("%s\n",
-                              memcmp(result, hash_tv[i].digest,
-                                     crypto_hash_digestsize(tfm)) ?
-                              "fail" : "pass");
+                       if (memcmp(result, template[i].digest,
+                                  crypto_ahash_digestsize(tfm))) {
+                               printk(KERN_ERR "alg: hash: Chunking test %d "
+                                      "failed for %s\n", j, algo);
+                               hexdump(result, crypto_ahash_digestsize(tfm));
+                               ret = -EINVAL;
+                               goto out;
+                       }
                }
        }
 
+       ret = 0;
+
 out:
-       crypto_free_hash(tfm);
+       ahash_request_free(req);
+out_noreq:
+       crypto_free_ahash(tfm);
+       return ret;
 }
 
-static void test_aead(char *algo, int enc, struct aead_testvec *template,
-                     unsigned int tcount)
+static int test_aead(char *algo, int enc, struct aead_testvec *template,
+                    unsigned int tcount)
 {
-       unsigned int ret, i, j, k, temp;
-       unsigned int tsize;
+       unsigned int i, j, k, n, temp;
+       int ret = 0;
        char *q;
        struct crypto_aead *tfm;
        char *key;
-       struct aead_testvec *aead_tv;
        struct aead_request *req;
        struct scatterlist sg[8];
        struct scatterlist asg[8];
        const char *e;
        struct tcrypt_result result;
        unsigned int authsize;
+       void *input;
+       void *assoc;
+       char iv[MAX_IVLEN];
 
        if (enc == ENCRYPT)
                e = "encryption";
        else
                e = "decryption";
 
-       printk(KERN_INFO "\ntesting %s %s\n", algo, e);
-
-       tsize = sizeof(struct aead_testvec);
-       tsize *= tcount;
-
-       if (tsize > TVMEMSIZE) {
-               printk(KERN_INFO "template (%u) too big for tvmem (%u)\n",
-                      tsize, TVMEMSIZE);
-               return;
-       }
-
-       memcpy(tvmem, template, tsize);
-       aead_tv = (void *)tvmem;
-
        init_completion(&result.completion);
 
        tfm = crypto_alloc_aead(algo, 0, 0);
 
        if (IS_ERR(tfm)) {
-               printk(KERN_INFO "failed to load transform for %s: %ld\n",
-                      algo, PTR_ERR(tfm));
-               return;
+               printk(KERN_ERR "alg: aead: Failed to load transform for %s: "
+                      "%ld\n", algo, PTR_ERR(tfm));
+               return PTR_ERR(tfm);
        }
 
        req = aead_request_alloc(tfm, GFP_KERNEL);
        if (!req) {
-               printk(KERN_INFO "failed to allocate request for %s\n", algo);
+               printk(KERN_ERR "alg: aead: Failed to allocate request for "
+                      "%s\n", algo);
+               ret = -ENOMEM;
                goto out;
        }
 
@@ -276,46 +298,57 @@ static void test_aead(char *algo, int enc, struct aead_testvec *template,
                                  tcrypt_complete, &result);
 
        for (i = 0, j = 0; i < tcount; i++) {
-               if (!aead_tv[i].np) {
-                       printk(KERN_INFO "test %u (%d bit key):\n",
-                              ++j, aead_tv[i].klen * 8);
+               if (!template[i].np) {
+                       j++;
+
+                       /* some tepmplates have no input data but they will
+                        * touch input
+                        */
+                       input = xbuf[0];
+                       assoc = axbuf[0];
+
+                       memcpy(input, template[i].input, template[i].ilen);
+                       memcpy(assoc, template[i].assoc, template[i].alen);
+                       if (template[i].iv)
+                               memcpy(iv, template[i].iv, MAX_IVLEN);
+                       else
+                               memset(iv, 0, MAX_IVLEN);
 
                        crypto_aead_clear_flags(tfm, ~0);
-                       if (aead_tv[i].wk)
+                       if (template[i].wk)
                                crypto_aead_set_flags(
                                        tfm, CRYPTO_TFM_REQ_WEAK_KEY);
-                       key = aead_tv[i].key;
+
+                       key = template[i].key;
 
                        ret = crypto_aead_setkey(tfm, key,
-                                                aead_tv[i].klen);
-                       if (ret) {
-                               printk(KERN_INFO "setkey() failed flags=%x\n",
+                                                template[i].klen);
+                       if (!ret == template[i].fail) {
+                               printk(KERN_ERR "alg: aead: setkey failed on "
+                                      "test %d for %s: flags=%x\n", j, algo,
                                       crypto_aead_get_flags(tfm));
+                               goto out;
+                       } else if (ret)
+                               continue;
 
-                               if (!aead_tv[i].fail)
-                                       goto out;
-                       }
-
-                       authsize = abs(aead_tv[i].rlen - aead_tv[i].ilen);
+                       authsize = abs(template[i].rlen - template[i].ilen);
                        ret = crypto_aead_setauthsize(tfm, authsize);
                        if (ret) {
-                               printk(KERN_INFO
-                                      "failed to set authsize = %u\n",
-                                      authsize);
+                               printk(KERN_ERR "alg: aead: Failed to set "
+                                      "authsize to %u on test %d for %s\n",
+                                      authsize, j, algo);
                                goto out;
                        }
 
-                       sg_init_one(&sg[0], aead_tv[i].input,
-                                   aead_tv[i].ilen + (enc ? authsize : 0));
+                       sg_init_one(&sg[0], input,
+                                   template[i].ilen + (enc ? authsize : 0));
 
-                       sg_init_one(&asg[0], aead_tv[i].assoc,
-                                   aead_tv[i].alen);
+                       sg_init_one(&asg[0], assoc, template[i].alen);
 
                        aead_request_set_crypt(req, sg, sg,
-                                              aead_tv[i].ilen,
-                                              aead_tv[i].iv);
+                                              template[i].ilen, iv);
 
-                       aead_request_set_assoc(req, asg, aead_tv[i].alen);
+                       aead_request_set_assoc(req, asg, template[i].alen);
 
                        ret = enc ?
                                crypto_aead_encrypt(req) :
@@ -334,80 +367,106 @@ static void test_aead(char *algo, int enc, struct aead_testvec *template,
                                }
                                /* fall through */
                        default:
-                               printk(KERN_INFO "%s () failed err=%d\n",
-                                      e, -ret);
+                               printk(KERN_ERR "alg: aead: %s failed on test "
+                                      "%d for %s: ret=%d\n", e, j, algo, -ret);
                                goto out;
                        }
 
-                       q = kmap(sg_page(&sg[0])) + sg[0].offset;
-                       hexdump(q, aead_tv[i].rlen);
-
-                       printk(KERN_INFO "enc/dec: %s\n",
-                              memcmp(q, aead_tv[i].result,
-                                     aead_tv[i].rlen) ? "fail" : "pass");
+                       q = input;
+                       if (memcmp(q, template[i].result, template[i].rlen)) {
+                               printk(KERN_ERR "alg: aead: Test %d failed on "
+                                      "%s for %s\n", j, e, algo);
+                               hexdump(q, template[i].rlen);
+                               ret = -EINVAL;
+                               goto out;
+                       }
                }
        }
 
-       printk(KERN_INFO "\ntesting %s %s across pages (chunking)\n", algo, e);
-       memset(xbuf, 0, XBUFSIZE);
-
        for (i = 0, j = 0; i < tcount; i++) {
-               if (aead_tv[i].np) {
-                       printk(KERN_INFO "test %u (%d bit key):\n",
-                              ++j, aead_tv[i].klen * 8);
+               if (template[i].np) {
+                       j++;
+
+                       if (template[i].iv)
+                               memcpy(iv, template[i].iv, MAX_IVLEN);
+                       else
+                               memset(iv, 0, MAX_IVLEN);
 
                        crypto_aead_clear_flags(tfm, ~0);
-                       if (aead_tv[i].wk)
+                       if (template[i].wk)
                                crypto_aead_set_flags(
                                        tfm, CRYPTO_TFM_REQ_WEAK_KEY);
-                       key = aead_tv[i].key;
+                       key = template[i].key;
 
-                       ret = crypto_aead_setkey(tfm, key, aead_tv[i].klen);
-                       if (ret) {
-                               printk(KERN_INFO "setkey() failed flags=%x\n",
-                                      crypto_aead_get_flags(tfm));
+                       ret = crypto_aead_setkey(tfm, key, template[i].klen);
+                       if (!ret == template[i].fail) {
+                               printk(KERN_ERR "alg: aead: setkey failed on "
+                                      "chunk test %d for %s: flags=%x\n", j,
+                                      algo, crypto_aead_get_flags(tfm));
+                               goto out;
+                       } else if (ret)
+                               continue;
+
+                       authsize = abs(template[i].rlen - template[i].ilen);
 
-                               if (!aead_tv[i].fail)
+                       ret = -EINVAL;
+                       sg_init_table(sg, template[i].np);
+                       for (k = 0, temp = 0; k < template[i].np; k++) {
+                               if (WARN_ON(offset_in_page(IDX[k]) +
+                                           template[i].tap[k] > PAGE_SIZE))
                                        goto out;
-                       }
 
-                       sg_init_table(sg, aead_tv[i].np);
-                       for (k = 0, temp = 0; k < aead_tv[i].np; k++) {
-                               memcpy(&xbuf[IDX[k]],
-                                      aead_tv[i].input + temp,
-                                      aead_tv[i].tap[k]);
-                               temp += aead_tv[i].tap[k];
-                               sg_set_buf(&sg[k], &xbuf[IDX[k]],
-                                          aead_tv[i].tap[k]);
+                               q = xbuf[IDX[k] >> PAGE_SHIFT] +
+                                   offset_in_page(IDX[k]);
+
+                               memcpy(q, template[i].input + temp,
+                                      template[i].tap[k]);
+
+                               n = template[i].tap[k];
+                               if (k == template[i].np - 1 && enc)
+                                       n += authsize;
+                               if (offset_in_page(q) + n < PAGE_SIZE)
+                                       q[n] = 0;
+
+                               sg_set_buf(&sg[k], q, template[i].tap[k]);
+                               temp += template[i].tap[k];
                        }
 
-                       authsize = abs(aead_tv[i].rlen - aead_tv[i].ilen);
                        ret = crypto_aead_setauthsize(tfm, authsize);
                        if (ret) {
-                               printk(KERN_INFO
-                                      "failed to set authsize = %u\n",
-                                      authsize);
+                               printk(KERN_ERR "alg: aead: Failed to set "
+                                      "authsize to %u on chunk test %d for "
+                                      "%s\n", authsize, j, algo);
                                goto out;
                        }
 
-                       if (enc)
+                       if (enc) {
+                               if (WARN_ON(sg[k - 1].offset +
+                                           sg[k - 1].length + authsize >
+                                           PAGE_SIZE)) {
+                                       ret = -EINVAL;
+                                       goto out;
+                               }
+
                                sg[k - 1].length += authsize;
+                       }
 
-                       sg_init_table(asg, aead_tv[i].anp);
-                       for (k = 0, temp = 0; k < aead_tv[i].anp; k++) {
-                               memcpy(&axbuf[IDX[k]],
-                                      aead_tv[i].assoc + temp,
-                                      aead_tv[i].atap[k]);
-                               temp += aead_tv[i].atap[k];
-                               sg_set_buf(&asg[k], &axbuf[IDX[k]],
-                                          aead_tv[i].atap[k]);
+                       sg_init_table(asg, template[i].anp);
+                       for (k = 0, temp = 0; k < template[i].anp; k++) {
+                               sg_set_buf(&asg[k],
+                                          memcpy(axbuf[IDX[k] >> PAGE_SHIFT] +
+                                                 offset_in_page(IDX[k]),
+                                                 template[i].assoc + temp,
+                                                 template[i].atap[k]),
+                                          template[i].atap[k]);
+                               temp += template[i].atap[k];
                        }
 
                        aead_request_set_crypt(req, sg, sg,
-                                              aead_tv[i].ilen,
-                                              aead_tv[i].iv);
+                                              template[i].ilen,
+                                              iv);
 
-                       aead_request_set_assoc(req, asg, aead_tv[i].alen);
+                       aead_request_set_assoc(req, asg, template[i].alen);
 
                        ret = enc ?
                                crypto_aead_encrypt(req) :
@@ -426,74 +485,97 @@ static void test_aead(char *algo, int enc, struct aead_testvec *template,
                                }
                                /* fall through */
                        default:
-                               printk(KERN_INFO "%s () failed err=%d\n",
-                                      e, -ret);
+                               printk(KERN_ERR "alg: aead: %s failed on "
+                                      "chunk test %d for %s: ret=%d\n", e, j,
+                                      algo, -ret);
                                goto out;
                        }
 
-                       for (k = 0, temp = 0; k < aead_tv[i].np; k++) {
-                               printk(KERN_INFO "page %u\n", k);
-                               q = kmap(sg_page(&sg[k])) + sg[k].offset;
-                               hexdump(q, aead_tv[i].tap[k]);
-                               printk(KERN_INFO "%s\n",
-                                      memcmp(q, aead_tv[i].result + temp,
-                                             aead_tv[i].tap[k] -
-                                             (k < aead_tv[i].np - 1 || enc ?
-                                              0 : authsize)) ?
-                                      "fail" : "pass");
-
-                               temp += aead_tv[i].tap[k];
+                       ret = -EINVAL;
+                       for (k = 0, temp = 0; k < template[i].np; k++) {
+                               q = xbuf[IDX[k] >> PAGE_SHIFT] +
+                                   offset_in_page(IDX[k]);
+
+                               n = template[i].tap[k];
+                               if (k == template[i].np - 1)
+                                       n += enc ? authsize : -authsize;
+
+                               if (memcmp(q, template[i].result + temp, n)) {
+                                       printk(KERN_ERR "alg: aead: Chunk "
+                                              "test %d failed on %s at page "
+                                              "%u for %s\n", j, e, k, algo);
+                                       hexdump(q, n);
+                                       goto out;
+                               }
+
+                               q += n;
+                               if (k == template[i].np - 1 && !enc) {
+                                       if (memcmp(q, template[i].input +
+                                                     temp + n, authsize))
+                                               n = authsize;
+                                       else
+                                               n = 0;
+                               } else {
+                                       for (n = 0; offset_in_page(q + n) &&
+                                                   q[n]; n++)
+                                               ;
+                               }
+                               if (n) {
+                                       printk(KERN_ERR "alg: aead: Result "
+                                              "buffer corruption in chunk "
+                                              "test %d on %s at page %u for "
+                                              "%s: %u bytes:\n", j, e, k,
+                                              algo, n);
+                                       hexdump(q, n);
+                                       goto out;
+                               }
+
+                               temp += template[i].tap[k];
                        }
                }
        }
 
+       ret = 0;
+
 out:
        crypto_free_aead(tfm);
        aead_request_free(req);
+       return ret;
 }
 
-static void test_cipher(char *algo, int enc,
-                       struct cipher_testvec *template, unsigned int tcount)
+static int test_cipher(char *algo, int enc,
+                      struct cipher_testvec *template, unsigned int tcount)
 {
-       unsigned int ret, i, j, k, temp;
-       unsigned int tsize;
+       unsigned int i, j, k, n, temp;
+       int ret;
        char *q;
        struct crypto_ablkcipher *tfm;
-       char *key;
-       struct cipher_testvec *cipher_tv;
        struct ablkcipher_request *req;
        struct scatterlist sg[8];
        const char *e;
        struct tcrypt_result result;
+       void *data;
+       char iv[MAX_IVLEN];
 
        if (enc == ENCRYPT)
                e = "encryption";
        else
                e = "decryption";
 
-       printk("\ntesting %s %s\n", algo, e);
-
-       tsize = sizeof (struct cipher_testvec);
-       if (tsize > TVMEMSIZE) {
-               printk("template (%u) too big for tvmem (%u)\n", tsize,
-                      TVMEMSIZE);
-               return;
-       }
-       cipher_tv = (void *)tvmem;
-
        init_completion(&result.completion);
-
        tfm = crypto_alloc_ablkcipher(algo, 0, 0);
 
        if (IS_ERR(tfm)) {
-               printk("failed to load transform for %s: %ld\n", algo,
-                      PTR_ERR(tfm));
-               return;
+               printk(KERN_ERR "alg: cipher: Failed to load transform for "
+                      "%s: %ld\n", algo, PTR_ERR(tfm));
+               return PTR_ERR(tfm);
        }
 
        req = ablkcipher_request_alloc(tfm, GFP_KERNEL);
        if (!req) {
-               printk("failed to allocate request for %s\n", algo);
+               printk(KERN_ERR "alg: cipher: Failed to allocate request for "
+                      "%s\n", algo);
+               ret = -ENOMEM;
                goto out;
        }
 
@@ -502,35 +584,36 @@ static void test_cipher(char *algo, int enc,
 
        j = 0;
        for (i = 0; i < tcount; i++) {
-               memcpy(cipher_tv, &template[i], tsize);
-               if (!(cipher_tv->np)) {
+               if (template[i].iv)
+                       memcpy(iv, template[i].iv, MAX_IVLEN);
+               else
+                       memset(iv, 0, MAX_IVLEN);
+
+               if (!(template[i].np)) {
                        j++;
-                       printk("test %u (%d bit key):\n",
-                       j, cipher_tv->klen * 8);
+
+                       data = xbuf[0];
+                       memcpy(data, template[i].input, template[i].ilen);
 
                        crypto_ablkcipher_clear_flags(tfm, ~0);
-                       if (cipher_tv->wk)
+                       if (template[i].wk)
                                crypto_ablkcipher_set_flags(
                                        tfm, CRYPTO_TFM_REQ_WEAK_KEY);
-                       key = cipher_tv->key;
 
-                       ret = crypto_ablkcipher_setkey(tfm, key,
-                                                      cipher_tv->klen);
-                       if (ret) {
-                               printk("setkey() failed flags=%x\n",
-                                      crypto_ablkcipher_get_flags(tfm));
-
-                               if (!cipher_tv->fail)
-                                       goto out;
-                       }
+                       ret = crypto_ablkcipher_setkey(tfm, template[i].key,
+                                                      template[i].klen);
+                       if (!ret == template[i].fail) {
+                               printk(KERN_ERR "alg: cipher: setkey failed "
+                                      "on test %d for %s: flags=%x\n", j,
+                                      algo, crypto_ablkcipher_get_flags(tfm));
+                               goto out;
+                       } else if (ret)
+                               continue;
 
-                       sg_init_one(&sg[0], cipher_tv->input,
-                                   cipher_tv->ilen);
+                       sg_init_one(&sg[0], data, template[i].ilen);
 
                        ablkcipher_request_set_crypt(req, sg, sg,
-                                                    cipher_tv->ilen,
-                                                    cipher_tv->iv);
-
+                                                    template[i].ilen, iv);
                        ret = enc ?
                                crypto_ablkcipher_encrypt(req) :
                                crypto_ablkcipher_decrypt(req);
@@ -548,60 +631,75 @@ static void test_cipher(char *algo, int enc,
                                }
                                /* fall through */
                        default:
-                               printk("%s () failed err=%d\n", e, -ret);
+                               printk(KERN_ERR "alg: cipher: %s failed on "
+                                      "test %d for %s: ret=%d\n", e, j, algo,
+                                      -ret);
                                goto out;
                        }
 
-                       q = kmap(sg_page(&sg[0])) + sg[0].offset;
-                       hexdump(q, cipher_tv->rlen);
-
-                       printk("%s\n",
-                              memcmp(q, cipher_tv->result,
-                                     cipher_tv->rlen) ? "fail" : "pass");
+                       q = data;
+                       if (memcmp(q, template[i].result, template[i].rlen)) {
+                               printk(KERN_ERR "alg: cipher: Test %d failed "
+                                      "on %s for %s\n", j, e, algo);
+                               hexdump(q, template[i].rlen);
+                               ret = -EINVAL;
+                               goto out;
+                       }
                }
        }
 
-       printk("\ntesting %s %s across pages (chunking)\n", algo, e);
-       memset(xbuf, 0, XBUFSIZE);
-
        j = 0;
        for (i = 0; i < tcount; i++) {
-               memcpy(cipher_tv, &template[i], tsize);
-               if (cipher_tv->np) {
+
+               if (template[i].iv)
+                       memcpy(iv, template[i].iv, MAX_IVLEN);
+               else
+                       memset(iv, 0, MAX_IVLEN);
+
+               if (template[i].np) {
                        j++;
-                       printk("test %u (%d bit key):\n",
-                       j, cipher_tv->klen * 8);
 
                        crypto_ablkcipher_clear_flags(tfm, ~0);
-                       if (cipher_tv->wk)
+                       if (template[i].wk)
                                crypto_ablkcipher_set_flags(
                                        tfm, CRYPTO_TFM_REQ_WEAK_KEY);
-                       key = cipher_tv->key;
 
-                       ret = crypto_ablkcipher_setkey(tfm, key,
-                                                      cipher_tv->klen);
-                       if (ret) {
-                               printk("setkey() failed flags=%x\n",
+                       ret = crypto_ablkcipher_setkey(tfm, template[i].key,
+                                                      template[i].klen);
+                       if (!ret == template[i].fail) {
+                               printk(KERN_ERR "alg: cipher: setkey failed "
+                                      "on chunk test %d for %s: flags=%x\n",
+                                      j, algo,
                                       crypto_ablkcipher_get_flags(tfm));
+                               goto out;
+                       } else if (ret)
+                               continue;
 
-                               if (!cipher_tv->fail)
+                       temp = 0;
+                       ret = -EINVAL;
+                       sg_init_table(sg, template[i].np);
+                       for (k = 0; k < template[i].np; k++) {
+                               if (WARN_ON(offset_in_page(IDX[k]) +
+                                           template[i].tap[k] > PAGE_SIZE))
                                        goto out;
-                       }
 
-                       temp = 0;
-                       sg_init_table(sg, cipher_tv->np);
-                       for (k = 0; k < cipher_tv->np; k++) {
-                               memcpy(&xbuf[IDX[k]],
-                                      cipher_tv->input + temp,
-                                      cipher_tv->tap[k]);
-                               temp += cipher_tv->tap[k];
-                               sg_set_buf(&sg[k], &xbuf[IDX[k]],
-                                          cipher_tv->tap[k]);
+                               q = xbuf[IDX[k] >> PAGE_SHIFT] +
+                                   offset_in_page(IDX[k]);
+
+                               memcpy(q, template[i].input + temp,
+                                      template[i].tap[k]);
+
+                               if (offset_in_page(q) + template[i].tap[k] <
+                                   PAGE_SIZE)
+                                       q[template[i].tap[k]] = 0;
+
+                               sg_set_buf(&sg[k], q, template[i].tap[k]);
+
+                               temp += template[i].tap[k];
                        }
 
                        ablkcipher_request_set_crypt(req, sg, sg,
-                                                    cipher_tv->ilen,
-                                                    cipher_tv->iv);
+                                       template[i].ilen, iv);
 
                        ret = enc ?
                                crypto_ablkcipher_encrypt(req) :
@@ -620,39 +718,59 @@ static void test_cipher(char *algo, int enc,
                                }
                                /* fall through */
                        default:
-                               printk("%s () failed err=%d\n", e, -ret);
+                               printk(KERN_ERR "alg: cipher: %s failed on "
+                                      "chunk test %d for %s: ret=%d\n", e, j,
+                                      algo, -ret);
                                goto out;
                        }
 
                        temp = 0;
-                       for (k = 0; k < cipher_tv->np; k++) {
-                               printk("page %u\n", k);
-                               q = kmap(sg_page(&sg[k])) + sg[k].offset;
-                               hexdump(q, cipher_tv->tap[k]);
-                               printk("%s\n",
-                                       memcmp(q, cipher_tv->result + temp,
-                                               cipher_tv->tap[k]) ? "fail" :
-                                       "pass");
-                               temp += cipher_tv->tap[k];
+                       ret = -EINVAL;
+                       for (k = 0; k < template[i].np; k++) {
+                               q = xbuf[IDX[k] >> PAGE_SHIFT] +
+                                   offset_in_page(IDX[k]);
+
+                               if (memcmp(q, template[i].result + temp,
+                                          template[i].tap[k])) {
+                                       printk(KERN_ERR "alg: cipher: Chunk "
+                                              "test %d failed on %s at page "
+                                              "%u for %s\n", j, e, k, algo);
+                                       hexdump(q, template[i].tap[k]);
+                                       goto out;
+                               }
+
+                               q += template[i].tap[k];
+                               for (n = 0; offset_in_page(q + n) && q[n]; n++)
+                                       ;
+                               if (n) {
+                                       printk(KERN_ERR "alg: cipher: "
+                                              "Result buffer corruption in "
+                                              "chunk test %d on %s at page "
+                                              "%u for %s: %u bytes:\n", j, e,
+                                              k, algo, n);
+                                       hexdump(q, n);
+                                       goto out;
+                               }
+                               temp += template[i].tap[k];
                        }
                }
        }
 
+       ret = 0;
+
 out:
        crypto_free_ablkcipher(tfm);
        ablkcipher_request_free(req);
+       return ret;
 }
 
-static int test_cipher_jiffies(struct blkcipher_desc *desc, int enc, char *p,
-                              int blen, int sec)
+static int test_cipher_jiffies(struct blkcipher_desc *desc, int enc,
+                              struct scatterlist *sg, int blen, int sec)
 {
-       struct scatterlist sg[1];
        unsigned long start, end;
        int bcount;
        int ret;
 
-       sg_init_one(sg, p, blen);
-
        for (start = jiffies, end = start + sec * HZ, bcount = 0;
             time_before(jiffies, end); bcount++) {
                if (enc)
@@ -669,16 +787,13 @@ static int test_cipher_jiffies(struct blkcipher_desc *desc, int enc, char *p,
        return 0;
 }
 
-static int test_cipher_cycles(struct blkcipher_desc *desc, int enc, char *p,
-                             int blen)
+static int test_cipher_cycles(struct blkcipher_desc *desc, int enc,
+                             struct scatterlist *sg, int blen)
 {
-       struct scatterlist sg[1];
        unsigned long cycles = 0;
        int ret = 0;
        int i;
 
-       sg_init_one(sg, p, blen);
-
        local_bh_disable();
        local_irq_disable();
 
@@ -721,15 +836,18 @@ out:
        return ret;
 }
 
+static u32 block_sizes[] = { 16, 64, 256, 1024, 8192, 0 };
+
 static void test_cipher_speed(char *algo, int enc, unsigned int sec,
                              struct cipher_testvec *template,
-                             unsigned int tcount, struct cipher_speed *speed)
+                             unsigned int tcount, u8 *keysize)
 {
        unsigned int ret, i, j, iv_len;
-       unsigned char *key, *p, iv[128];
+       unsigned char *key, iv[128];
        struct crypto_blkcipher *tfm;
        struct blkcipher_desc desc;
        const char *e;
+       u32 *b_size;
 
        if (enc == ENCRYPT)
                e = "encryption";
@@ -748,70 +866,86 @@ static void test_cipher_speed(char *algo, int enc, unsigned int sec,
        desc.tfm = tfm;
        desc.flags = 0;
 
-       for (i = 0; speed[i].klen != 0; i++) {
-               if ((speed[i].blen + speed[i].klen) > TVMEMSIZE) {
-                       printk("template (%u) too big for tvmem (%u)\n",
-                              speed[i].blen + speed[i].klen, TVMEMSIZE);
-                       goto out;
-               }
+       i = 0;
+       do {
+
+               b_size = block_sizes;
+               do {
+                       struct scatterlist sg[TVMEMSIZE];
 
-               printk("test %u (%d bit key, %d byte blocks): ", i,
-                      speed[i].klen * 8, speed[i].blen);
+                       if ((*keysize + *b_size) > TVMEMSIZE * PAGE_SIZE) {
+                               printk("template (%u) too big for "
+                                      "tvmem (%lu)\n", *keysize + *b_size,
+                                      TVMEMSIZE * PAGE_SIZE);
+                               goto out;
+                       }
 
-               memset(tvmem, 0xff, speed[i].klen + speed[i].blen);
+                       printk("test %u (%d bit key, %d byte blocks): ", i,
+                                       *keysize * 8, *b_size);
 
-               /* set key, plain text and IV */
-               key = (unsigned char *)tvmem;
-               for (j = 0; j < tcount; j++) {
-                       if (template[j].klen == speed[i].klen) {
-                               key = template[j].key;
-                               break;
+                       memset(tvmem[0], 0xff, PAGE_SIZE);
+
+                       /* set key, plain text and IV */
+                       key = (unsigned char *)tvmem[0];
+                       for (j = 0; j < tcount; j++) {
+                               if (template[j].klen == *keysize) {
+                                       key = template[j].key;
+                                       break;
+                               }
                        }
-               }
-               p = (unsigned char *)tvmem + speed[i].klen;
 
-               ret = crypto_blkcipher_setkey(tfm, key, speed[i].klen);
-               if (ret) {
-                       printk("setkey() failed flags=%x\n",
-                              crypto_blkcipher_get_flags(tfm));
-                       goto out;
-               }
+                       ret = crypto_blkcipher_setkey(tfm, key, *keysize);
+                       if (ret) {
+                               printk("setkey() failed flags=%x\n",
+                                               crypto_blkcipher_get_flags(tfm));
+                               goto out;
+                       }
 
-               iv_len = crypto_blkcipher_ivsize(tfm);
-               if (iv_len) {
-                       memset(&iv, 0xff, iv_len);
-                       crypto_blkcipher_set_iv(tfm, iv, iv_len);
-               }
+                       sg_init_table(sg, TVMEMSIZE);
+                       sg_set_buf(sg, tvmem[0] + *keysize,
+                                  PAGE_SIZE - *keysize);
+                       for (j = 1; j < TVMEMSIZE; j++) {
+                               sg_set_buf(sg + j, tvmem[j], PAGE_SIZE);
+                               memset (tvmem[j], 0xff, PAGE_SIZE);
+                       }
 
-               if (sec)
-                       ret = test_cipher_jiffies(&desc, enc, p, speed[i].blen,
-                                                 sec);
-               else
-                       ret = test_cipher_cycles(&desc, enc, p, speed[i].blen);
+                       iv_len = crypto_blkcipher_ivsize(tfm);
+                       if (iv_len) {
+                               memset(&iv, 0xff, iv_len);
+                               crypto_blkcipher_set_iv(tfm, iv, iv_len);
+                       }
 
-               if (ret) {
-                       printk("%s() failed flags=%x\n", e, desc.flags);
-                       break;
-               }
-       }
+                       if (sec)
+                               ret = test_cipher_jiffies(&desc, enc, sg,
+                                                         *b_size, sec);
+                       else
+                               ret = test_cipher_cycles(&desc, enc, sg,
+                                                        *b_size);
+
+                       if (ret) {
+                               printk("%s() failed flags=%x\n", e, desc.flags);
+                               break;
+                       }
+                       b_size++;
+                       i++;
+               } while (*b_size);
+               keysize++;
+       } while (*keysize);
 
 out:
        crypto_free_blkcipher(tfm);
 }
 
-static int test_hash_jiffies_digest(struct hash_desc *desc, char *p, int blen,
+static int test_hash_jiffies_digest(struct hash_desc *desc,
+                                   struct scatterlist *sg, int blen,
                                    char *out, int sec)
 {
-       struct scatterlist sg[1];
        unsigned long start, end;
        int bcount;
        int ret;
 
-       sg_init_table(sg, 1);
-
        for (start = jiffies, end = start + sec * HZ, bcount = 0;
             time_before(jiffies, end); bcount++) {
-               sg_set_buf(sg, p, blen);
                ret = crypto_hash_digest(desc, sg, blen, out);
                if (ret)
                        return ret;
@@ -823,18 +957,15 @@ static int test_hash_jiffies_digest(struct hash_desc *desc, char *p, int blen,
        return 0;
 }
 
-static int test_hash_jiffies(struct hash_desc *desc, char *p, int blen,
-                            int plen, char *out, int sec)
+static int test_hash_jiffies(struct hash_desc *desc, struct scatterlist *sg,
+                            int blen, int plen, char *out, int sec)
 {
-       struct scatterlist sg[1];
        unsigned long start, end;
        int bcount, pcount;
        int ret;
 
        if (plen == blen)
-               return test_hash_jiffies_digest(desc, p, blen, out, sec);
-
-       sg_init_table(sg, 1);
+               return test_hash_jiffies_digest(desc, sg, blen, out, sec);
 
        for (start = jiffies, end = start + sec * HZ, bcount = 0;
             time_before(jiffies, end); bcount++) {
@@ -842,7 +973,6 @@ static int test_hash_jiffies(struct hash_desc *desc, char *p, int blen,
                if (ret)
                        return ret;
                for (pcount = 0; pcount < blen; pcount += plen) {
-                       sg_set_buf(sg, p + pcount, plen);
                        ret = crypto_hash_update(desc, sg, plen);
                        if (ret)
                                return ret;
@@ -859,22 +989,18 @@ static int test_hash_jiffies(struct hash_desc *desc, char *p, int blen,
        return 0;
 }
 
-static int test_hash_cycles_digest(struct hash_desc *desc, char *p, int blen,
-                                  char *out)
+static int test_hash_cycles_digest(struct hash_desc *desc,
+                                  struct scatterlist *sg, int blen, char *out)
 {
-       struct scatterlist sg[1];
        unsigned long cycles = 0;
        int i;
        int ret;
 
-       sg_init_table(sg, 1);
-
        local_bh_disable();
        local_irq_disable();
 
        /* Warm-up run. */
        for (i = 0; i < 4; i++) {
-               sg_set_buf(sg, p, blen);
                ret = crypto_hash_digest(desc, sg, blen, out);
                if (ret)
                        goto out;
@@ -886,7 +1012,6 @@ static int test_hash_cycles_digest(struct hash_desc *desc, char *p, int blen,
 
                start = get_cycles();
 
-               sg_set_buf(sg, p, blen);
                ret = crypto_hash_digest(desc, sg, blen, out);
                if (ret)
                        goto out;
@@ -909,18 +1034,15 @@ out:
        return 0;
 }
 
-static int test_hash_cycles(struct hash_desc *desc, char *p, int blen,
-                           int plen, char *out)
+static int test_hash_cycles(struct hash_desc *desc, struct scatterlist *sg,
+                           int blen, int plen, char *out)
 {
-       struct scatterlist sg[1];
        unsigned long cycles = 0;
        int i, pcount;
        int ret;
 
        if (plen == blen)
-               return test_hash_cycles_digest(desc, p, blen, out);
-
-       sg_init_table(sg, 1);
+               return test_hash_cycles_digest(desc, sg, blen, out);
 
        local_bh_disable();
        local_irq_disable();
@@ -931,7 +1053,6 @@ static int test_hash_cycles(struct hash_desc *desc, char *p, int blen,
                if (ret)
                        goto out;
                for (pcount = 0; pcount < blen; pcount += plen) {
-                       sg_set_buf(sg, p + pcount, plen);
                        ret = crypto_hash_update(desc, sg, plen);
                        if (ret)
                                goto out;
@@ -951,7 +1072,6 @@ static int test_hash_cycles(struct hash_desc *desc, char *p, int blen,
                if (ret)
                        goto out;
                for (pcount = 0; pcount < blen; pcount += plen) {
-                       sg_set_buf(sg, p + pcount, plen);
                        ret = crypto_hash_update(desc, sg, plen);
                        if (ret)
                                goto out;
@@ -981,6 +1101,7 @@ out:
 static void test_hash_speed(char *algo, unsigned int sec,
                              struct hash_speed *speed)
 {
+       struct scatterlist sg[TVMEMSIZE];
        struct crypto_hash *tfm;
        struct hash_desc desc;
        char output[1024];
@@ -1006,23 +1127,27 @@ static void test_hash_speed(char *algo, unsigned int sec,
                goto out;
        }
 
+       sg_init_table(sg, TVMEMSIZE);
+       for (i = 0; i < TVMEMSIZE; i++) {
+               sg_set_buf(sg + i, tvmem[i], PAGE_SIZE);
+               memset(tvmem[i], 0xff, PAGE_SIZE);
+       }
+
        for (i = 0; speed[i].blen != 0; i++) {
-               if (speed[i].blen > TVMEMSIZE) {
-                       printk("template (%u) too big for tvmem (%u)\n",
-                              speed[i].blen, TVMEMSIZE);
+               if (speed[i].blen > TVMEMSIZE * PAGE_SIZE) {
+                       printk("template (%u) too big for tvmem (%lu)\n",
+                              speed[i].blen, TVMEMSIZE * PAGE_SIZE);
                        goto out;
                }
 
                printk("test%3u (%5u byte blocks,%5u bytes per update,%4u updates): ",
                       i, speed[i].blen, speed[i].plen, speed[i].blen / speed[i].plen);
 
-               memset(tvmem, 0xff, speed[i].blen);
-
                if (sec)
-                       ret = test_hash_jiffies(&desc, tvmem, speed[i].blen,
+                       ret = test_hash_jiffies(&desc, sg, speed[i].blen,
                                                speed[i].plen, output, sec);
                else
-                       ret = test_hash_cycles(&desc, tvmem, speed[i].blen,
+                       ret = test_hash_cycles(&desc, sg, speed[i].blen,
                                               speed[i].plen, output);
 
                if (ret) {
@@ -1035,86 +1160,74 @@ out:
        crypto_free_hash(tfm);
 }
 
-static void test_comp(char *algo, struct comp_testvec *ctemplate,
-                      struct comp_testvec *dtemplate, int ctcount, int dtcount)
+static int test_comp(char *algo, struct comp_testvec *ctemplate,
+                    struct comp_testvec *dtemplate, int ctcount, int dtcount)
 {
        unsigned int i;
        char result[COMP_BUF_SIZE];
        struct crypto_comp *tfm;
-       struct comp_testvec *tv;
-       unsigned int tsize;
-
-       printk("\ntesting %s compression\n", algo);
-
-       tsize = sizeof(struct comp_testvec);
-       tsize *= ctcount;
-       if (tsize > TVMEMSIZE) {
-               printk("template (%u) too big for tvmem (%u)\n", tsize,
-                      TVMEMSIZE);
-               return;
-       }
-
-       memcpy(tvmem, ctemplate, tsize);
-       tv = (void *)tvmem;
+       int ret;
 
        tfm = crypto_alloc_comp(algo, 0, CRYPTO_ALG_ASYNC);
        if (IS_ERR(tfm)) {
-               printk("failed to load transform for %s\n", algo);
-               return;
+               printk(KERN_ERR "alg: comp: Failed to load transform for %s: "
+                      "%ld\n", algo, PTR_ERR(tfm));
+               return PTR_ERR(tfm);
        }
 
        for (i = 0; i < ctcount; i++) {
-               int ilen, ret, dlen = COMP_BUF_SIZE;
+               int ilen, dlen = COMP_BUF_SIZE;
 
-               printk("test %u:\n", i + 1);
                memset(result, 0, sizeof (result));
 
-               ilen = tv[i].inlen;
-               ret = crypto_comp_compress(tfm, tv[i].input,
+               ilen = ctemplate[i].inlen;
+               ret = crypto_comp_compress(tfm, ctemplate[i].input,
                                           ilen, result, &dlen);
                if (ret) {
-                       printk("fail: ret=%d\n", ret);
-                       continue;
+                       printk(KERN_ERR "alg: comp: compression failed "
+                              "on test %d for %s: ret=%d\n", i + 1, algo,
+                              -ret);
+                       goto out;
                }
-               hexdump(result, dlen);
-               printk("%s (ratio %d:%d)\n",
-                      memcmp(result, tv[i].output, dlen) ? "fail" : "pass",
-                      ilen, dlen);
-       }
 
-       printk("\ntesting %s decompression\n", algo);
-
-       tsize = sizeof(struct comp_testvec);
-       tsize *= dtcount;
-       if (tsize > TVMEMSIZE) {
-               printk("template (%u) too big for tvmem (%u)\n", tsize,
-                      TVMEMSIZE);
-               goto out;
+               if (memcmp(result, ctemplate[i].output, dlen)) {
+                       printk(KERN_ERR "alg: comp: Compression test %d "
+                              "failed for %s\n", i + 1, algo);
+                       hexdump(result, dlen);
+                       ret = -EINVAL;
+                       goto out;
+               }
        }
 
-       memcpy(tvmem, dtemplate, tsize);
-       tv = (void *)tvmem;
-
        for (i = 0; i < dtcount; i++) {
                int ilen, ret, dlen = COMP_BUF_SIZE;
 
-               printk("test %u:\n", i + 1);
                memset(result, 0, sizeof (result));
 
-               ilen = tv[i].inlen;
-               ret = crypto_comp_decompress(tfm, tv[i].input,
+               ilen = dtemplate[i].inlen;
+               ret = crypto_comp_decompress(tfm, dtemplate[i].input,
                                             ilen, result, &dlen);
                if (ret) {
-                       printk("fail: ret=%d\n", ret);
-                       continue;
+                       printk(KERN_ERR "alg: comp: decompression failed "
+                              "on test %d for %s: ret=%d\n", i + 1, algo,
+                              -ret);
+                       goto out;
+               }
+
+               if (memcmp(result, dtemplate[i].output, dlen)) {
+                       printk(KERN_ERR "alg: comp: Decompression test %d "
+                              "failed for %s\n", i + 1, algo);
+                       hexdump(result, dlen);
+                       ret = -EINVAL;
+                       goto out;
                }
-               hexdump(result, dlen);
-               printk("%s (ratio %d:%d)\n",
-                      memcmp(result, tv[i].output, dlen) ? "fail" : "pass",
-                      ilen, dlen);
        }
+
+       ret = 0;
+
 out:
        crypto_free_comp(tfm);
+       return ret;
 }
 
 static void test_available(void)
@@ -1154,6 +1267,14 @@ static void do_test(void)
                test_cipher("ecb(des3_ede)", DECRYPT, des3_ede_dec_tv_template,
                            DES3_EDE_DEC_TEST_VECTORS);
 
+               test_cipher("cbc(des3_ede)", ENCRYPT,
+                           des3_ede_cbc_enc_tv_template,
+                           DES3_EDE_CBC_ENC_TEST_VECTORS);
+
+               test_cipher("cbc(des3_ede)", DECRYPT,
+                           des3_ede_cbc_dec_tv_template,
+                           DES3_EDE_CBC_DEC_TEST_VECTORS);
+
                test_hash("md4", md4_tv_template, MD4_TEST_VECTORS);
 
                test_hash("sha224", sha224_tv_template, SHA224_TEST_VECTORS);
@@ -1301,6 +1422,12 @@ static void do_test(void)
                test_cipher("ecb(seed)", DECRYPT, seed_dec_tv_template,
                            SEED_DEC_TEST_VECTORS);
 
+               //CTS
+               test_cipher("cts(cbc(aes))", ENCRYPT, cts_mode_enc_tv_template,
+                           CTS_MODE_ENC_TEST_VECTORS);
+               test_cipher("cts(cbc(aes))", DECRYPT, cts_mode_dec_tv_template,
+                           CTS_MODE_DEC_TEST_VECTORS);
+
                test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS);
                test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS);
                test_hash("wp512", wp512_tv_template, WP512_TEST_VECTORS);
@@ -1358,6 +1485,14 @@ static void do_test(void)
                            DES3_EDE_ENC_TEST_VECTORS);
                test_cipher("ecb(des3_ede)", DECRYPT, des3_ede_dec_tv_template,
                            DES3_EDE_DEC_TEST_VECTORS);
+
+               test_cipher("cbc(des3_ede)", ENCRYPT,
+                           des3_ede_cbc_enc_tv_template,
+                           DES3_EDE_CBC_ENC_TEST_VECTORS);
+
+               test_cipher("cbc(des3_ede)", DECRYPT,
+                           des3_ede_cbc_dec_tv_template,
+                           DES3_EDE_CBC_DEC_TEST_VECTORS);
                break;
 
        case 5:
@@ -1526,7 +1661,7 @@ static void do_test(void)
        case 29:
                test_hash("tgr128", tgr128_tv_template, TGR128_TEST_VECTORS);
                break;
-               
+
        case 30:
                test_cipher("ecb(xeta)", ENCRYPT, xeta_enc_tv_template,
                            XETA_ENC_TEST_VECTORS);
@@ -1584,6 +1719,29 @@ static void do_test(void)
                          AES_CCM_DEC_TEST_VECTORS);
                break;
 
+       case 38:
+               test_cipher("cts(cbc(aes))", ENCRYPT, cts_mode_enc_tv_template,
+                           CTS_MODE_ENC_TEST_VECTORS);
+               test_cipher("cts(cbc(aes))", DECRYPT, cts_mode_dec_tv_template,
+                           CTS_MODE_DEC_TEST_VECTORS);
+               break;
+
+        case 39:
+               test_hash("rmd128", rmd128_tv_template, RMD128_TEST_VECTORS);
+               break;
+
+        case 40:
+               test_hash("rmd160", rmd160_tv_template, RMD160_TEST_VECTORS);
+               break;
+
+       case 41:
+               test_hash("rmd256", rmd256_tv_template, RMD256_TEST_VECTORS);
+               break;
+
+       case 42:
+               test_hash("rmd320", rmd320_tv_template, RMD320_TEST_VECTORS);
+               break;
+
        case 100:
                test_hash("hmac(md5)", hmac_md5_tv_template,
                          HMAC_MD5_TEST_VECTORS);
@@ -1608,96 +1766,108 @@ static void do_test(void)
                test_hash("hmac(sha512)", hmac_sha512_tv_template,
                          HMAC_SHA512_TEST_VECTORS);
                break;
+
        case 105:
                test_hash("hmac(sha224)", hmac_sha224_tv_template,
                          HMAC_SHA224_TEST_VECTORS);
                break;
 
+       case 106:
+               test_hash("xcbc(aes)", aes_xcbc128_tv_template,
+                         XCBC_AES_TEST_VECTORS);
+               break;
+
+       case 107:
+               test_hash("hmac(rmd128)", hmac_rmd128_tv_template,
+                         HMAC_RMD128_TEST_VECTORS);
+               break;
+
+       case 108:
+               test_hash("hmac(rmd160)", hmac_rmd160_tv_template,
+                         HMAC_RMD160_TEST_VECTORS);
+               break;
+
        case 200:
                test_cipher_speed("ecb(aes)", ENCRYPT, sec, NULL, 0,
-                                 aes_speed_template);
+                               speed_template_16_24_32);
                test_cipher_speed("ecb(aes)", DECRYPT, sec, NULL, 0,
-                                 aes_speed_template);
+                               speed_template_16_24_32);
                test_cipher_speed("cbc(aes)", ENCRYPT, sec, NULL, 0,
-                                 aes_speed_template);
+                               speed_template_16_24_32);
                test_cipher_speed("cbc(aes)", DECRYPT, sec, NULL, 0,
-                                 aes_speed_template);
+                               speed_template_16_24_32);
                test_cipher_speed("lrw(aes)", ENCRYPT, sec, NULL, 0,
-                                 aes_lrw_speed_template);
+                               speed_template_32_40_48);
                test_cipher_speed("lrw(aes)", DECRYPT, sec, NULL, 0,
-                                 aes_lrw_speed_template);
+                               speed_template_32_40_48);
                test_cipher_speed("xts(aes)", ENCRYPT, sec, NULL, 0,
-                                 aes_xts_speed_template);
+                               speed_template_32_48_64);
                test_cipher_speed("xts(aes)", DECRYPT, sec, NULL, 0,
-                                 aes_xts_speed_template);
+                               speed_template_32_48_64);
                break;
 
        case 201:
                test_cipher_speed("ecb(des3_ede)", ENCRYPT, sec,
-                                 des3_ede_enc_tv_template,
-                                 DES3_EDE_ENC_TEST_VECTORS,
-                                 des3_ede_speed_template);
+                               des3_ede_enc_tv_template, DES3_EDE_ENC_TEST_VECTORS,
+                               speed_template_24);
                test_cipher_speed("ecb(des3_ede)", DECRYPT, sec,
-                                 des3_ede_dec_tv_template,
-                                 DES3_EDE_DEC_TEST_VECTORS,
-                                 des3_ede_speed_template);
+                               des3_ede_enc_tv_template, DES3_EDE_ENC_TEST_VECTORS,
+                               speed_template_24);
                test_cipher_speed("cbc(des3_ede)", ENCRYPT, sec,
-                                 des3_ede_enc_tv_template,
-                                 DES3_EDE_ENC_TEST_VECTORS,
-                                 des3_ede_speed_template);
+                               des3_ede_enc_tv_template, DES3_EDE_ENC_TEST_VECTORS,
+                               speed_template_24);
                test_cipher_speed("cbc(des3_ede)", DECRYPT, sec,
-                                 des3_ede_dec_tv_template,
-                                 DES3_EDE_DEC_TEST_VECTORS,
-                                 des3_ede_speed_template);
+                               des3_ede_enc_tv_template, DES3_EDE_ENC_TEST_VECTORS,
+                               speed_template_24);
                break;
 
        case 202:
                test_cipher_speed("ecb(twofish)", ENCRYPT, sec, NULL, 0,
-                                 twofish_speed_template);
+                               speed_template_16_24_32);
                test_cipher_speed("ecb(twofish)", DECRYPT, sec, NULL, 0,
-                                 twofish_speed_template);
+                               speed_template_16_24_32);
                test_cipher_speed("cbc(twofish)", ENCRYPT, sec, NULL, 0,
-                                 twofish_speed_template);
+                               speed_template_16_24_32);
                test_cipher_speed("cbc(twofish)", DECRYPT, sec, NULL, 0,
-                                 twofish_speed_template);
+                               speed_template_16_24_32);
                break;
 
        case 203:
                test_cipher_speed("ecb(blowfish)", ENCRYPT, sec, NULL, 0,
-                                 blowfish_speed_template);
+                                 speed_template_8_32);
                test_cipher_speed("ecb(blowfish)", DECRYPT, sec, NULL, 0,
-                                 blowfish_speed_template);
+                                 speed_template_8_32);
                test_cipher_speed("cbc(blowfish)", ENCRYPT, sec, NULL, 0,
-                                 blowfish_speed_template);
+                                 speed_template_8_32);
                test_cipher_speed("cbc(blowfish)", DECRYPT, sec, NULL, 0,
-                                 blowfish_speed_template);
+                                 speed_template_8_32);
                break;
 
        case 204:
                test_cipher_speed("ecb(des)", ENCRYPT, sec, NULL, 0,
-                                 des_speed_template);
+                                 speed_template_8);
                test_cipher_speed("ecb(des)", DECRYPT, sec, NULL, 0,
-                                 des_speed_template);
+                                 speed_template_8);
                test_cipher_speed("cbc(des)", ENCRYPT, sec, NULL, 0,
-                                 des_speed_template);
+                                 speed_template_8);
                test_cipher_speed("cbc(des)", DECRYPT, sec, NULL, 0,
-                                 des_speed_template);
+                                 speed_template_8);
                break;
 
        case 205:
                test_cipher_speed("ecb(camellia)", ENCRYPT, sec, NULL, 0,
-                               camellia_speed_template);
+                               speed_template_16_24_32);
                test_cipher_speed("ecb(camellia)", DECRYPT, sec, NULL, 0,
-                               camellia_speed_template);
+                               speed_template_16_24_32);
                test_cipher_speed("cbc(camellia)", ENCRYPT, sec, NULL, 0,
-                               camellia_speed_template);
+                               speed_template_16_24_32);
                test_cipher_speed("cbc(camellia)", DECRYPT, sec, NULL, 0,
-                               camellia_speed_template);
+                               speed_template_16_24_32);
                break;
 
        case 206:
                test_cipher_speed("salsa20", ENCRYPT, sec, NULL, 0,
-                                 salsa20_speed_template);
+                                 speed_template_16_32);
                break;
 
        case 300:
@@ -1755,6 +1925,22 @@ static void do_test(void)
                test_hash_speed("sha224", sec, generic_hash_speed_template);
                if (mode > 300 && mode < 400) break;
 
+       case 314:
+               test_hash_speed("rmd128", sec, generic_hash_speed_template);
+               if (mode > 300 && mode < 400) break;
+
+       case 315:
+               test_hash_speed("rmd160", sec, generic_hash_speed_template);
+               if (mode > 300 && mode < 400) break;
+
+       case 316:
+               test_hash_speed("rmd256", sec, generic_hash_speed_template);
+               if (mode > 300 && mode < 400) break;
+
+       case 317:
+               test_hash_speed("rmd320", sec, generic_hash_speed_template);
+               if (mode > 300 && mode < 400) break;
+
        case 399:
                break;
 
@@ -1769,21 +1955,28 @@ static void do_test(void)
        }
 }
 
-static int __init init(void)
+static int __init tcrypt_mod_init(void)
 {
        int err = -ENOMEM;
+       int i;
 
-       tvmem = kmalloc(TVMEMSIZE, GFP_KERNEL);
-       if (tvmem == NULL)
-               return err;
+       for (i = 0; i < TVMEMSIZE; i++) {
+               tvmem[i] = (void *)__get_free_page(GFP_KERNEL);
+               if (!tvmem[i])
+                       goto err_free_tv;
+       }
 
-       xbuf = kmalloc(XBUFSIZE, GFP_KERNEL);
-       if (xbuf == NULL)
-               goto err_free_tv;
+       for (i = 0; i < XBUFSIZE; i++) {
+               xbuf[i] = (void *)__get_free_page(GFP_KERNEL);
+               if (!xbuf[i])
+                       goto err_free_xbuf;
+       }
 
-       axbuf = kmalloc(XBUFSIZE, GFP_KERNEL);
-       if (axbuf == NULL)
-               goto err_free_xbuf;
+       for (i = 0; i < XBUFSIZE; i++) {
+               axbuf[i] = (void *)__get_free_page(GFP_KERNEL);
+               if (!axbuf[i])
+                       goto err_free_axbuf;
+       }
 
        do_test();
 
@@ -1795,11 +1988,15 @@ static int __init init(void)
         */
        err = -EAGAIN;
 
-       kfree(axbuf);
- err_free_xbuf:
-       kfree(xbuf);
- err_free_tv:
-       kfree(tvmem);
+err_free_axbuf:
+       for (i = 0; i < XBUFSIZE && axbuf[i]; i++)
+               free_page((unsigned long)axbuf[i]);
+err_free_xbuf:
+       for (i = 0; i < XBUFSIZE && xbuf[i]; i++)
+               free_page((unsigned long)xbuf[i]);
+err_free_tv:
+       for (i = 0; i < TVMEMSIZE && tvmem[i]; i++)
+               free_page((unsigned long)tvmem[i]);
 
        return err;
 }
@@ -1808,10 +2005,10 @@ static int __init init(void)
  * If an init function is provided, an exit function must also be provided
  * to allow module unload.
  */
-static void __exit fini(void) { }
+static void __exit tcrypt_mod_fini(void) { }
 
-module_init(init);
-module_exit(fini);
+module_init(tcrypt_mod_init);
+module_exit(tcrypt_mod_fini);
 
 module_param(mode, int, 0);
 module_param(sec, uint, 0);