diff options
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.patch | 315 |
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 00000000..4745dc90 --- /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 + |