These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / crypto / tcrypt.c
index 1a28001..46a4a75 100644 (file)
  *
  */
 
+#include <crypto/aead.h>
 #include <crypto/hash.h>
 #include <linux/err.h>
+#include <linux/fips.h>
 #include <linux/init.h>
 #include <linux/gfp.h>
 #include <linux/module.h>
@@ -34,7 +36,6 @@
 #include <linux/timex.h>
 #include <linux/interrupt.h>
 #include "tcrypt.h"
-#include "internal.h"
 
 /*
  * Need slab memory for testing (size in number of pages).
@@ -47,6 +48,8 @@
 #define ENCRYPT 1
 #define DECRYPT 0
 
+#define MAX_DIGEST_SIZE                64
+
 /*
  * return a string with the driver name
  */
@@ -72,6 +75,22 @@ static char *check[] = {
        "lzo", "cts", "zlib", NULL
 };
 
+struct tcrypt_result {
+       struct completion completion;
+       int err;
+};
+
+static void tcrypt_complete(struct crypto_async_request *req, int err)
+{
+       struct tcrypt_result *res = req->data;
+
+       if (err == -EINPROGRESS)
+               return;
+
+       res->err = err;
+       complete(&res->completion);
+}
+
 static int test_cipher_jiffies(struct blkcipher_desc *desc, int enc,
                               struct scatterlist *sg, int blen, int secs)
 {
@@ -142,6 +161,20 @@ out:
        return ret;
 }
 
