]> code.ossystems Code Review - meta-freescale.git/blob
4745dc9065771de298de3226d68c2b3565b6c490
[meta-freescale.git] /
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
5
6 Signed-off-by: Cristian Stoica <cristian.stoica@nxp.com>
7 ---
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(-)
13
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 {
19  
20  /* data container for CIOCHASH operations */
21  struct hash_op_data {
22 -       __u32   ses;            /* session identifier */
23 +       struct csession *ses;   /* session identifier */
24         __u32   mac_op;         /* cryptodev_crypto_op_t */
25         __u8    *mackey;
26         __u32   mackeylen;
27 diff --git a/cryptodev_int.h b/cryptodev_int.h
28 index cb005d7..74c295a 100644
29 --- a/cryptodev_int.h
30 +++ b/cryptodev_int.h
31 @@ -164,6 +164,15 @@ struct kernel_crypt_op {
32         struct mm_struct *mm;
33  };
34  
35 +struct kernel_hash_op {
36 +       struct hash_op_data hash_op;
37 +
38 +       int digestsize;
39 +       uint8_t hash_output[AALG_MAX_RESULT_LEN];
40 +       struct task_struct *task;
41 +       struct mm_struct *mm;
42 +};
43 +
44  struct kernel_crypt_auth_op {
45         struct crypt_auth_op caop;
46  
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);
52  
53  #include <cryptlib.h>
54  
55 diff --git a/ioctl.c b/ioctl.c
56 index 3763954..a052614 100644
57 --- a/ioctl.c
58 +++ b/ioctl.c
59 @@ -397,7 +397,128 @@ session_error:
60         return ret;
61  }
62  
63 -/* Everything that needs to be done when removing a session. */
64 +static inline void hash_destroy_session(struct csession *ses_ptr)
65 +{
66 +       cryptodev_hash_deinit(&ses_ptr->hdata);
67 +       kfree(ses_ptr->pages);
68 +       kfree(ses_ptr->sg);
69 +       kfree(ses_ptr);
70 +}
71 +
72 +static int hash_create_session(struct hash_op_data *hash_op)
73 +{
74 +       struct csession *ses;
75 +       int ret = 0;
76 +       const char *hash_name;
77 +       int hmac_mode = 1;
78 +       uint8_t mkey[CRYPTO_HMAC_MAX_KEY_LEN];
79 +
80 +       switch (hash_op->mac_op) {
81 +       case CRYPTO_MD5_HMAC:
82 +               hash_name = "hmac(md5)";
83 +               break;
84 +       case CRYPTO_RIPEMD160_HMAC:
85 +               hash_name = "hmac(rmd160)";
86 +               break;
87 +       case CRYPTO_SHA1_HMAC:
88 +               hash_name = "hmac(sha1)";
89 +               break;
90 +       case CRYPTO_SHA2_224_HMAC:
91 +               hash_name = "hmac(sha224)";
92 +               break;
93 +       case CRYPTO_SHA2_256_HMAC:
94 +               hash_name = "hmac(sha256)";
95 +               break;
96 +       case CRYPTO_SHA2_384_HMAC:
97 +               hash_name = "hmac(sha384)";
98 +               break;
99 +       case CRYPTO_SHA2_512_HMAC:
100 +               hash_name = "hmac(sha512)";
101 +               break;
102 +       /* non-hmac cases */
103 +       case CRYPTO_MD5:
104 +               hash_name = "md5";
105 +               hmac_mode = 0;
106 +               break;
107 +       case CRYPTO_RIPEMD160:
108 +               hash_name = "rmd160";
109 +               hmac_mode = 0;
110 +               break;
111 +       case CRYPTO_SHA1:
112 +               hash_name = "sha1";
113 +               hmac_mode = 0;
114 +               break;
115 +       case CRYPTO_SHA2_224:
116 +               hash_name = "sha224";
117 +               hmac_mode = 0;
118 +               break;
119 +       case CRYPTO_SHA2_256:
120 +               hash_name = "sha256";
121 +               hmac_mode = 0;
122 +               break;
123 +       case CRYPTO_SHA2_384:
124 +               hash_name = "sha384";
125 +               hmac_mode = 0;
126 +               break;
127 +       case CRYPTO_SHA2_512:
128 +               hash_name = "sha512";
129 +               hmac_mode = 0;
130 +               break;
131 +       default:
132 +               ddebug(1, "bad mac: %d", hash_op->mac_op);
133 +               return -EINVAL;
134 +       }
135 +
136 +       ses = kzalloc(sizeof(*ses), GFP_KERNEL);
137 +       if (!ses) {
138 +               return -ENOMEM;
139 +       }
140 +
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);
144 +               ret = -EINVAL;
145 +               goto error_hash;
146 +       }
147 +
148 +       if (hash_op->mackey &&
149 +           unlikely(copy_from_user(mkey, hash_op->mackey, hash_op->mackeylen))) {
150 +               ret = -EFAULT;
151 +               goto error_hash;
152 +       }
153 +
154 +       ret = cryptodev_hash_init(&ses->hdata, hash_name, hmac_mode,
155 +                       mkey, hash_op->mackeylen);
156 +       if (ret != 0) {
157 +               ddebug(1, "Failed to load hash for %s", hash_name);
158 +               ret = -EINVAL;
159 +               goto error_hash;
160 +       }
161 +
162 +       ses->alignmask = ses->hdata.alignmask;
163 +       ddebug(2, "got alignmask %d", ses->alignmask);
164 +
165 +       ses->array_size = DEFAULT_PREALLOC_PAGES;
166 +       ddebug(2, "preallocating for %d user pages", ses->array_size);
167 +
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");
172 +               ret = -ENOMEM;
173 +               goto error_hash;
174 +       }
175 +
176 +       hash_op->ses = ses;
177 +       return 0;
178 +
179 +error_hash:
180 +       hash_destroy_session(ses);
181 +       return ret;
182 +}
183 +
184 +
185 +/* Everything that needs to be done when remowing a session. */
186  static inline void
187  crypto_destroy_session(struct csession *ses_ptr)
188  {
189 @@ -960,7 +1081,7 @@ cryptodev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg_)
190         void __user *arg = (void __user *)arg_;
191         int __user *p = 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_)
199  
200                 return kcop_to_user(&kcop, fcr, arg);
201         case CIOCHASH:
202 -               /* get session */
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");
206                         return -EFAULT;
207                 }
208 +               khop.task = current;
209 +               khop.mm = current->mm;
210  
211 -               sop.cipher = 0;
212 -               sop.mac = hash_op.mac_op;
213 -               sop.mackey = hash_op.mackey;
214 -               sop.mackeylen = hash_op.mackeylen;
215 -
216 -               /* writes sop.ses as a side-effect */
217 -               ret = crypto_create_session(fcr, &sop);
218 +               /* get session */
219 +               ret = hash_create_session(&khop.hash_op);
220                 if (unlikely(ret)) {
221                         pr_err("can't get session\n");
222                         return ret;
223                 }
224  
225                 /* do hashing */
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;
231 -               kcop.cop.dst = 0;
232 -               kcop.cop.op = 0;
233 -               kcop.cop.iv = 0;
234 -               kcop.ivlen = 0;
235 -               kcop.digestsize = 0; /* will be updated during operation */
236 -               kcop.task = current;
237 -               kcop.mm = current->mm;
238 -
239 -               ret = crypto_run(fcr, &kcop);
240 +               ret = hash_run(&khop);
241                 if (unlikely(ret)) {
242                         dwarning(1, "Error in hash run");
243                         return ret;
244                 }
245  
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);
248                 if (unlikely(ret)) {
249                         dwarning(1, "Error in copy to user");
250                         return ret;
251                 }
252  
253                 /* put session */
254 -               ret = crypto_finish_session(fcr, sop.ses);
255 +               hash_destroy_session(khop.hash_op.ses);
256                 return 0;
257         case CIOCAUTHCRYPT:
258                 if (unlikely(ret = kcaop_from_user(&kcaop, fcr, arg))) {
259 diff --git a/main.c b/main.c
260 index ec11129..095aea5 100644
261 --- a/main.c
262 +++ b/main.c
263 @@ -159,8 +159,6 @@ __crypto_run_std(struct csession *ses_ptr, struct crypt_op *cop)
264         return ret;
265  }
266  
267 -
268 -
269  /* This is the main crypto function - zero-copy edition */
270  static int
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);
274         return ret;
275  }
276 +
277 +int hash_run(struct kernel_hash_op *khop)
278 +{
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;
282 +       int ret;
283 +       struct scatterlist *src_sg;
284 +       struct scatterlist *dst_sg; /* required by get_userbuf but not used */
285 +
286 +       if (hash_op->len == 0) {
287 +               src_sg = NULL;
288 +       } else {
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");
293 +                       return ret;
294 +               }
295 +       }
296 +
297 +       ahash_request_set_crypt(hdata->async.request, src_sg, khop->hash_output, hash_op->len);
298 +
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;
303 +               if (ret != 0) {
304 +                       derr(0, "CryptoAPI failure: %d", ret);
305 +               }
306 +       }
307 +
308 +       khop->digestsize = ses_ptr->hdata.digestsize;
309 +
310 +       release_user_pages(ses_ptr);
311 +       return ret;
312 +}
313 -- 
314 2.7.0
315