]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - crypto/tcrypt.c
Merge branch 'for-4.8/core' of git://git.kernel.dk/linux-block
[karo-tx-linux.git] / crypto / tcrypt.c
index 579dce07146389f9a38d036fe48b00f347d7f070..ae22f05d5936c724f830cd00afee303a85836dd5 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <crypto/aead.h>
 #include <crypto/hash.h>
+#include <crypto/skcipher.h>
 #include <linux/err.h>
 #include <linux/fips.h>
 #include <linux/init.h>
@@ -72,7 +73,8 @@ static char *check[] = {
        "cast6", "arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea",
        "khazad", "wp512", "wp384", "wp256", "tnepres", "xeta",  "fcrypt",
        "camellia", "seed", "salsa20", "rmd128", "rmd160", "rmd256", "rmd320",
-       "lzo", "cts", "zlib", NULL
+       "lzo", "cts", "zlib", "sha3-224", "sha3-256", "sha3-384", "sha3-512",
+       NULL
 };
 
 struct tcrypt_result {
@@ -91,76 +93,6 @@ static void tcrypt_complete(struct crypto_async_request *req, int err)
        complete(&res->completion);
 }
 
-static int test_cipher_jiffies(struct blkcipher_desc *desc, int enc,
-                              struct scatterlist *sg, int blen, int secs)
-{
-       unsigned long start, end;
-       int bcount;
-       int ret;
-
-       for (start = jiffies, end = start + secs * HZ, bcount = 0;
-            time_before(jiffies, end); bcount++) {
-               if (enc)
-                       ret = crypto_blkcipher_encrypt(desc, sg, sg, blen);
-               else
-                       ret = crypto_blkcipher_decrypt(desc, sg, sg, blen);
-
-               if (ret)
-                       return ret;
-       }
-
-       printk("%d operations in %d seconds (%ld bytes)\n",
-              bcount, secs, (long)bcount * blen);
-       return 0;
-}
-
-static int test_cipher_cycles(struct blkcipher_desc *desc, int enc,
-                             struct scatterlist *sg, int blen)
-{
-       unsigned long cycles = 0;
-       int ret = 0;
-       int i;
-
-       local_irq_disable();
-
-       /* Warm-up run. */
-       for (i = 0; i < 4; i++) {
-               if (enc)
-                       ret = crypto_blkcipher_encrypt(desc, sg, sg, blen);
-               else
-                       ret = crypto_blkcipher_decrypt(desc, sg, sg, blen);
-
-               if (ret)
-                       goto out;
-       }
-
-       /* The real thing. */
-       for (i = 0; i < 8; i++) {
-               cycles_t start, end;
-
-               start = get_cycles();
-               if (enc)
-                       ret = crypto_blkcipher_encrypt(desc, sg, sg, blen);
-               else
-                       ret = crypto_blkcipher_decrypt(desc, sg, sg, blen);
-               end = get_cycles();
-
-               if (ret)
-                       goto out;
-
-               cycles += end - start;
-       }
-
-out:
-       local_irq_enable();
-
-       if (ret == 0)
-               printk("1 operation in %lu cycles (%d bytes)\n",
-                      (cycles + 4) / 8, blen);
-
-       return ret;
-}
-
 static inline int do_one_aead_op(struct aead_request *req, int ret)
 {
        if (ret == -EINPROGRESS || ret == -EBUSY) {
@@ -454,127 +386,148 @@ out_noxbuf:
        return;
 }
 
-static void test_cipher_speed(const char *algo, int enc, unsigned int secs,
-                             struct cipher_speed_template *template,
-                             unsigned int tcount, u8 *keysize)
+static void test_hash_sg_init(struct scatterlist *sg)
 {
-       unsigned int ret, i, j, iv_len;
-       const char *key;
-       char iv[128];
-       struct crypto_blkcipher *tfm;
-       struct blkcipher_desc desc;
-       const char *e;
-       u32 *b_size;
+       int i;
 
-       if (enc == ENCRYPT)
-               e = "encryption";
-       else
-               e = "decryption";
+       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);
+       }
+}
 
