unknown changes from android-tegra-nv-3.4
[linux-3.10.git] / drivers / misc / tegra-cryptodev.c
1 /*
2  * drivers/misc/tegra-cryptodev.c
3  *
4  * crypto dev node for NVIDIA tegra aes hardware
5  *
6  * Copyright (c) 2010, NVIDIA Corporation.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
16  * more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program; if not, write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21  */
22
23 #include <linux/module.h>
24 #include <linux/init.h>
25 #include <linux/errno.h>
26 #include <linux/kernel.h>
27 #include <linux/slab.h>
28 #include <linux/fs.h>
29 #include <linux/miscdevice.h>
30 #include <linux/crypto.h>
31 #include <linux/scatterlist.h>
32 #include <linux/uaccess.h>
33 #include <crypto/rng.h>
34 #include <crypto/hash.h>
35 #include <mach/hardware.h>
36
37 #include "tegra-cryptodev.h"
38
39 #define NBUFS 2
40 #define XBUFSIZE 8
41
42 struct tegra_crypto_ctx {
43         struct crypto_ablkcipher *ecb_tfm;
44         struct crypto_ablkcipher *cbc_tfm;
45         struct crypto_ablkcipher *ofb_tfm;
46         struct crypto_ablkcipher *ctr_tfm;
47         struct crypto_ablkcipher *cmac_tfm;
48         struct crypto_rng *rng;
49         u8 seed[TEGRA_CRYPTO_RNG_SEED_SIZE];
50         int use_ssk;
51 };
52
53 struct tegra_crypto_completion {
54         struct completion restart;
55         int req_err;
56 };
57
58 static int alloc_bufs(unsigned long *buf[NBUFS])
59 {
60         int i;
61
62         for (i = 0; i < NBUFS; i++) {
63                 buf[i] = (void *)__get_free_page(GFP_KERNEL);
64                 if (!buf[i])
65                         goto err_free_buf;
66         }
67
68         return 0;
69
70 err_free_buf:
71         while (i-- > 0)
72                 free_page((unsigned long)buf[i]);
73
74         return -ENOMEM;
75 }
76
77 static void free_bufs(unsigned long *buf[NBUFS])
78 {
79         int i;
80
81         for (i = 0; i < NBUFS; i++)
82                 free_page((unsigned long)buf[i]);
83 }
84
85 static int tegra_crypto_dev_open(struct inode *inode, struct file *filp)
86 {
87         struct tegra_crypto_ctx *ctx;
88         int ret = 0;
89
90         ctx = kzalloc(sizeof(struct tegra_crypto_ctx), GFP_KERNEL);
91         if (!ctx) {
92                 pr_err("no memory for context\n");
93                 return -ENOMEM;
94         }
95
96         ctx->ecb_tfm = crypto_alloc_ablkcipher("ecb-aes-tegra",
97                 CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, 0);
98         if (IS_ERR(ctx->ecb_tfm)) {
99                 pr_err("Failed to load transform for ecb-aes-tegra: %ld\n",
100                         PTR_ERR(ctx->ecb_tfm));
101                 ret = PTR_ERR(ctx->ecb_tfm);
102                 goto fail_ecb;
103         }
104
105         ctx->cbc_tfm = crypto_alloc_ablkcipher("cbc-aes-tegra",
106                 CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, 0);
107         if (IS_ERR(ctx->cbc_tfm)) {
108                 pr_err("Failed to load transform for cbc-aes-tegra: %ld\n",
109                         PTR_ERR(ctx->cbc_tfm));
110                 ret = PTR_ERR(ctx->cbc_tfm);
111                 goto fail_cbc;
112         }
113
114         if (tegra_get_chipid() != TEGRA_CHIPID_TEGRA2) {
115                 ctx->ofb_tfm = crypto_alloc_ablkcipher("ofb-aes-tegra",
116                         CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, 0);
117                 if (IS_ERR(ctx->ofb_tfm)) {
118                         pr_err("Failed to load transform for ofb-aes-tegra: %ld\n",
119                                 PTR_ERR(ctx->ofb_tfm));
120                         ret = PTR_ERR(ctx->ofb_tfm);
121                         goto fail_ofb;
122                 }
123
124                 ctx->ctr_tfm = crypto_alloc_ablkcipher("ctr-aes-tegra",
125                         CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, 0);
126                 if (IS_ERR(ctx->ctr_tfm)) {
127                         pr_err("Failed to load transform for ctr-aes-tegra: %ld\n",
128                                 PTR_ERR(ctx->ctr_tfm));
129                         ret = PTR_ERR(ctx->ctr_tfm);
130                         goto fail_ctr;
131                 }
132         }
133
134         ctx->rng = crypto_alloc_rng("rng-aes-tegra", CRYPTO_ALG_TYPE_RNG, 0);
135         if (IS_ERR(ctx->rng)) {
136                 pr_err("Failed to load transform for tegra rng: %ld\n",
137                         PTR_ERR(ctx->rng));
138                 ret = PTR_ERR(ctx->rng);
139                 goto fail_rng;
140         }
141
142         filp->private_data = ctx;
143         return ret;
144
145 fail_rng:
146         if (tegra_get_chipid() != TEGRA_CHIPID_TEGRA2)
147                 crypto_free_ablkcipher(ctx->ctr_tfm);
148 fail_ctr:
149         if (tegra_get_chipid() != TEGRA_CHIPID_TEGRA2)
150                 crypto_free_ablkcipher(ctx->ofb_tfm);
151 fail_ofb:
152         crypto_free_ablkcipher(ctx->cbc_tfm);
153
154 fail_cbc:
155         crypto_free_ablkcipher(ctx->ecb_tfm);
156
157 fail_ecb:
158         kfree(ctx);
159         return ret;
160 }
161
162 static int tegra_crypto_dev_release(struct inode *inode, struct file *filp)
163 {
164         struct tegra_crypto_ctx *ctx = filp->private_data;
165
166         crypto_free_ablkcipher(ctx->ecb_tfm);
167         crypto_free_ablkcipher(ctx->cbc_tfm);
168
169         if (tegra_get_chipid() != TEGRA_CHIPID_TEGRA2) {
170                 crypto_free_ablkcipher(ctx->ofb_tfm);
171                 crypto_free_ablkcipher(ctx->ctr_tfm);
172         }
173
174         crypto_free_rng(ctx->rng);
175         kfree(ctx);
176         filp->private_data = NULL;
177         return 0;
178 }
179
180 static void tegra_crypt_complete(struct crypto_async_request *req, int err)
181 {
182         struct tegra_crypto_completion *done = req->data;
183
184         if (err != -EINPROGRESS) {
185                 done->req_err = err;
186                 complete(&done->restart);
187         }
188 }
189
190 static int process_crypt_req(struct tegra_crypto_ctx *ctx, struct tegra_crypt_req *crypt_req)
191 {
192         struct crypto_ablkcipher *tfm;
193         struct ablkcipher_request *req = NULL;
194         struct scatterlist in_sg;
195         struct scatterlist out_sg;
196         unsigned long *xbuf[NBUFS];
197         int ret = 0, size = 0;
198         unsigned long total = 0;
199         const u8 *key = NULL;
200         struct tegra_crypto_completion tcrypt_complete;
201
202         if (crypt_req->op & TEGRA_CRYPTO_ECB) {
203                 req = ablkcipher_request_alloc(ctx->ecb_tfm, GFP_KERNEL);
204                 tfm = ctx->ecb_tfm;
205         } else if (crypt_req->op & TEGRA_CRYPTO_CBC) {
206                 req = ablkcipher_request_alloc(ctx->cbc_tfm, GFP_KERNEL);
207                 tfm = ctx->cbc_tfm;
208         } else if ((crypt_req->op & TEGRA_CRYPTO_OFB) &&
209                         (tegra_get_chipid() != TEGRA_CHIPID_TEGRA2)) {
210
211                 req = ablkcipher_request_alloc(ctx->ofb_tfm, GFP_KERNEL);
212                 tfm = ctx->ofb_tfm;
213         } else if ((crypt_req->op & TEGRA_CRYPTO_CTR) &&
214                         (tegra_get_chipid() != TEGRA_CHIPID_TEGRA2)) {
215
216                 req = ablkcipher_request_alloc(ctx->ctr_tfm, GFP_KERNEL);
217                 tfm = ctx->ctr_tfm;
218         }
219
220         if (!req) {
221                 pr_err("%s: Failed to allocate request\n", __func__);
222                 return -ENOMEM;
223         }
224
225         if ((crypt_req->keylen < 0) || (crypt_req->keylen > AES_MAX_KEY_SIZE))
226                 return -EINVAL;
227
228         crypto_ablkcipher_clear_flags(tfm, ~0);
229
230         if (!ctx->use_ssk)
231                 key = crypt_req->key;
232
233         ret = crypto_ablkcipher_setkey(tfm, key, crypt_req->keylen);
234         if (ret < 0) {
235                 pr_err("setkey failed");
236                 goto process_req_out;
237         }
238
239         ret = alloc_bufs(xbuf);
240         if (ret < 0) {
241                 pr_err("alloc_bufs failed");
242                 goto process_req_out;
243         }
244
245         init_completion(&tcrypt_complete.restart);
246
247         ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
248                 tegra_crypt_complete, &tcrypt_complete);
249
250         total = crypt_req->plaintext_sz;
251         while (total > 0) {
252                 size = min(total, PAGE_SIZE);
253                 ret = copy_from_user((void *)xbuf[0],
254                         (void __user *)crypt_req->plaintext, size);
255                 if (ret < 0) {
256                         pr_debug("%s: copy_from_user failed (%d)\n", __func__, ret);
257                         goto process_req_buf_out;
258                 }
259                 sg_init_one(&in_sg, xbuf[0], size);
260                 sg_init_one(&out_sg, xbuf[1], size);
261
262                 ablkcipher_request_set_crypt(req, &in_sg,
263                         &out_sg, size, crypt_req->iv);
264
265                 INIT_COMPLETION(tcrypt_complete.restart);
266                 tcrypt_complete.req_err = 0;
267                 ret = crypt_req->encrypt ?
268                         crypto_ablkcipher_encrypt(req) :
269                         crypto_ablkcipher_decrypt(req);
270
271                 if ((ret == -EINPROGRESS) || (ret == -EBUSY)) {
272                         /* crypto driver is asynchronous */
273                         ret = wait_for_completion_interruptible(&tcrypt_complete.restart);
274
275                         if (ret < 0)
276                                 goto process_req_buf_out;
277
278                         if (tcrypt_complete.req_err < 0) {
279                                 ret = tcrypt_complete.req_err;
280                                 goto process_req_buf_out;
281                         }
282                 } else if (ret < 0) {
283                         pr_debug("%scrypt failed (%d)\n",
284                                 crypt_req->encrypt ? "en" : "de", ret);
285                         goto process_req_buf_out;
286                 }
287
288                 ret = copy_to_user((void __user *)crypt_req->result,
289                         (const void *)xbuf[1], size);
290                 if (ret < 0)
291                         goto process_req_buf_out;
292
293                 total -= size;
294                 crypt_req->result += size;
295                 crypt_req->plaintext += size;
296         }
297
298 process_req_buf_out:
299         free_bufs(xbuf);
300 process_req_out:
301         ablkcipher_request_free(req);
302
303         return ret;
304 }
305
306 static int sha_async_hash_op(struct ahash_request *req,
307                                 struct tegra_crypto_completion *tr,
308                                 int ret)
309 {
310         if (ret == -EINPROGRESS || ret == -EBUSY) {
311                 ret = wait_for_completion_interruptible(&tr->restart);
312                 if (!ret)
313                         ret = tr->req_err;
314                 INIT_COMPLETION(tr->restart);
315         }
316         return ret;
317 }
318
319 static int tegra_crypto_sha(struct tegra_sha_req *sha_req)
320 {
321
322         struct crypto_ahash *tfm;
323         struct scatterlist sg[1];
324         char result[64];
325         struct ahash_request *req;
326         struct tegra_crypto_completion sha_complete;
327         void *hash_buff;
328         unsigned long *xbuf[XBUFSIZE];
329         int ret = -ENOMEM;
330
331         tfm = crypto_alloc_ahash(sha_req->algo, 0, 0);
332         if (IS_ERR(tfm)) {
333                 printk(KERN_ERR "alg: hash: Failed to load transform for %s: "
334                        "%ld\n", sha_req->algo, PTR_ERR(tfm));
335                 goto out_alloc;
336         }
337
338         req = ahash_request_alloc(tfm, GFP_KERNEL);
339         if (!req) {
340                 printk(KERN_ERR "alg: hash: Failed to allocate request for "
341                        "%s\n", sha_req->algo);
342                 goto out_noreq;
343         }
344
345         ret = alloc_bufs(xbuf);
346         if (ret < 0) {
347                 pr_err("alloc_bufs failed");
348                 goto out_buf;
349         }
350
351         init_completion(&sha_complete.restart);
352
353         memset(result, 0, 64);
354
355         hash_buff = xbuf[0];
356
357         memcpy(hash_buff, sha_req->plaintext, sha_req->plaintext_sz);
358         sg_init_one(&sg[0], hash_buff, sha_req->plaintext_sz);
359
360         if (sha_req->keylen) {
361                 crypto_ahash_clear_flags(tfm, ~0);
362                 ret = crypto_ahash_setkey(tfm, sha_req->key,
363                                           sha_req->keylen);
364                 if (ret) {
365                         printk(KERN_ERR "alg: hash: setkey failed on "
366                                " %s: ret=%d\n", sha_req->algo,
367                                -ret);
368                         goto out;
369                 }
370         }
371
372         ahash_request_set_crypt(req, sg, result, sha_req->plaintext_sz);
373
374         ret = sha_async_hash_op(req, &sha_complete, crypto_ahash_init(req));
375         if (ret) {
376                 pr_err("alg: hash: init failed on "
377                        "for %s: ret=%d\n", sha_req->algo, -ret);
378                 goto out;
379         }
380
381         ret = sha_async_hash_op(req, &sha_complete, crypto_ahash_update(req));
382         if (ret) {
383                 pr_err("alg: hash: update failed on "
384                        "for %s: ret=%d\n", sha_req->algo, -ret);
385                 goto out;
386         }
387
388         ret = sha_async_hash_op(req, &sha_complete, crypto_ahash_final(req));
389         if (ret) {
390                 pr_err("alg: hash: final failed on "
391                        "for %s: ret=%d\n", sha_req->algo, -ret);
392                 goto out;
393         }
394
395         ret = copy_to_user((void __user *)sha_req->result,
396                 (const void *)result, crypto_ahash_digestsize(tfm));
397         if (ret < 0)
398                 goto out;
399
400 out:
401         free_bufs(xbuf);
402
403 out_buf:
404         ahash_request_free(req);
405
406 out_noreq:
407         crypto_free_ahash(tfm);
408
409 out_alloc:
410         return ret;
411
412 }
413
414 static long tegra_crypto_dev_ioctl(struct file *filp,
415         unsigned int ioctl_num, unsigned long arg)
416 {
417         struct tegra_crypto_ctx *ctx = filp->private_data;
418         struct tegra_crypt_req crypt_req;
419         struct tegra_rng_req rng_req;
420         struct tegra_sha_req sha_req;
421         char *rng;
422         int ret = 0;
423
424         switch (ioctl_num) {
425         case TEGRA_CRYPTO_IOCTL_NEED_SSK:
426                 ctx->use_ssk = (int)arg;
427                 break;
428
429         case TEGRA_CRYPTO_IOCTL_PROCESS_REQ:
430                 ret = copy_from_user(&crypt_req, (void __user *)arg, sizeof(crypt_req));
431                 if (ret < 0) {
432                         pr_err("%s: copy_from_user fail(%d)\n", __func__, ret);
433                         break;
434                 }
435
436                 ret = process_crypt_req(ctx, &crypt_req);
437                 break;
438
439         case TEGRA_CRYPTO_IOCTL_SET_SEED:
440                 if (copy_from_user(&rng_req, (void __user *)arg, sizeof(rng_req)))
441                         return -EFAULT;
442
443                 memcpy(ctx->seed, rng_req.seed, TEGRA_CRYPTO_RNG_SEED_SIZE);
444
445                 ret = crypto_rng_reset(ctx->rng, ctx->seed,
446                         crypto_rng_seedsize(ctx->rng));
447                 break;
448
449         case TEGRA_CRYPTO_IOCTL_GET_RANDOM:
450                 if (copy_from_user(&rng_req, (void __user *)arg, sizeof(rng_req)))
451                         return -EFAULT;
452
453                 rng = kzalloc(rng_req.nbytes, GFP_KERNEL);
454                 if (!rng) {
455                         pr_err("mem alloc for rng fail");
456                         ret = -ENODATA;
457                         goto rng_out;
458                 }
459
460                 ret = crypto_rng_get_bytes(ctx->rng, rng,
461                         rng_req.nbytes);
462
463                 if (ret != rng_req.nbytes) {
464                         pr_err("rng failed");
465                         ret = -ENODATA;
466                         goto rng_out;
467                 }
468
469                 ret = copy_to_user((void __user *)rng_req.rdata,
470                         (const void *)rng, rng_req.nbytes);
471                 ret = (ret < 0) ? -ENODATA : 0;
472 rng_out:
473                 if (rng)
474                         kfree(rng);
475                 break;
476
477         case TEGRA_CRYPTO_IOCTL_GET_SHA:
478                 if (tegra_get_chipid() != TEGRA_CHIPID_TEGRA2) {
479                         if (copy_from_user(&sha_req, (void __user *)arg,
480                                 sizeof(sha_req)))
481                                 return -EFAULT;
482                         ret = tegra_crypto_sha(&sha_req);
483                 } else {
484                         ret = -EINVAL;
485                 }
486                 break;
487
488         default:
489                 pr_debug("invalid ioctl code(%d)", ioctl_num);
490                 ret = -EINVAL;
491         }
492
493         return ret;
494 }
495
496 struct file_operations tegra_crypto_fops = {
497         .owner = THIS_MODULE,
498         .open = tegra_crypto_dev_open,
499         .release = tegra_crypto_dev_release,
500         .unlocked_ioctl = tegra_crypto_dev_ioctl,
501 };
502
503 struct miscdevice tegra_crypto_device = {
504         .minor = MISC_DYNAMIC_MINOR,
505         .name = "tegra-crypto",
506         .fops = &tegra_crypto_fops,
507 };
508
509 static int __init tegra_crypto_dev_init(void)
510 {
511         return misc_register(&tegra_crypto_device);
512 }
513
514 late_initcall(tegra_crypto_dev_init);
515
516 MODULE_DESCRIPTION("Tegra AES hw device node.");
517 MODULE_AUTHOR("NVIDIA Corporation");
518 MODULE_LICENSE("GPLv2");