aboutsummaryrefslogtreecommitdiffstats
path: root/recipes-kernel/cryptodev/sdk_patches/0035-use-directly-crypto-API-digest-operation-for-CIOCHAS.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes-kernel/cryptodev/sdk_patches/0035-use-directly-crypto-API-digest-operation-for-CIOCHAS.patch')
-rw-r--r--recipes-kernel/cryptodev/sdk_patches/0035-use-directly-crypto-API-digest-operation-for-CIOCHAS.patch315
1 files changed, 315 insertions, 0 deletions
diff --git a/recipes-kernel/cryptodev/sdk_patches/0035-use-directly-crypto-API-digest-operation-for-CIOCHAS.patch b/recipes-kernel/cryptodev/sdk_patches/0035-use-directly-crypto-API-digest-operation-for-CIOCHAS.patch
new file mode 100644
index 0000000..4745dc9
--- /dev/null
+++ b/recipes-kernel/cryptodev/sdk_patches/0035-use-directly-crypto-API-digest-operation-for-CIOCHAS.patch
@@ -0,0 +1,315 @@
+From f123f38532ae022e818312a9bc04cdb287e9623f Mon Sep 17 00:00:00 2001
+From: Cristian Stoica <cristian.stoica@nxp.com>
+Date: Thu, 17 Dec 2015 10:34:20 +0200
+Subject: [PATCH 35/38] use directly crypto API 'digest' operation for CIOCHASH
+
+Signed-off-by: Cristian Stoica <cristian.stoica@nxp.com>
+---
+ crypto/cryptodev.h | 2 +-
+ cryptodev_int.h | 10 ++++
+ ioctl.c | 158 ++++++++++++++++++++++++++++++++++++++++++++---------
+ main.c | 39 ++++++++++++-
+ 4 files changed, 179 insertions(+), 30 deletions(-)
+
+diff --git a/crypto/cryptodev.h b/crypto/cryptodev.h
+index c6083f7..9ade102 100644
+--- a/crypto/cryptodev.h
++++ b/crypto/cryptodev.h
+@@ -169,7 +169,7 @@ struct crypt_auth_op {
+
+ /* data container for CIOCHASH operations */
+ struct hash_op_data {
+- __u32 ses; /* session identifier */
++ struct csession *ses; /* session identifier */
+ __u32 mac_op; /* cryptodev_crypto_op_t */
+ __u8 *mackey;
+ __u32 mackeylen;
+diff --git a/cryptodev_int.h b/cryptodev_int.h
+index cb005d7..74c295a 100644
+--- a/cryptodev_int.h
++++ b/cryptodev_int.h
+@@ -164,6 +164,15 @@ struct kernel_crypt_op {
+ struct mm_struct *mm;
+ };
+
++struct kernel_hash_op {
++ struct hash_op_data hash_op;
++
++ int digestsize;
++ uint8_t hash_output[AALG_MAX_RESULT_LEN];
++ struct task_struct *task;
++ struct mm_struct *mm;
++};
++
+ struct kernel_crypt_auth_op {
+ struct crypt_auth_op caop;
+
+@@ -192,6 +201,7 @@ int kcaop_to_user(struct kernel_crypt_auth_op *kcaop,
+ struct fcrypt *fcr, void __user *arg);
+ int crypto_auth_run(struct fcrypt *fcr, struct kernel_crypt_auth_op *kcaop);
+ int crypto_run(struct fcrypt *fcr, struct kernel_crypt_op *kcop);
++int hash_run(struct kernel_hash_op *khop);
+
+ #include <cryptlib.h>
+
+diff --git a/ioctl.c b/ioctl.c
+index 3763954..a052614 100644
+--- a/ioctl.c
++++ b/ioctl.c
+@@ -397,7 +397,128 @@ session_error:
+ return ret;
+ }
+
+-/* Everything that needs to be done when removing a session. */
++static inline void hash_destroy_session(struct csession *ses_ptr)
++{
++ cryptodev_hash_deinit(&ses_ptr->hdata);
++ kfree(ses_ptr->pages);
++ kfree(ses_ptr->sg);
++ kfree(ses_ptr);
++}
++
++static int hash_create_session(struct hash_op_data *hash_op)
++{
++ struct csession *ses;
++ int ret = 0;
++ const char *hash_name;
++ int hmac_mode = 1;
++ uint8_t mkey[CRYPTO_HMAC_MAX_KEY_LEN];
++
++ switch (hash_op->mac_op) {
++ case CRYPTO_MD5_HMAC:
++ hash_name = "hmac(md5)";
++ break;
++ case CRYPTO_RIPEMD160_HMAC:
++ hash_name = "hmac(rmd160)";
++ break;
++ case CRYPTO_SHA1_HMAC:
++ hash_name = "hmac(sha1)";
++ break;
++ case CRYPTO_SHA2_224_HMAC:
++ hash_name = "hmac(sha224)";
++ break;
++ case CRYPTO_SHA2_256_HMAC:
++ hash_name = "hmac(sha256)";
++ break;
++ case CRYPTO_SHA2_384_HMAC:
++ hash_name = "hmac(sha384)";
++ break;
++ case CRYPTO_SHA2_512_HMAC:
++ hash_name = "hmac(sha512)";
++ break;
++ /* non-hmac cases */
++ case CRYPTO_MD5:
++ hash_name = "md5";
++ hmac_mode = 0;
++ break;
++ case CRYPTO_RIPEMD160:
++ hash_name = "rmd160";
++ hmac_mode = 0;
++ break;
++ case CRYPTO_SHA1:
++ hash_name = "sha1";
++ hmac_mode = 0;
++ break;
++ case CRYPTO_SHA2_224:
++ hash_name = "sha224";
++ hmac_mode = 0;
++ break;
++ case CRYPTO_SHA2_256:
++ hash_name = "sha256";
++ hmac_mode = 0;
++ break;
++ case CRYPTO_SHA2_384:
++ hash_name = "sha384";
++ hmac_mode = 0;
++ break;
++ case CRYPTO_SHA2_512:
++ hash_name = "sha512";
++ hmac_mode = 0;
++ break;
++ default:
++ ddebug(1, "bad mac: %d", hash_op->mac_op);
++ return -EINVAL;
++ }
++
++ ses = kzalloc(sizeof(*ses), GFP_KERNEL);
++ if (!ses) {
++ return -ENOMEM;
++ }
++
++ if (unlikely(hash_op->mackeylen > CRYPTO_HMAC_MAX_KEY_LEN)) {
++ ddebug(1, "Setting key failed for %s-%zu.", hash_name,
++ (size_t)hash_op->mackeylen * 8);
++ ret = -EINVAL;
++ goto error_hash;
++ }
++
++ if (hash_op->mackey &&
++ unlikely(copy_from_user(mkey, hash_op->mackey, hash_op->mackeylen))) {
++ ret = -EFAULT;
++ goto error_hash;
++ }
++
++ ret = cryptodev_hash_init(&ses->hdata, hash_name, hmac_mode,
++ mkey, hash_op->mackeylen);
++ if (ret != 0) {
++ ddebug(1, "Failed to load hash for %s", hash_name);
++ ret = -EINVAL;
++ goto error_hash;
++ }
++
++ ses->alignmask = ses->hdata.alignmask;
++ ddebug(2, "got alignmask %d", ses->alignmask);
++
++ ses->array_size = DEFAULT_PREALLOC_PAGES;
++ ddebug(2, "preallocating for %d user pages", ses->array_size);
++
++ ses->pages = kzalloc(ses->array_size * sizeof(struct page *), GFP_KERNEL);
++ ses->sg = kzalloc(ses->array_size * sizeof(struct scatterlist), GFP_KERNEL);
++ if (ses->sg == NULL || ses->pages == NULL) {
++ ddebug(0, "Memory error");
++ ret = -ENOMEM;
++ goto error_hash;
++ }
++
++ hash_op->ses = ses;
++ return 0;
++
++error_hash:
++ hash_destroy_session(ses);
++ return ret;
++}
++
++
++/* Everything that needs to be done when remowing a session. */
+ static inline void
+ crypto_destroy_session(struct csession *ses_ptr)
+ {
+@@ -960,7 +1081,7 @@ cryptodev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg_)
+ void __user *arg = (void __user *)arg_;
+ int __user *p = arg;
+ struct session_op sop;
+- struct hash_op_data hash_op;
++ struct kernel_hash_op khop;
+ struct kernel_crypt_op kcop;
+ struct kernel_crypt_auth_op kcaop;
+ struct crypt_priv *pcr = filp->private_data;
+@@ -1051,52 +1172,35 @@ cryptodev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg_)
+
+ return kcop_to_user(&kcop, fcr, arg);
+ case CIOCHASH:
+- /* get session */
+- if (unlikely(copy_from_user(&hash_op, arg, sizeof(struct hash_op_data)))) {
++ if (unlikely(copy_from_user(&khop.hash_op, arg, sizeof(struct hash_op_data)))) {
+ pr_err("copy from user fault\n");
+ return -EFAULT;
+ }
++ khop.task = current;
++ khop.mm = current->mm;
+
+- sop.cipher = 0;
+- sop.mac = hash_op.mac_op;
+- sop.mackey = hash_op.mackey;
+- sop.mackeylen = hash_op.mackeylen;
+-
+- /* writes sop.ses as a side-effect */
+- ret = crypto_create_session(fcr, &sop);
++ /* get session */
++ ret = hash_create_session(&khop.hash_op);
+ if (unlikely(ret)) {
+ pr_err("can't get session\n");
+ return ret;
+ }
+
+ /* do hashing */
+- kcop.cop.ses = sop.ses;
+- kcop.cop.flags = hash_op.flags;
+- kcop.cop.len = hash_op.len;
+- kcop.cop.src = hash_op.src;
+- kcop.cop.mac = hash_op.mac_result;
+- kcop.cop.dst = 0;
+- kcop.cop.op = 0;
+- kcop.cop.iv = 0;
+- kcop.ivlen = 0;
+- kcop.digestsize = 0; /* will be updated during operation */
+- kcop.task = current;
+- kcop.mm = current->mm;
+-
+- ret = crypto_run(fcr, &kcop);
++ ret = hash_run(&khop);
+ if (unlikely(ret)) {
+ dwarning(1, "Error in hash run");
+ return ret;
+ }
+
+- ret = copy_to_user(kcop.cop.mac, kcop.hash_output, kcop.digestsize);
++ ret = copy_to_user(khop.hash_op.mac_result, khop.hash_output, khop.digestsize);
+ if (unlikely(ret)) {
+ dwarning(1, "Error in copy to user");
+ return ret;
+ }
+
+ /* put session */
+- ret = crypto_finish_session(fcr, sop.ses);
++ hash_destroy_session(khop.hash_op.ses);
+ return 0;
+ case CIOCAUTHCRYPT:
+ if (unlikely(ret = kcaop_from_user(&kcaop, fcr, arg))) {
+diff --git a/main.c b/main.c
+index ec11129..095aea5 100644
+--- a/main.c
++++ b/main.c
+@@ -159,8 +159,6 @@ __crypto_run_std(struct csession *ses_ptr, struct crypt_op *cop)
+ return ret;
+ }
+
+-
+-
+ /* This is the main crypto function - zero-copy edition */
+ static int
+ __crypto_run_zc(struct csession *ses_ptr, struct kernel_crypt_op *kcop)
+@@ -841,3 +839,40 @@ out_unlock:
+ crypto_put_session(ses_ptr);
+ return ret;
+ }
++
++int hash_run(struct kernel_hash_op *khop)
++{
++ struct hash_op_data *hash_op = &khop->hash_op;
++ struct csession *ses_ptr = hash_op->ses;
++ struct hash_data *hdata = &ses_ptr->hdata;
++ int ret;
++ struct scatterlist *src_sg;
++ struct scatterlist *dst_sg; /* required by get_userbuf but not used */
++
++ if (hash_op->len == 0) {
++ src_sg = NULL;
++ } else {
++ ret = get_userbuf(ses_ptr, hash_op->src, hash_op->len, NULL, 0,
++ khop->task, khop->mm, &src_sg, &dst_sg);
++ if (unlikely(ret)) {
++ derr(1, "Error getting user pages");
++ return ret;
++ }
++ }
++
++ ahash_request_set_crypt(hdata->async.request, src_sg, khop->hash_output, hash_op->len);
++
++ ret = crypto_ahash_digest(hdata->async.request);
++ if (ret == -EINPROGRESS || ret == -EBUSY) {
++ wait_for_completion(&hdata->async.result.completion);
++ ret = hdata->async.result.err;
++ if (ret != 0) {
++ derr(0, "CryptoAPI failure: %d", ret);
++ }
++ }
++
++ khop->digestsize = ses_ptr->hdata.digestsize;
++
++ release_user_pages(ses_ptr);
++ return ret;
++}
+--
+2.7.0
+