-       tfm = crypto_alloc_blkcipher(algo, 0, CRYPTO_ALG_ASYNC);
+static inline int do_one_ahash_op(struct ahash_request *req, int ret)
+{
+       if (ret == -EINPROGRESS || ret == -EBUSY) {
+               struct tcrypt_result *tr = req->base.data;
 
-       if (IS_ERR(tfm)) {
-               printk("failed to load transform for %s: %ld\n", algo,
-                      PTR_ERR(tfm));
+               wait_for_completion(&tr->completion);
+               reinit_completion(&tr->completion);
+               ret = tr->err;
+       }
+       return ret;
+}
+
+struct test_mb_ahash_data {
+       struct scatterlist sg[TVMEMSIZE];
+       char result[64];
+       struct ahash_request *req;
+       struct tcrypt_result tresult;
+       char *xbuf[XBUFSIZE];
+};
+
+static void test_mb_ahash_speed(const char *algo, unsigned int sec,
+                               struct hash_speed *speed)
+{
+       struct test_mb_ahash_data *data;
+       struct crypto_ahash *tfm;
+       unsigned long start, end;
+       unsigned long cycles;
+       unsigned int i, j, k;
+       int ret;
+
+       data = kzalloc(sizeof(*data) * 8, GFP_KERNEL);
+       if (!data)
                return;
+
+       tfm = crypto_alloc_ahash(algo, 0, 0);
+       if (IS_ERR(tfm)) {
+               pr_err("failed to load transform for %s: %ld\n",
+                       algo, PTR_ERR(tfm));
+               goto free_data;
        }
-       desc.tfm = tfm;
-       desc.flags = 0;
 
-       printk(KERN_INFO "\ntesting speed of %s (%s) %s\n", algo,
-                       get_driver_name(crypto_blkcipher, tfm), e);
+       for (i = 0; i < 8; ++i) {
+               if (testmgr_alloc_buf(data[i].xbuf))
+                       goto out;
 
-       i = 0;
-       do {
+               init_completion(&data[i].tresult.completion);
 
-               b_size = block_sizes;
-               do {
-                       struct scatterlist sg[TVMEMSIZE];
+               data[i].req = ahash_request_alloc(tfm, GFP_KERNEL);
+               if (!data[i].req) {
+                       pr_err("alg: hash: Failed to allocate request for %s\n",
+                              algo);
+                       goto out;
+               }
 
-                       if ((*keysize + *b_size) > TVMEMSIZE * PAGE_SIZE) {
-                               printk("template (%u) too big for "
-                                      "tvmem (%lu)\n", *keysize + *b_size,
-                                      TVMEMSIZE * PAGE_SIZE);
-                               goto out;
-                       }
+               ahash_request_set_callback(data[i].req, 0,
+                                          tcrypt_complete, &data[i].tresult);
+               test_hash_sg_init(data[i].sg);
+       }
 
-                       printk("test %u (%d bit key, %d byte blocks): ", i,
-                                       *keysize * 8, *b_size);
+       pr_info("\ntesting speed of multibuffer %s (%s)\n", algo,
+               get_driver_name(crypto_ahash, tfm));
 
-                       memset(tvmem[0], 0xff, PAGE_SIZE);
+       for (i = 0; speed[i].blen != 0; i++) {
+               /* For some reason this only tests digests. */
+               if (speed[i].blen != speed[i].plen)
+                       continue;
 
-                       /* set key, plain text and IV */
-                       key = tvmem[0];
-                       for (j = 0; j < tcount; j++) {
-                               if (template[j].klen == *keysize) {
-                                       key = template[j].key;
-                                       break;
-                               }
-                       }
+               if (speed[i].blen > TVMEMSIZE * PAGE_SIZE) {
+                       pr_err("template (%u) too big for tvmem (%lu)\n",
+                              speed[i].blen, TVMEMSIZE * PAGE_SIZE);
+                       goto out;
+               }
 
-                       ret = crypto_blkcipher_setkey(tfm, key, *keysize);
-                       if (ret) {
-                               printk("setkey() failed flags=%x\n",
-                                               crypto_blkcipher_get_flags(tfm));
-                               goto out;
-                       }
+               if (speed[i].klen)
+                       crypto_ahash_setkey(tfm, tvmem[0], speed[i].klen);
 
-                       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);
-                       }
+               for (k = 0; k < 8; k++)
+                       ahash_request_set_crypt(data[k].req, data[k].sg,
+                                               data[k].result, 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);
-                       }
+               pr_info("test%3u "
+                       "(%5u byte blocks,%5u bytes per update,%4u updates): ",
+                       i, speed[i].blen, speed[i].plen,
+                       speed[i].blen / speed[i].plen);
 
-                       if (secs)
-                               ret = test_cipher_jiffies(&desc, enc, sg,
-                                                         *b_size, secs);
-                       else
-                               ret = test_cipher_cycles(&desc, enc, sg,
-                                                        *b_size);
+               start = get_cycles();
 
-                       if (ret) {
-                               printk("%s() failed flags=%x\n", e, desc.flags);
-                               break;
+               for (k = 0; k < 8; k++) {
+                       ret = crypto_ahash_digest(data[k].req);
+                       if (ret == -EINPROGRESS) {
+                               ret = 0;
+                               continue;
                        }
-                       b_size++;
-                       i++;
-               } while (*b_size);
-               keysize++;
-       } while (*keysize);
 
-out:
-       crypto_free_blkcipher(tfm);
-}
+                       if (ret)
+                               break;
 
-static void test_hash_sg_init(struct scatterlist *sg)
-{
-       int i;
+                       complete(&data[k].tresult.completion);
+                       data[k].tresult.err = 0;
+               }
 
-       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 (j = 0; j < k; j++) {
+                       struct tcrypt_result *tr = &data[j].tresult;
 
-static inline int do_one_ahash_op(struct ahash_request *req, int ret)
-{
-       if (ret == -EINPROGRESS || ret == -EBUSY) {
-               struct tcrypt_result *tr = req->base.data;
+                       wait_for_completion(&tr->completion);
+                       if (tr->err)
+                               ret = tr->err;
+               }
 
-               wait_for_completion(&tr->completion);
-               reinit_completion(&tr->completion);
-               ret = tr->err;
+               end = get_cycles();
+               cycles = end - start;
+               pr_cont("%6lu cycles/operation, %4lu cycles/byte\n",
+                       cycles, cycles / (8 * speed[i].blen));
+
+               if (ret) {
+                       pr_err("At least one hashing failed ret=%d\n", ret);
+                       break;
+               }
        }
-       return ret;
+
+out:
+       for (k = 0; k < 8; ++k)
+               ahash_request_free(data[k].req);
+
+       for (k = 0; k < 8; ++k)
+               testmgr_free_buf(data[k].xbuf);
+
+       crypto_free_ahash(tfm);
+
+free_data:
+       kfree(data);
 }
 
 static int test_ahash_jiffies_digest(struct ahash_request *req, int blen,
@@ -812,7 +765,7 @@ static void test_hash_speed(const char *algo, unsigned int secs,
        return test_ahash_speed_common(algo, secs, speed, CRYPTO_ALG_ASYNC);
 }
 
-static inline int do_one_acipher_op(struct ablkcipher_request *req, int ret)
+static inline int do_one_acipher_op(struct skcipher_request *req, int ret)
 {
        if (ret == -EINPROGRESS || ret == -EBUSY) {
                struct tcrypt_result *tr = req->base.data;
@@ -825,7 +778,7 @@ static inline int do_one_acipher_op(struct ablkcipher_request *req, int ret)
        return ret;
 }
 
-static int test_acipher_jiffies(struct ablkcipher_request *req, int enc,
+static int test_acipher_jiffies(struct skcipher_request *req, int enc,
                                int blen, int secs)
 {
        unsigned long start, end;
@@ -836,10 +789,10 @@ static int test_acipher_jiffies(struct ablkcipher_request *req, int enc,
             time_before(jiffies, end); bcount++) {
                if (enc)
                        ret = do_one_acipher_op(req,
-                                               crypto_ablkcipher_encrypt(req));
+                                               crypto_skcipher_encrypt(req));
                else
                        ret = do_one_acipher_op(req,
-                                               crypto_ablkcipher_decrypt(req));
+                                               crypto_skcipher_decrypt(req));
 
                if (ret)
                        return ret;
@@ -850,7 +803,7 @@ static int test_acipher_jiffies(struct ablkcipher_request *req, int enc,
        return 0;
 }
 
-static int test_acipher_cycles(struct ablkcipher_request *req, int enc,
+static int test_acipher_cycles(struct skcipher_request *req, int enc,
                               int blen)
 {
        unsigned long cycles = 0;
@@ -861,10 +814,10 @@ static int test_acipher_cycles(struct ablkcipher_request *req, int enc,
        for (i = 0; i < 4; i++) {
                if (enc)
                        ret = do_one_acipher_op(req,
-                                               crypto_ablkcipher_encrypt(req));
+                                               crypto_skcipher_encrypt(req));
                else
                        ret = do_one_acipher_op(req,
-                                               crypto_ablkcipher_decrypt(req));
+                                               crypto_skcipher_decrypt(req));
 
                if (ret)
                        goto out;
@@ -877,10 +830,10 @@ static int test_acipher_cycles(struct ablkcipher_request *req, int enc,
                start = get_cycles();
                if (enc)
                        ret = do_one_acipher_op(req,
-                                               crypto_ablkcipher_encrypt(req));
+                                               crypto_skcipher_encrypt(req));
                else
                        ret = do_one_acipher_op(req,
-                                               crypto_ablkcipher_decrypt(req));
+                                               crypto_skcipher_decrypt(req));
                end = get_cycles();
 
                if (ret)
@@ -897,16 +850,16 @@ out:
        return ret;
 }
 
-static void test_acipher_speed(const char *algo, int enc, unsigned int secs,
-                              struct cipher_speed_template *template,
-                              unsigned int tcount, u8 *keysize)
+static void test_skcipher_speed(const char *algo, int enc, unsigned int secs,
+                               struct cipher_speed_template *template,
+                               unsigned int tcount, u8 *keysize, bool async)
 {
        unsigned int ret, i, j, k, iv_len;
        struct tcrypt_result tresult;
        const char *key;
        char iv[128];
-       struct ablkcipher_request *req;
-       struct crypto_ablkcipher *tfm;
+       struct skcipher_request *req;
+       struct crypto_skcipher *tfm;
        const char *e;
        u32 *b_size;
 
@@ -917,7 +870,7 @@ static void test_acipher_speed(const char *algo, int enc, unsigned int secs,
 
        init_completion(&tresult.completion);
 
-       tfm = crypto_alloc_ablkcipher(algo, 0, 0);
+       tfm = crypto_alloc_skcipher(algo, 0, async ? 0 : CRYPTO_ALG_ASYNC);
 
        if (IS_ERR(tfm)) {
                pr_err("failed to load transform for %s: %ld\n", algo,
@@ -926,17 +879,17 @@ static void test_acipher_speed(const char *algo, int enc, unsigned int secs,
        }
 
        pr_info("\ntesting speed of async %s (%s) %s\n", algo,
-                       get_driver_name(crypto_ablkcipher, tfm), e);
+                       get_driver_name(crypto_skcipher, tfm), e);
 
-       req = ablkcipher_request_alloc(tfm, GFP_KERNEL);
+       req = skcipher_request_alloc(tfm, GFP_KERNEL);
        if (!req) {
                pr_err("tcrypt: skcipher: Failed to allocate request for %s\n",
                       algo);
                goto out;
        }
 
-       ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
-                                       tcrypt_complete, &tresult);
+       skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+                                     tcrypt_complete, &tresult);
 
        i = 0;
        do {
@@ -966,12 +919,12 @@ static void test_acipher_speed(const char *algo, int enc, unsigned int secs,
                                }
                        }
 
-                       crypto_ablkcipher_clear_flags(tfm, ~0);
+                       crypto_skcipher_clear_flags(tfm, ~0);
 
-                       ret = crypto_ablkcipher_setkey(tfm, key, *keysize);
+                       ret = crypto_skcipher_setkey(tfm, key, *keysize);
                        if (ret) {
                                pr_err("setkey() failed flags=%x\n",
-                                       crypto_ablkcipher_get_flags(tfm));
+                                       crypto_skcipher_get_flags(tfm));
                                goto out_free_req;
                        }
 
@@ -995,11 +948,11 @@ static void test_acipher_speed(const char *algo, int enc, unsigned int secs,
                                sg_set_buf(sg, tvmem[0] + *keysize, *b_size);
                        }
 
-                       iv_len = crypto_ablkcipher_ivsize(tfm);
+                       iv_len = crypto_skcipher_ivsize(tfm);
                        if (iv_len)
                                memset(&iv, 0xff, iv_len);
 
-                       ablkcipher_request_set_crypt(req, sg, sg, *b_size, iv);
+                       skcipher_request_set_crypt(req, sg, sg, *b_size, iv);
 
                        if (secs)
                                ret = test_acipher_jiffies(req, enc,
@@ -1010,7 +963,7 @@ static void test_acipher_speed(const char *algo, int enc, unsigned int secs,
 
                        if (ret) {
                                pr_err("%s() failed flags=%x\n", e,
-                                       crypto_ablkcipher_get_flags(tfm));
+                                      crypto_skcipher_get_flags(tfm));
                                break;
                        }
                        b_size++;
@@ -1020,9 +973,25 @@ static void test_acipher_speed(const char *algo, int enc, unsigned int secs,
        } while (*keysize);
 
 out_free_req:
-       ablkcipher_request_free(req);
+       skcipher_request_free(req);
 out:
-       crypto_free_ablkcipher(tfm);
+       crypto_free_skcipher(tfm);
+}
+
+static void test_acipher_speed(const char *algo, int enc, unsigned int secs,
+                              struct cipher_speed_template *template,
+                              unsigned int tcount, u8 *keysize)
+{
+       return test_skcipher_speed(algo, enc, secs, template, tcount, keysize,
+                                  true);
+}
+
+static void test_cipher_speed(const char *algo, int enc, unsigned int secs,
+                             struct cipher_speed_template *template,
+                             unsigned int tcount, u8 *keysize)
+{
+       return test_skcipher_speed(algo, enc, secs, template, tcount, keysize,
+                                  false);
 }
 
 static void test_available(void)
@@ -1284,6 +1253,22 @@ static int do_test(const char *alg, u32 type, u32 mask, int m)
                ret += tcrypt_test("crct10dif");
                break;
 
+       case 48:
+               ret += tcrypt_test("sha3-224");
+               break;
+
+       case 49:
+               ret += tcrypt_test("sha3-256");
+               break;
+
+       case 50:
+               ret += tcrypt_test("sha3-384");
+               break;
+
+       case 51:
+               ret += tcrypt_test("sha3-512");
+               break;
+
        case 100:
                ret += tcrypt_test("hmac(md5)");
                break;
@@ -1328,6 +1313,22 @@ static int do_test(const char *alg, u32 type, u32 mask, int m)
                ret += tcrypt_test("hmac(crc32)");
                break;
 
+       case 111:
+               ret += tcrypt_test("hmac(sha3-224)");
+               break;
+
+       case 112:
+               ret += tcrypt_test("hmac(sha3-256)");
+               break;
+
+       case 113:
+               ret += tcrypt_test("hmac(sha3-384)");
+               break;
+
+       case 114:
+               ret += tcrypt_test("hmac(sha3-512)");
+               break;
+
        case 150:
                ret += tcrypt_test("ansi_cprng");
                break;
@@ -1406,6 +1407,10 @@ static int do_test(const char *alg, u32 type, u32 mask, int m)
                                speed_template_32_48_64);
                test_cipher_speed("xts(aes)", DECRYPT, sec, NULL, 0,
                                speed_template_32_48_64);
+               test_cipher_speed("cts(cbc(aes))", ENCRYPT, sec, NULL, 0,
+                               speed_template_16_24_32);
+               test_cipher_speed("cts(cbc(aes))", DECRYPT, sec, NULL, 0,
+                               speed_template_16_24_32);
                test_cipher_speed("ctr(aes)", ENCRYPT, sec, NULL, 0,
                                speed_template_16_24_32);
                test_cipher_speed("ctr(aes)", DECRYPT, sec, NULL, 0,
@@ -1691,6 +1696,22 @@ static int do_test(const char *alg, u32 type, u32 mask, int m)
                test_hash_speed("poly1305", sec, poly1305_speed_template);
                if (mode > 300 && mode < 400) break;
 
+       case 322:
+               test_hash_speed("sha3-224", sec, generic_hash_speed_template);
+               if (mode > 300 && mode < 400) break;
+
+       case 323:
+               test_hash_speed("sha3-256", sec, generic_hash_speed_template);
+               if (mode > 300 && mode < 400) break;
+
+       case 324:
+               test_hash_speed("sha3-384", sec, generic_hash_speed_template);
+               if (mode > 300 && mode < 400) break;
+
+       case 325:
+               test_hash_speed("sha3-512", sec, generic_hash_speed_template);
+               if (mode > 300 && mode < 400) break;
+
        case 399:
                break;
 
@@ -1770,6 +1791,35 @@ static int do_test(const char *alg, u32 type, u32 mask, int m)
                test_ahash_speed("rmd320", sec, generic_hash_speed_template);
                if (mode > 400 && mode < 500) break;
 
+       case 418:
+               test_ahash_speed("sha3-224", sec, generic_hash_speed_template);
+               if (mode > 400 && mode < 500) break;
+
+       case 419:
+               test_ahash_speed("sha3-256", sec, generic_hash_speed_template);
+               if (mode > 400 && mode < 500) break;
+
+       case 420:
+               test_ahash_speed("sha3-384", sec, generic_hash_speed_template);
+               if (mode > 400 && mode < 500) break;
+
+
+       case 421:
+               test_ahash_speed("sha3-512", sec, generic_hash_speed_template);
+               if (mode > 400 && mode < 500) break;
+
+       case 422:
+               test_mb_ahash_speed("sha1", sec, generic_hash_speed_template);
+               if (mode > 400 && mode < 500) break;
+
+       case 423:
+               test_mb_ahash_speed("sha256", sec, generic_hash_speed_template);
+               if (mode > 400 && mode < 500) break;
+
+       case 424:
+               test_mb_ahash_speed("sha512", sec, generic_hash_speed_template);
+               if (mode > 400 && mode < 500) break;
+
        case 499:
                break;
 
@@ -1790,6 +1840,10 @@ static int do_test(const char *alg, u32 type, u32 mask, int m)
                                   speed_template_32_48_64);
                test_acipher_speed("xts(aes)", DECRYPT, sec, NULL, 0,
                                   speed_template_32_48_64);
+               test_acipher_speed("cts(cbc(aes))", ENCRYPT, sec, NULL, 0,
+                                  speed_template_16_24_32);
+               test_acipher_speed("cts(cbc(aes))", DECRYPT, sec, NULL, 0,
+                                  speed_template_16_24_32);
                test_acipher_speed("ctr(aes)", ENCRYPT, sec, NULL, 0,
                                   speed_template_16_24_32);
                test_acipher_speed("ctr(aes)", DECRYPT, sec, NULL, 0,