+static inline int do_one_aead_op(struct aead_request *req, int ret)
+{
+       if (ret == -EINPROGRESS || ret == -EBUSY) {
+               struct tcrypt_result *tr = req->base.data;
+
+               ret = wait_for_completion_interruptible(&tr->completion);
+               if (!ret)
+                       ret = tr->err;
+               reinit_completion(&tr->completion);
+       }
+
+       return ret;
+}
+
 static int test_aead_jiffies(struct aead_request *req, int enc,
                                int blen, int secs)
 {
@@ -152,9 +185,9 @@ static int test_aead_jiffies(struct aead_request *req, int enc,
        for (start = jiffies, end = start + secs * HZ, bcount = 0;
             time_before(jiffies, end); bcount++) {
                if (enc)
-                       ret = crypto_aead_encrypt(req);
+                       ret = do_one_aead_op(req, crypto_aead_encrypt(req));
                else
-                       ret = crypto_aead_decrypt(req);
+                       ret = do_one_aead_op(req, crypto_aead_decrypt(req));
 
                if (ret)
                        return ret;
@@ -176,9 +209,9 @@ static int test_aead_cycles(struct aead_request *req, int enc, int blen)
        /* Warm-up run. */
        for (i = 0; i < 4; i++) {
                if (enc)
-                       ret = crypto_aead_encrypt(req);
+                       ret = do_one_aead_op(req, crypto_aead_encrypt(req));
                else
-                       ret = crypto_aead_decrypt(req);
+                       ret = do_one_aead_op(req, crypto_aead_decrypt(req));
 
                if (ret)
                        goto out;
@@ -190,9 +223,9 @@ static int test_aead_cycles(struct aead_request *req, int enc, int blen)
 
                start = get_cycles();
                if (enc)
-                       ret = crypto_aead_encrypt(req);
+                       ret = do_one_aead_op(req, crypto_aead_encrypt(req));
                else
-                       ret = crypto_aead_decrypt(req);
+                       ret = do_one_aead_op(req, crypto_aead_decrypt(req));
                end = get_cycles();
 
                if (ret)
@@ -257,12 +290,12 @@ static void sg_init_aead(struct scatterlist *sg, char *xbuf[XBUFSIZE],
                rem = buflen % PAGE_SIZE;
        }
 
-       sg_init_table(sg, np);
+       sg_init_table(sg, np + 1);
        np--;
        for (k = 0; k < np; k++)
-               sg_set_buf(&sg[k], xbuf[k], PAGE_SIZE);
+               sg_set_buf(&sg[k + 1], xbuf[k], PAGE_SIZE);
 
-       sg_set_buf(&sg[k], xbuf[k], rem);
+       sg_set_buf(&sg[k + 1], xbuf[k], rem);
 }
 
 static void test_aead_speed(const char *algo, int enc, unsigned int secs,
@@ -276,7 +309,6 @@ static void test_aead_speed(const char *algo, int enc, unsigned int secs,
        const char *key;
        struct aead_request *req;
        struct scatterlist *sg;
-       struct scatterlist *asg;
        struct scatterlist *sgout;
        const char *e;
        void *assoc;
@@ -286,6 +318,7 @@ static void test_aead_speed(const char *algo, int enc, unsigned int secs,
        char *axbuf[XBUFSIZE];
        unsigned int *b_size;
        unsigned int iv_len;
+       struct tcrypt_result result;
 
        iv = kzalloc(MAX_IVLEN, GFP_KERNEL);
        if (!iv)
@@ -308,11 +341,10 @@ static void test_aead_speed(const char *algo, int enc, unsigned int secs,
        if (testmgr_alloc_buf(xoutbuf))
                goto out_nooutbuf;
 
-       sg = kmalloc(sizeof(*sg) * 8 * 3, GFP_KERNEL);
+       sg = kmalloc(sizeof(*sg) * 9 * 2, GFP_KERNEL);
        if (!sg)
                goto out_nosg;
-       asg = &sg[8];
-       sgout = &asg[8];
+       sgout = &sg[9];
 
        tfm = crypto_alloc_aead(algo, 0, 0);
 
@@ -322,6 +354,7 @@ static void test_aead_speed(const char *algo, int enc, unsigned int secs,
                goto out_notfm;
        }
 
+       init_completion(&result.completion);
        printk(KERN_INFO "\ntesting speed of %s (%s) %s\n", algo,
                        get_driver_name(crypto_aead, tfm), e);
 
@@ -332,13 +365,15 @@ static void test_aead_speed(const char *algo, int enc, unsigned int secs,
                goto out_noreq;
        }
 
+       aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+                                 tcrypt_complete, &result);
+
        i = 0;
        do {
                b_size = aead_sizes;
                do {
                        assoc = axbuf[0];
                        memset(assoc, 0xff, aad_size);
-                       sg_init_one(&asg[0], assoc, aad_size);
 
                        if ((*keysize + *b_size) > TVMEMSIZE * PAGE_SIZE) {
                                pr_err("template (%u) too big for tvmem (%lu)\n",
@@ -374,14 +409,17 @@ static void test_aead_speed(const char *algo, int enc, unsigned int secs,
                                goto out;
                        }
 
-                       sg_init_aead(&sg[0], xbuf,
+                       sg_init_aead(sg, xbuf,
                                    *b_size + (enc ? authsize : 0));
 
-                       sg_init_aead(&sgout[0], xoutbuf,
+                       sg_init_aead(sgout, xoutbuf,
                                    *b_size + (enc ? authsize : 0));
 
+                       sg_set_buf(&sg[0], assoc, aad_size);
+                       sg_set_buf(&sgout[0], assoc, aad_size);
+
                        aead_request_set_crypt(req, sg, sgout, *b_size, iv);
-                       aead_request_set_assoc(req, asg, aad_size);
+                       aead_request_set_ad(req, aad_size);
 
                        if (secs)
                                ret = test_aead_jiffies(req, enc, *b_size,
@@ -748,22 +786,6 @@ out:
        crypto_free_hash(tfm);
 }
 
-struct tcrypt_result {
-       struct completion completion;
-       int err;
-};
-
-static void tcrypt_complete(struct crypto_async_request *req, int err)
-{
-       struct tcrypt_result *res = req->data;
-
-       if (err == -EINPROGRESS)
-               return;
-
-       res->err = err;
-       complete(&res->completion);
-}
-
 static inline int do_one_ahash_op(struct ahash_request *req, int ret)
 {
        if (ret == -EINPROGRESS || ret == -EBUSY) {
@@ -808,7 +830,7 @@ static int test_ahash_jiffies(struct ahash_request *req, int blen,
 
        for (start = jiffies, end = start + secs * HZ, bcount = 0;
             time_before(jiffies, end); bcount++) {
-               ret = crypto_ahash_init(req);
+               ret = do_one_ahash_op(req, crypto_ahash_init(req));
                if (ret)
                        return ret;
                for (pcount = 0; pcount < blen; pcount += plen) {
@@ -877,7 +899,7 @@ static int test_ahash_cycles(struct ahash_request *req, int blen,
 
        /* Warm-up run. */
        for (i = 0; i < 4; i++) {
-               ret = crypto_ahash_init(req);
+               ret = do_one_ahash_op(req, crypto_ahash_init(req));
                if (ret)
                        goto out;
                for (pcount = 0; pcount < blen; pcount += plen) {
@@ -896,7 +918,7 @@ static int test_ahash_cycles(struct ahash_request *req, int blen,
 
                start = get_cycles();
 
-               ret = crypto_ahash_init(req);
+               ret = do_one_ahash_op(req, crypto_ahash_init(req));
                if (ret)
                        goto out;
                for (pcount = 0; pcount < blen; pcount += plen) {
@@ -930,7 +952,7 @@ static void test_ahash_speed(const char *algo, unsigned int secs,
        struct tcrypt_result tresult;
        struct ahash_request *req;
        struct crypto_ahash *tfm;
-       static char output[1024];
+       char *output;
        int i, ret;
 
        tfm = crypto_alloc_ahash(algo, 0, 0);
@@ -943,9 +965,9 @@ static void test_ahash_speed(const char *algo, unsigned int secs,
        printk(KERN_INFO "\ntesting speed of async %s (%s)\n", algo,
                        get_driver_name(crypto_ahash, tfm));
 
-       if (crypto_ahash_digestsize(tfm) > sizeof(output)) {
-               pr_err("digestsize(%u) > outputbuffer(%zu)\n",
-                      crypto_ahash_digestsize(tfm), sizeof(output));
+       if (crypto_ahash_digestsize(tfm) > MAX_DIGEST_SIZE) {
+               pr_err("digestsize(%u) > %d\n", crypto_ahash_digestsize(tfm),
+                      MAX_DIGEST_SIZE);
                goto out;
        }
 
@@ -960,6 +982,10 @@ static void test_ahash_speed(const char *algo, unsigned int secs,
        ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
                                   tcrypt_complete, &tresult);
 
+       output = kmalloc(MAX_DIGEST_SIZE, GFP_KERNEL);
+       if (!output)
+               goto out_nomem;
+
        for (i = 0; speed[i].blen != 0; i++) {
                if (speed[i].blen > TVMEMSIZE * PAGE_SIZE) {
                        pr_err("template (%u) too big for tvmem (%lu)\n",
@@ -986,6 +1012,9 @@ static void test_ahash_speed(const char *algo, unsigned int secs,
                }
        }
 
+       kfree(output);
+
+out_nomem:
        ahash_request_free(req);
 
 out:
@@ -1758,9 +1787,27 @@ static int do_test(const char *alg, u32 type, u32 mask, int m)
 
        case 211:
                test_aead_speed("rfc4106(gcm(aes))", ENCRYPT, sec,
+                               NULL, 0, 16, 16, aead_speed_template_20);
+               test_aead_speed("gcm(aes)", ENCRYPT, sec,
                                NULL, 0, 16, 8, aead_speed_template_20);
                break;
 
+       case 212:
+               test_aead_speed("rfc4309(ccm(aes))", ENCRYPT, sec,
+                               NULL, 0, 16, 16, aead_speed_template_19);
+               break;
+
+       case 213:
+               test_aead_speed("rfc7539esp(chacha20,poly1305)", ENCRYPT, sec,
+                               NULL, 0, 16, 8, aead_speed_template_36);
+               break;
+
+       case 214:
+               test_cipher_speed("chacha20", ENCRYPT, sec, NULL, 0,
+                                 speed_template_32);
+               break;
+
+
        case 300:
                if (alg) {
                        test_hash_speed(alg, sec, generic_hash_speed_template);
@@ -1849,6 +1896,10 @@ static int do_test(const char *alg, u32 type, u32 mask, int m)
                test_hash_speed("crct10dif", sec, generic_hash_speed_template);
                if (mode > 300 && mode < 400) break;
 
+       case 321:
+               test_hash_speed("poly1305", sec, poly1305_speed_template);
+               if (mode > 300 && mode < 400) break;
+
        case 399:
                break;