1 From f123f38532ae022e818312a9bc04cdb287e9623f Mon Sep 17 00:00:00 2001
2 From: Cristian Stoica <cristian.stoica@nxp.com>
3 Date: Thu, 17 Dec 2015 10:34:20 +0200
4 Subject: [PATCH 35/38] use directly crypto API 'digest' operation for CIOCHASH
6 Signed-off-by: Cristian Stoica <cristian.stoica@nxp.com>
8 crypto/cryptodev.h | 2 +-
9 cryptodev_int.h | 10 ++++
10 ioctl.c | 158 ++++++++++++++++++++++++++++++++++++++++++++---------
11 main.c | 39 ++++++++++++-
12 4 files changed, 179 insertions(+), 30 deletions(-)
14 diff --git a/crypto/cryptodev.h b/crypto/cryptodev.h
15 index c6083f7..9ade102 100644
16 --- a/crypto/cryptodev.h
17 +++ b/crypto/cryptodev.h
18 @@ -169,7 +169,7 @@ struct crypt_auth_op {
20 /* data container for CIOCHASH operations */
22 - __u32 ses; /* session identifier */
23 + struct csession *ses; /* session identifier */
24 __u32 mac_op; /* cryptodev_crypto_op_t */
27 diff --git a/cryptodev_int.h b/cryptodev_int.h
28 index cb005d7..74c295a 100644
31 @@ -164,6 +164,15 @@ struct kernel_crypt_op {
35 +struct kernel_hash_op {
36 + struct hash_op_data hash_op;
39 + uint8_t hash_output[AALG_MAX_RESULT_LEN];
40 + struct task_struct *task;
41 + struct mm_struct *mm;
44 struct kernel_crypt_auth_op {
45 struct crypt_auth_op caop;
47 @@ -192,6 +201,7 @@ int kcaop_to_user(struct kernel_crypt_auth_op *kcaop,
48 struct fcrypt *fcr, void __user *arg);
49 int crypto_auth_run(struct fcrypt *fcr, struct kernel_crypt_auth_op *kcaop);
50 int crypto_run(struct fcrypt *fcr, struct kernel_crypt_op *kcop);
51 +int hash_run(struct kernel_hash_op *khop);
55 diff --git a/ioctl.c b/ioctl.c
56 index 3763954..a052614 100644
59 @@ -397,7 +397,128 @@ session_error:
63 -/* Everything that needs to be done when removing a session. */
64 +static inline void hash_destroy_session(struct csession *ses_ptr)
66 + cryptodev_hash_deinit(&ses_ptr->hdata);
67 + kfree(ses_ptr->pages);
72 +static int hash_create_session(struct hash_op_data *hash_op)
74 + struct csession *ses;
76 + const char *hash_name;
78 + uint8_t mkey[CRYPTO_HMAC_MAX_KEY_LEN];
80 + switch (hash_op->mac_op) {
81 + case CRYPTO_MD5_HMAC:
82 + hash_name = "hmac(md5)";
84 + case CRYPTO_RIPEMD160_HMAC:
85 + hash_name = "hmac(rmd160)";
87 + case CRYPTO_SHA1_HMAC:
88 + hash_name = "hmac(sha1)";
90 + case CRYPTO_SHA2_224_HMAC:
91 + hash_name = "hmac(sha224)";
93 + case CRYPTO_SHA2_256_HMAC:
94 + hash_name = "hmac(sha256)";
96 + case CRYPTO_SHA2_384_HMAC:
97 + hash_name = "hmac(sha384)";
99 + case CRYPTO_SHA2_512_HMAC:
100 + hash_name = "hmac(sha512)";
102 + /* non-hmac cases */
107 + case CRYPTO_RIPEMD160:
108 + hash_name = "rmd160";
112 + hash_name = "sha1";
115 + case CRYPTO_SHA2_224:
116 + hash_name = "sha224";
119 + case CRYPTO_SHA2_256:
120 + hash_name = "sha256";
123 + case CRYPTO_SHA2_384:
124 + hash_name = "sha384";
127 + case CRYPTO_SHA2_512:
128 + hash_name = "sha512";
132 + ddebug(1, "bad mac: %d", hash_op->mac_op);
136 + ses = kzalloc(sizeof(*ses), GFP_KERNEL);
141 + if (unlikely(hash_op->mackeylen > CRYPTO_HMAC_MAX_KEY_LEN)) {
142 + ddebug(1, "Setting key failed for %s-%zu.", hash_name,
143 + (size_t)hash_op->mackeylen * 8);
148 + if (hash_op->mackey &&
149 + unlikely(copy_from_user(mkey, hash_op->mackey, hash_op->mackeylen))) {
154 + ret = cryptodev_hash_init(&ses->hdata, hash_name, hmac_mode,
155 + mkey, hash_op->mackeylen);
157 + ddebug(1, "Failed to load hash for %s", hash_name);
162 + ses->alignmask = ses->hdata.alignmask;
163 + ddebug(2, "got alignmask %d", ses->alignmask);
165 + ses->array_size = DEFAULT_PREALLOC_PAGES;
166 + ddebug(2, "preallocating for %d user pages", ses->array_size);
168 + ses->pages = kzalloc(ses->array_size * sizeof(struct page *), GFP_KERNEL);
169 + ses->sg = kzalloc(ses->array_size * sizeof(struct scatterlist), GFP_KERNEL);
170 + if (ses->sg == NULL || ses->pages == NULL) {
171 + ddebug(0, "Memory error");
176 + hash_op->ses = ses;
180 + hash_destroy_session(ses);
185 +/* Everything that needs to be done when remowing a session. */
187 crypto_destroy_session(struct csession *ses_ptr)
189 @@ -960,7 +1081,7 @@ cryptodev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg_)
190 void __user *arg = (void __user *)arg_;
192 struct session_op sop;
193 - struct hash_op_data hash_op;
194 + struct kernel_hash_op khop;
195 struct kernel_crypt_op kcop;
196 struct kernel_crypt_auth_op kcaop;
197 struct crypt_priv *pcr = filp->private_data;
198 @@ -1051,52 +1172,35 @@ cryptodev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg_)
200 return kcop_to_user(&kcop, fcr, arg);
203 - if (unlikely(copy_from_user(&hash_op, arg, sizeof(struct hash_op_data)))) {
204 + if (unlikely(copy_from_user(&khop.hash_op, arg, sizeof(struct hash_op_data)))) {
205 pr_err("copy from user fault\n");
208 + khop.task = current;
209 + khop.mm = current->mm;
212 - sop.mac = hash_op.mac_op;
213 - sop.mackey = hash_op.mackey;
214 - sop.mackeylen = hash_op.mackeylen;
216 - /* writes sop.ses as a side-effect */
217 - ret = crypto_create_session(fcr, &sop);
219 + ret = hash_create_session(&khop.hash_op);
221 pr_err("can't get session\n");
226 - kcop.cop.ses = sop.ses;
227 - kcop.cop.flags = hash_op.flags;
228 - kcop.cop.len = hash_op.len;
229 - kcop.cop.src = hash_op.src;
230 - kcop.cop.mac = hash_op.mac_result;
235 - kcop.digestsize = 0; /* will be updated during operation */
236 - kcop.task = current;
237 - kcop.mm = current->mm;
239 - ret = crypto_run(fcr, &kcop);
240 + ret = hash_run(&khop);
242 dwarning(1, "Error in hash run");
246 - ret = copy_to_user(kcop.cop.mac, kcop.hash_output, kcop.digestsize);
247 + ret = copy_to_user(khop.hash_op.mac_result, khop.hash_output, khop.digestsize);
249 dwarning(1, "Error in copy to user");
254 - ret = crypto_finish_session(fcr, sop.ses);
255 + hash_destroy_session(khop.hash_op.ses);
258 if (unlikely(ret = kcaop_from_user(&kcaop, fcr, arg))) {
259 diff --git a/main.c b/main.c
260 index ec11129..095aea5 100644
263 @@ -159,8 +159,6 @@ __crypto_run_std(struct csession *ses_ptr, struct crypt_op *cop)
269 /* This is the main crypto function - zero-copy edition */
271 __crypto_run_zc(struct csession *ses_ptr, struct kernel_crypt_op *kcop)
272 @@ -841,3 +839,40 @@ out_unlock:
273 crypto_put_session(ses_ptr);
277 +int hash_run(struct kernel_hash_op *khop)
279 + struct hash_op_data *hash_op = &khop->hash_op;
280 + struct csession *ses_ptr = hash_op->ses;
281 + struct hash_data *hdata = &ses_ptr->hdata;
283 + struct scatterlist *src_sg;
284 + struct scatterlist *dst_sg; /* required by get_userbuf but not used */
286 + if (hash_op->len == 0) {
289 + ret = get_userbuf(ses_ptr, hash_op->src, hash_op->len, NULL, 0,
290 + khop->task, khop->mm, &src_sg, &dst_sg);
291 + if (unlikely(ret)) {
292 + derr(1, "Error getting user pages");
297 + ahash_request_set_crypt(hdata->async.request, src_sg, khop->hash_output, hash_op->len);
299 + ret = crypto_ahash_digest(hdata->async.request);
300 + if (ret == -EINPROGRESS || ret == -EBUSY) {
301 + wait_for_completion(&hdata->async.result.completion);
302 + ret = hdata->async.result.err;
304 + derr(0, "CryptoAPI failure: %d", ret);
308 + khop->digestsize = ses_ptr->hdata.digestsize;
310 + release_user_pages(ses_ptr);