2ee3618cd795ac91cebc9ded796d5887312ba041
[openwrt.git] / target / linux / generic / files / crypto / ocf / cryptodev.c
1 /*      $OpenBSD: cryptodev.c,v 1.52 2002/06/19 07:22:46 deraadt Exp $  */
2
3 /*-
4  * Linux port done by David McCullough <david_mccullough@mcafee.com>
5  * Copyright (C) 2006-2010 David McCullough
6  * Copyright (C) 2004-2005 Intel Corporation.
7  * The license and original author are listed below.
8  *
9  * Copyright (c) 2001 Theo de Raadt
10  * Copyright (c) 2002-2006 Sam Leffler, Errno Consulting
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  *
16  * 1. Redistributions of source code must retain the above copyright
17  *   notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *   notice, this list of conditions and the following disclaimer in the
20  *   documentation and/or other materials provided with the distribution.
21  * 3. The name of the author may not be used to endorse or promote products
22  *   derived from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  *
35  * Effort sponsored in part by the Defense Advanced Research Projects
36  * Agency (DARPA) and Air Force Research Laboratory, Air Force
37  * Materiel Command, USAF, under agreement number F30602-01-2-0537.
38  *
39 __FBSDID("$FreeBSD: src/sys/opencrypto/cryptodev.c,v 1.34 2007/05/09 19:37:02 gnn Exp $");
40  */
41
42 #include <linux/version.h>
43 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38) && !defined(AUTOCONF_INCLUDED)
44 #include <linux/config.h>
45 #endif
46 #include <linux/types.h>
47 #include <linux/time.h>
48 #include <linux/delay.h>
49 #include <linux/list.h>
50 #include <linux/init.h>
51 #include <linux/sched.h>
52 #include <linux/unistd.h>
53 #include <linux/module.h>
54 #include <linux/wait.h>
55 #include <linux/slab.h>
56 #include <linux/fs.h>
57 #include <linux/dcache.h>
58 #include <linux/file.h>
59 #include <linux/mount.h>
60 #include <linux/miscdevice.h>
61 #include <asm/uaccess.h>
62
63 #include <cryptodev.h>
64 #include <uio.h>
65
66 extern asmlinkage long sys_dup(unsigned int fildes);
67
68 #define debug cryptodev_debug
69 int cryptodev_debug = 0;
70 module_param(cryptodev_debug, int, 0644);
71 MODULE_PARM_DESC(cryptodev_debug, "Enable cryptodev debug");
72
73 struct csession_info {
74         u_int16_t       blocksize;
75         u_int16_t       minkey, maxkey;
76
77         u_int16_t       keysize;
78         /* u_int16_t    hashsize;  */
79         u_int16_t       authsize;
80         u_int16_t       authkey;
81         /* u_int16_t    ctxsize; */
82 };
83
84 struct csession {
85         struct list_head        list;
86         u_int64_t       sid;
87         u_int32_t       ses;
88
89         wait_queue_head_t waitq;
90
91         u_int32_t       cipher;
92
93         u_int32_t       mac;
94
95         caddr_t         key;
96         int             keylen;
97         u_char          tmp_iv[EALG_MAX_BLOCK_LEN];
98
99         caddr_t         mackey;
100         int             mackeylen;
101
102         struct csession_info info;
103
104         struct iovec    iovec;
105         struct uio      uio;
106         int             error;
107 };
108
109 struct fcrypt {
110         struct list_head        csessions;
111         int             sesn;
112 };
113
114 static struct csession *csefind(struct fcrypt *, u_int);
115 static int csedelete(struct fcrypt *, struct csession *);
116 static struct csession *cseadd(struct fcrypt *, struct csession *);
117 static struct csession *csecreate(struct fcrypt *, u_int64_t,
118                 struct cryptoini *crie, struct cryptoini *cria, struct csession_info *);
119 static int csefree(struct csession *);
120
121 static  int cryptodev_op(struct csession *, struct crypt_op *);
122 static  int cryptodev_key(struct crypt_kop *);
123 static  int cryptodev_find(struct crypt_find_op *);
124
125 static int cryptodev_cb(void *);
126 static int cryptodev_open(struct inode *inode, struct file *filp);
127
128 /*
129  * Check a crypto identifier to see if it requested
130  * a valid crid and it's capabilities match.
131  */
132 static int
133 checkcrid(int crid)
134 {
135         int hid = crid & ~(CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_HARDWARE);
136         int typ = crid & (CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_HARDWARE);
137         int caps = 0;
138         
139         /* if the user hasn't selected a driver, then just call newsession */
140         if (hid == 0 && typ != 0)
141                 return 0;
142
143         caps = crypto_getcaps(hid);
144
145         /* didn't find anything with capabilities */
146         if (caps == 0) {
147                 dprintk("%s: hid=%x typ=%x not matched\n", __FUNCTION__, hid, typ);
148                 return EINVAL;
149         }
150         
151         /* the user didn't specify SW or HW, so the driver is ok */
152         if (typ == 0)
153                 return 0;
154
155         /* if the type specified didn't match */
156         if (typ != (caps & (CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_HARDWARE))) {
157                 dprintk("%s: hid=%x typ=%x caps=%x not matched\n", __FUNCTION__,
158                                 hid, typ, caps);
159                 return EINVAL;
160         }
161
162         return 0;
163 }
164
165 static int
166 cryptodev_op(struct csession *cse, struct crypt_op *cop)
167 {
168         struct cryptop *crp = NULL;
169         struct cryptodesc *crde = NULL, *crda = NULL;
170         int error = 0;
171
172         dprintk("%s()\n", __FUNCTION__);
173         if (cop->len > CRYPTO_MAX_DATA_LEN) {
174                 dprintk("%s: %d > %d\n", __FUNCTION__, cop->len, CRYPTO_MAX_DATA_LEN);
175                 return (E2BIG);
176         }
177
178         if (cse->info.blocksize && (cop->len % cse->info.blocksize) != 0) {
179                 dprintk("%s: blocksize=%d len=%d\n", __FUNCTION__, cse->info.blocksize,
180                                 cop->len);
181                 return (EINVAL);
182         }
183
184         cse->uio.uio_iov = &cse->iovec;
185         cse->uio.uio_iovcnt = 1;
186         cse->uio.uio_offset = 0;
187 #if 0
188         cse->uio.uio_resid = cop->len;
189         cse->uio.uio_segflg = UIO_SYSSPACE;
190         cse->uio.uio_rw = UIO_WRITE;
191         cse->uio.uio_td = td;
192 #endif
193         cse->uio.uio_iov[0].iov_len = cop->len;
194         if (cse->info.authsize)
195                 cse->uio.uio_iov[0].iov_len += cse->info.authsize;
196         cse->uio.uio_iov[0].iov_base = kmalloc(cse->uio.uio_iov[0].iov_len,
197                         GFP_KERNEL);
198
199         if (cse->uio.uio_iov[0].iov_base == NULL) {
200                 dprintk("%s: iov_base kmalloc(%d) failed\n", __FUNCTION__,
201                                 (int)cse->uio.uio_iov[0].iov_len);
202                 return (ENOMEM);
203         }
204
205         crp = crypto_getreq((cse->info.blocksize != 0) + (cse->info.authsize != 0));
206         if (crp == NULL) {
207                 dprintk("%s: ENOMEM\n", __FUNCTION__);
208                 error = ENOMEM;
209                 goto bail;
210         }
211
212         if (cse->info.authsize && cse->info.blocksize) {
213                 if (cop->op == COP_ENCRYPT) {
214                         crde = crp->crp_desc;
215                         crda = crde->crd_next;
216                 } else {
217                         crda = crp->crp_desc;
218                         crde = crda->crd_next;
219                 }
220         } else if (cse->info.authsize) {
221                 crda = crp->crp_desc;
222         } else if (cse->info.blocksize) {
223                 crde = crp->crp_desc;
224         } else {
225                 dprintk("%s: bad request\n", __FUNCTION__);
226                 error = EINVAL;
227                 goto bail;
228         }
229
230         if ((error = copy_from_user(cse->uio.uio_iov[0].iov_base, cop->src,
231                                         cop->len))) {
232                 dprintk("%s: bad copy\n", __FUNCTION__);
233                 goto bail;
234         }
235
236         if (crda) {
237                 crda->crd_skip = 0;
238                 crda->crd_len = cop->len;
239                 crda->crd_inject = cop->len;
240
241                 crda->crd_alg = cse->mac;
242                 crda->crd_key = cse->mackey;
243                 crda->crd_klen = cse->mackeylen * 8;
244         }
245
246         if (crde) {
247                 if (cop->op == COP_ENCRYPT)
248                         crde->crd_flags |= CRD_F_ENCRYPT;
249                 else
250                         crde->crd_flags &= ~CRD_F_ENCRYPT;
251                 crde->crd_len = cop->len;
252                 crde->crd_inject = 0;
253
254                 crde->crd_alg = cse->cipher;
255                 crde->crd_key = cse->key;
256                 crde->crd_klen = cse->keylen * 8;
257         }
258
259         crp->crp_ilen = cse->uio.uio_iov[0].iov_len;
260         crp->crp_flags = CRYPTO_F_IOV | CRYPTO_F_CBIMM
261                        | (cop->flags & COP_F_BATCH);
262         crp->crp_buf = (caddr_t)&cse->uio;
263         crp->crp_callback = (int (*) (struct cryptop *)) cryptodev_cb;
264         crp->crp_sid = cse->sid;
265         crp->crp_opaque = (void *)cse;
266
267         if (cop->iv) {
268                 if (crde == NULL) {
269                         error = EINVAL;
270                         dprintk("%s no crde\n", __FUNCTION__);
271                         goto bail;
272                 }
273                 if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
274                         error = EINVAL;
275                         dprintk("%s arc4 with IV\n", __FUNCTION__);
276                         goto bail;
277                 }
278                 if ((error = copy_from_user(cse->tmp_iv, cop->iv,
279                                                 cse->info.blocksize))) {
280                         dprintk("%s bad iv copy\n", __FUNCTION__);
281                         goto bail;
282                 }
283                 memcpy(crde->crd_iv, cse->tmp_iv, cse->info.blocksize);
284                 crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
285                 crde->crd_skip = 0;
286         } else if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
287                 crde->crd_skip = 0;
288         } else if (crde) {
289                 crde->crd_flags |= CRD_F_IV_PRESENT;
290                 crde->crd_skip = cse->info.blocksize;
291                 crde->crd_len -= cse->info.blocksize;
292         }
293
294         if (cop->mac && crda == NULL) {
295                 error = EINVAL;
296                 dprintk("%s no crda\n", __FUNCTION__);
297                 goto bail;
298         }
299
300         /*
301          * Let the dispatch run unlocked, then, interlock against the
302          * callback before checking if the operation completed and going
303          * to sleep.  This insures drivers don't inherit our lock which
304          * results in a lock order reversal between crypto_dispatch forced
305          * entry and the crypto_done callback into us.
306          */
307         error = crypto_dispatch(crp);
308         if (error) {
309                 dprintk("%s error in crypto_dispatch\n", __FUNCTION__);
310                 goto bail;
311         }
312
313         dprintk("%s about to WAIT\n", __FUNCTION__);
314         /*
315          * we really need to wait for driver to complete to maintain
316          * state,  luckily interrupts will be remembered
317          */
318         do {
319                 error = wait_event_interruptible(crp->crp_waitq,
320                                 ((crp->crp_flags & CRYPTO_F_DONE) != 0));
321                 /*
322                  * we can't break out of this loop or we will leave behind
323                  * a huge mess,  however,  staying here means if your driver
324                  * is broken user applications can hang and not be killed.
325                  * The solution,  fix your driver :-)
326                  */
327                 if (error) {
328                         schedule();
329                         error = 0;
330                 }
331         } while ((crp->crp_flags & CRYPTO_F_DONE) == 0);
332         dprintk("%s finished WAITING error=%d\n", __FUNCTION__, error);
333
334         if (crp->crp_etype != 0) {
335                 error = crp->crp_etype;
336                 dprintk("%s error in crp processing\n", __FUNCTION__);
337                 goto bail;
338         }
339
340         if (cse->error) {
341                 error = cse->error;
342                 dprintk("%s error in cse processing\n", __FUNCTION__);
343                 goto bail;
344         }
345
346         if (cop->dst && (error = copy_to_user(cop->dst,
347                                         cse->uio.uio_iov[0].iov_base, cop->len))) {
348                 dprintk("%s bad dst copy\n", __FUNCTION__);
349                 goto bail;
350         }
351
352         if (cop->mac &&
353                         (error=copy_to_user(cop->mac,
354                                 (caddr_t)cse->uio.uio_iov[0].iov_base + cop->len,
355                                 cse->info.authsize))) {
356                 dprintk("%s bad mac copy\n", __FUNCTION__);
357                 goto bail;
358         }
359
360 bail:
361         if (crp)
362                 crypto_freereq(crp);
363         if (cse->uio.uio_iov[0].iov_base)
364                 kfree(cse->uio.uio_iov[0].iov_base);
365
366         return (error);
367 }
368
369 static int
370 cryptodev_cb(void *op)
371 {
372         struct cryptop *crp = (struct cryptop *) op;
373         struct csession *cse = (struct csession *)crp->crp_opaque;
374         int error;
375
376         dprintk("%s()\n", __FUNCTION__);
377         error = crp->crp_etype;
378         if (error == EAGAIN) {
379                 crp->crp_flags &= ~CRYPTO_F_DONE;
380 #ifdef NOTYET
381                 /*
382                  * DAVIDM I am fairly sure that we should turn this into a batch
383                  * request to stop bad karma/lockup, revisit
384                  */
385                 crp->crp_flags |= CRYPTO_F_BATCH;
386 #endif
387                 return crypto_dispatch(crp);
388         }
389         if (error != 0 || (crp->crp_flags & CRYPTO_F_DONE)) {
390                 cse->error = error;
391                 wake_up_interruptible(&crp->crp_waitq);
392         }
393         return (0);
394 }
395
396 static int
397 cryptodevkey_cb(void *op)
398 {
399         struct cryptkop *krp = (struct cryptkop *) op;
400         dprintk("%s()\n", __FUNCTION__);
401         wake_up_interruptible(&krp->krp_waitq);
402         return (0);
403 }
404
405 static int
406 cryptodev_key(struct crypt_kop *kop)
407 {
408         struct cryptkop *krp = NULL;
409         int error = EINVAL;
410         int in, out, size, i;
411
412         dprintk("%s()\n", __FUNCTION__);
413         if (kop->crk_iparams + kop->crk_oparams > CRK_MAXPARAM) {
414                 dprintk("%s params too big\n", __FUNCTION__);
415                 return (EFBIG);
416         }
417
418         in = kop->crk_iparams;
419         out = kop->crk_oparams;
420         switch (kop->crk_op) {
421         case CRK_MOD_EXP:
422                 if (in == 3 && out == 1)
423                         break;
424                 return (EINVAL);
425         case CRK_MOD_EXP_CRT:
426                 if (in == 6 && out == 1)
427                         break;
428                 return (EINVAL);
429         case CRK_DSA_SIGN:
430                 if (in == 5 && out == 2)
431                         break;
432                 return (EINVAL);
433         case CRK_DSA_VERIFY:
434                 if (in == 7 && out == 0)
435                         break;
436                 return (EINVAL);
437         case CRK_DH_COMPUTE_KEY:
438                 if (in == 3 && out == 1)
439                         break;
440                 return (EINVAL);
441         default:
442                 return (EINVAL);
443         }
444
445         krp = (struct cryptkop *)kmalloc(sizeof *krp, GFP_KERNEL);
446         if (!krp)
447                 return (ENOMEM);
448         bzero(krp, sizeof *krp);
449         krp->krp_op = kop->crk_op;
450         krp->krp_status = kop->crk_status;
451         krp->krp_iparams = kop->crk_iparams;
452         krp->krp_oparams = kop->crk_oparams;
453         krp->krp_crid = kop->crk_crid;
454         krp->krp_status = 0;
455         krp->krp_flags = CRYPTO_KF_CBIMM;
456         krp->krp_callback = (int (*) (struct cryptkop *)) cryptodevkey_cb;
457         init_waitqueue_head(&krp->krp_waitq);
458
459         for (i = 0; i < CRK_MAXPARAM; i++)
460                 krp->krp_param[i].crp_nbits = kop->crk_param[i].crp_nbits;
461         for (i = 0; i < krp->krp_iparams + krp->krp_oparams; i++) {
462                 size = (krp->krp_param[i].crp_nbits + 7) / 8;
463                 if (size == 0)
464                         continue;
465                 krp->krp_param[i].crp_p = (caddr_t) kmalloc(size, GFP_KERNEL);
466                 if (i >= krp->krp_iparams)
467                         continue;
468                 error = copy_from_user(krp->krp_param[i].crp_p,
469                                 kop->crk_param[i].crp_p, size);
470                 if (error)
471                         goto fail;
472         }
473
474         error = crypto_kdispatch(krp);
475         if (error)
476                 goto fail;
477
478         do {
479                 error = wait_event_interruptible(krp->krp_waitq,
480                                 ((krp->krp_flags & CRYPTO_KF_DONE) != 0));
481                 /*
482                  * we can't break out of this loop or we will leave behind
483                  * a huge mess,  however,  staying here means if your driver
484                  * is broken user applications can hang and not be killed.
485                  * The solution,  fix your driver :-)
486                  */
487                 if (error) {
488                         schedule();
489                         error = 0;
490                 }
491         } while ((krp->krp_flags & CRYPTO_KF_DONE) == 0);
492
493         dprintk("%s finished WAITING error=%d\n", __FUNCTION__, error);
494         
495         kop->crk_crid = krp->krp_crid;          /* device that did the work */
496         if (krp->krp_status != 0) {
497                 error = krp->krp_status;
498                 goto fail;
499         }
500
501         for (i = krp->krp_iparams; i < krp->krp_iparams + krp->krp_oparams; i++) {
502                 size = (krp->krp_param[i].crp_nbits + 7) / 8;
503                 if (size == 0)
504                         continue;
505                 error = copy_to_user(kop->crk_param[i].crp_p, krp->krp_param[i].crp_p,
506                                 size);
507                 if (error)
508                         goto fail;
509         }
510
511 fail:
512         if (krp) {
513                 kop->crk_status = krp->krp_status;
514                 for (i = 0; i < CRK_MAXPARAM; i++) {
515                         if (krp->krp_param[i].crp_p)
516                                 kfree(krp->krp_param[i].crp_p);
517                 }
518                 kfree(krp);
519         }
520         return (error);
521 }
522
523 static int
524 cryptodev_find(struct crypt_find_op *find)
525 {
526         device_t dev;
527
528         if (find->crid != -1) {
529                 dev = crypto_find_device_byhid(find->crid);
530                 if (dev == NULL)
531                         return (ENOENT);
532                 strlcpy(find->name, device_get_nameunit(dev),
533                     sizeof(find->name));
534         } else {
535                 find->crid = crypto_find_driver(find->name);
536                 if (find->crid == -1)
537                         return (ENOENT);
538         }
539         return (0);
540 }
541
542 static struct csession *
543 csefind(struct fcrypt *fcr, u_int ses)
544 {
545         struct csession *cse;
546
547         dprintk("%s()\n", __FUNCTION__);
548         list_for_each_entry(cse, &fcr->csessions, list)
549                 if (cse->ses == ses)
550                         return (cse);
551         return (NULL);
552 }
553
554 static int
555 csedelete(struct fcrypt *fcr, struct csession *cse_del)
556 {
557         struct csession *cse;
558
559         dprintk("%s()\n", __FUNCTION__);
560         list_for_each_entry(cse, &fcr->csessions, list) {
561                 if (cse == cse_del) {
562                         list_del(&cse->list);
563                         return (1);
564                 }
565         }
566         return (0);
567 }
568         
569 static struct csession *
570 cseadd(struct fcrypt *fcr, struct csession *cse)
571 {
572         dprintk("%s()\n", __FUNCTION__);
573         list_add_tail(&cse->list, &fcr->csessions);
574         cse->ses = fcr->sesn++;
575         return (cse);
576 }
577
578 static struct csession *
579 csecreate(struct fcrypt *fcr, u_int64_t sid, struct cryptoini *crie,
580         struct cryptoini *cria, struct csession_info *info)
581 {
582         struct csession *cse;
583
584         dprintk("%s()\n", __FUNCTION__);
585         cse = (struct csession *) kmalloc(sizeof(struct csession), GFP_KERNEL);
586         if (cse == NULL)
587                 return NULL;
588         memset(cse, 0, sizeof(struct csession));
589
590         INIT_LIST_HEAD(&cse->list);
591         init_waitqueue_head(&cse->waitq);
592
593         cse->key = crie->cri_key;
594         cse->keylen = crie->cri_klen/8;
595         cse->mackey = cria->cri_key;
596         cse->mackeylen = cria->cri_klen/8;
597         cse->sid = sid;
598         cse->cipher = crie->cri_alg;
599         cse->mac = cria->cri_alg;
600         cse->info = *info;
601         cseadd(fcr, cse);
602         return (cse);
603 }
604
605 static int
606 csefree(struct csession *cse)
607 {
608         int error;
609
610         dprintk("%s()\n", __FUNCTION__);
611         error = crypto_freesession(cse->sid);
612         if (cse->key)
613                 kfree(cse->key);
614         if (cse->mackey)
615                 kfree(cse->mackey);
616         kfree(cse);
617         return(error);
618 }
619
620 static int
621 cryptodev_ioctl(
622         struct inode *inode,
623         struct file *filp,
624         unsigned int cmd,
625         unsigned long arg)
626 {
627         struct cryptoini cria, crie;
628         struct fcrypt *fcr = filp->private_data;
629         struct csession *cse;
630         struct csession_info info;
631         struct session2_op sop;
632         struct crypt_op cop;
633         struct crypt_kop kop;
634         struct crypt_find_op fop;
635         u_int64_t sid;
636         u_int32_t ses = 0;
637         int feat, fd, error = 0, crid;
638         mm_segment_t fs;
639
640         dprintk("%s(cmd=%x arg=%lx)\n", __FUNCTION__, cmd, arg);
641
642         switch (cmd) {
643
644         case CRIOGET: {
645                 dprintk("%s(CRIOGET)\n", __FUNCTION__);
646                 fs = get_fs();
647                 set_fs(get_ds());
648                 for (fd = 0; fd < files_fdtable(current->files)->max_fds; fd++)
649                         if (files_fdtable(current->files)->fd[fd] == filp)
650                                 break;
651                 fd = sys_dup(fd);
652                 set_fs(fs);
653                 put_user(fd, (int *) arg);
654                 return IS_ERR_VALUE(fd) ? fd : 0;
655                 }
656
657 #define CIOCGSESSSTR    (cmd == CIOCGSESSION ? "CIOCGSESSION" : "CIOCGSESSION2")
658         case CIOCGSESSION:
659         case CIOCGSESSION2:
660                 dprintk("%s(%s)\n", __FUNCTION__, CIOCGSESSSTR);
661                 memset(&crie, 0, sizeof(crie));
662                 memset(&cria, 0, sizeof(cria));
663                 memset(&info, 0, sizeof(info));
664                 memset(&sop, 0, sizeof(sop));
665
666                 if (copy_from_user(&sop, (void*)arg, (cmd == CIOCGSESSION) ?
667                                         sizeof(struct session_op) : sizeof(sop))) {
668                         dprintk("%s(%s) - bad copy\n", __FUNCTION__, CIOCGSESSSTR);
669                         error = EFAULT;
670                         goto bail;
671                 }
672
673                 switch (sop.cipher) {
674                 case 0:
675                         dprintk("%s(%s) - no cipher\n", __FUNCTION__, CIOCGSESSSTR);
676                         break;
677                 case CRYPTO_NULL_CBC:
678                         info.blocksize = NULL_BLOCK_LEN;
679                         info.minkey = NULL_MIN_KEY_LEN;
680                         info.maxkey = NULL_MAX_KEY_LEN;
681                         break;
682                 case CRYPTO_DES_CBC:
683                         info.blocksize = DES_BLOCK_LEN;
684                         info.minkey = DES_MIN_KEY_LEN;
685                         info.maxkey = DES_MAX_KEY_LEN;
686                         break;
687                 case CRYPTO_3DES_CBC:
688                         info.blocksize = DES3_BLOCK_LEN;
689                         info.minkey = DES3_MIN_KEY_LEN;
690                         info.maxkey = DES3_MAX_KEY_LEN;
691                         break;
692                 case CRYPTO_BLF_CBC:
693                         info.blocksize = BLOWFISH_BLOCK_LEN;
694                         info.minkey = BLOWFISH_MIN_KEY_LEN;
695                         info.maxkey = BLOWFISH_MAX_KEY_LEN;
696                         break;
697                 case CRYPTO_CAST_CBC:
698                         info.blocksize = CAST128_BLOCK_LEN;
699                         info.minkey = CAST128_MIN_KEY_LEN;
700                         info.maxkey = CAST128_MAX_KEY_LEN;
701                         break;
702                 case CRYPTO_SKIPJACK_CBC:
703                         info.blocksize = SKIPJACK_BLOCK_LEN;
704                         info.minkey = SKIPJACK_MIN_KEY_LEN;
705                         info.maxkey = SKIPJACK_MAX_KEY_LEN;
706                         break;
707                 case CRYPTO_AES_CBC:
708                         info.blocksize = AES_BLOCK_LEN;
709                         info.minkey = AES_MIN_KEY_LEN;
710                         info.maxkey = AES_MAX_KEY_LEN;
711                         break;
712                 case CRYPTO_ARC4:
713                         info.blocksize = ARC4_BLOCK_LEN;
714                         info.minkey = ARC4_MIN_KEY_LEN;
715                         info.maxkey = ARC4_MAX_KEY_LEN;
716                         break;
717                 case CRYPTO_CAMELLIA_CBC:
718                         info.blocksize = CAMELLIA_BLOCK_LEN;
719                         info.minkey = CAMELLIA_MIN_KEY_LEN;
720                         info.maxkey = CAMELLIA_MAX_KEY_LEN;
721                         break;
722                 default:
723                         dprintk("%s(%s) - bad cipher\n", __FUNCTION__, CIOCGSESSSTR);
724                         error = EINVAL;
725                         goto bail;
726                 }
727
728                 switch (sop.mac) {
729                 case 0:
730                         dprintk("%s(%s) - no mac\n", __FUNCTION__, CIOCGSESSSTR);
731                         break;
732                 case CRYPTO_NULL_HMAC:
733                         info.authsize = NULL_HASH_LEN;
734                         break;
735                 case CRYPTO_MD5:
736                         info.authsize = MD5_HASH_LEN;
737                         break;
738                 case CRYPTO_SHA1:
739                         info.authsize = SHA1_HASH_LEN;
740                         break;
741                 case CRYPTO_SHA2_256:
742                         info.authsize = SHA2_256_HASH_LEN;
743                         break;
744                 case CRYPTO_SHA2_384:
745                         info.authsize = SHA2_384_HASH_LEN;
746                         break;
747                 case CRYPTO_SHA2_512:
748                         info.authsize = SHA2_512_HASH_LEN;
749                         break;
750                 case CRYPTO_RIPEMD160:
751                         info.authsize = RIPEMD160_HASH_LEN;
752                         break;
753                 case CRYPTO_MD5_HMAC:
754                         info.authsize = MD5_HASH_LEN;
755                         info.authkey = 16;
756                         break;
757                 case CRYPTO_SHA1_HMAC:
758                         info.authsize = SHA1_HASH_LEN;
759                         info.authkey = 20;
760                         break;
761                 case CRYPTO_SHA2_256_HMAC:
762                         info.authsize = SHA2_256_HASH_LEN;
763                         info.authkey = 32;
764                         break;
765                 case CRYPTO_SHA2_384_HMAC:
766                         info.authsize = SHA2_384_HASH_LEN;
767                         info.authkey = 48;
768                         break;
769                 case CRYPTO_SHA2_512_HMAC:
770                         info.authsize = SHA2_512_HASH_LEN;
771                         info.authkey = 64;
772                         break;
773                 case CRYPTO_RIPEMD160_HMAC:
774                         info.authsize = RIPEMD160_HASH_LEN;
775                         info.authkey = 20;
776                         break;
777                 default:
778                         dprintk("%s(%s) - bad mac\n", __FUNCTION__, CIOCGSESSSTR);
779                         error = EINVAL;
780                         goto bail;
781                 }
782
783                 if (info.blocksize) {
784                         crie.cri_alg = sop.cipher;
785                         crie.cri_klen = sop.keylen * 8;
786                         if ((info.maxkey && sop.keylen > info.maxkey) ||
787                                         sop.keylen < info.minkey) {
788                                 dprintk("%s(%s) - bad key\n", __FUNCTION__, CIOCGSESSSTR);
789                                 error = EINVAL;
790                                 goto bail;
791                         }
792
793                         crie.cri_key = (u_int8_t *) kmalloc(crie.cri_klen/8+1, GFP_KERNEL);
794                         if (copy_from_user(crie.cri_key, sop.key,
795                                                         crie.cri_klen/8)) {
796                                 dprintk("%s(%s) - bad copy\n", __FUNCTION__, CIOCGSESSSTR);
797                                 error = EFAULT;
798                                 goto bail;
799                         }
800                         if (info.authsize)
801                                 crie.cri_next = &cria;
802                 }
803
804                 if (info.authsize) {
805                         cria.cri_alg = sop.mac;
806                         cria.cri_klen = sop.mackeylen * 8;
807                         if (info.authkey && sop.mackeylen != info.authkey) {
808                                 dprintk("%s(%s) - mackeylen %d != %d\n", __FUNCTION__,
809                                                 CIOCGSESSSTR, sop.mackeylen, info.authkey);
810                                 error = EINVAL;
811                                 goto bail;
812                         }
813
814                         if (cria.cri_klen) {
815                                 cria.cri_key = (u_int8_t *) kmalloc(cria.cri_klen/8,GFP_KERNEL);
816                                 if (copy_from_user(cria.cri_key, sop.mackey,
817                                                                 cria.cri_klen / 8)) {
818                                         dprintk("%s(%s) - bad copy\n", __FUNCTION__, CIOCGSESSSTR);
819                                         error = EFAULT;
820                                         goto bail;
821                                 }
822                         }
823                 }
824
825                 /* NB: CIOGSESSION2 has the crid */
826                 if (cmd == CIOCGSESSION2) {
827                         crid = sop.crid;
828                         error = checkcrid(crid);
829                         if (error) {
830                                 dprintk("%s(%s) - checkcrid %x\n", __FUNCTION__,
831                                                 CIOCGSESSSTR, error);
832                                 goto bail;
833                         }
834                 } else {
835                         /* allow either HW or SW to be used */
836                         crid = CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE;
837                 }
838                 error = crypto_newsession(&sid, (info.blocksize ? &crie : &cria), crid);
839                 if (error) {
840                         dprintk("%s(%s) - newsession %d\n",__FUNCTION__,CIOCGSESSSTR,error);
841                         goto bail;
842                 }
843
844                 cse = csecreate(fcr, sid, &crie, &cria, &info);
845                 if (cse == NULL) {
846                         crypto_freesession(sid);
847                         error = EINVAL;
848                         dprintk("%s(%s) - csecreate failed\n", __FUNCTION__, CIOCGSESSSTR);
849                         goto bail;
850                 }
851                 sop.ses = cse->ses;
852
853                 if (cmd == CIOCGSESSION2) {
854                         /* return hardware/driver id */
855                         sop.crid = CRYPTO_SESID2HID(cse->sid);
856                 }
857
858                 if (copy_to_user((void*)arg, &sop, (cmd == CIOCGSESSION) ?
859                                         sizeof(struct session_op) : sizeof(sop))) {
860                         dprintk("%s(%s) - bad copy\n", __FUNCTION__, CIOCGSESSSTR);
861                         error = EFAULT;
862                 }
863 bail:
864                 if (error) {
865                         dprintk("%s(%s) - bail %d\n", __FUNCTION__, CIOCGSESSSTR, error);
866                         if (crie.cri_key)
867                                 kfree(crie.cri_key);
868                         if (cria.cri_key)
869                                 kfree(cria.cri_key);
870                 }
871                 break;
872         case CIOCFSESSION:
873                 dprintk("%s(CIOCFSESSION)\n", __FUNCTION__);
874                 get_user(ses, (uint32_t*)arg);
875                 cse = csefind(fcr, ses);
876                 if (cse == NULL) {
877                         error = EINVAL;
878                         dprintk("%s(CIOCFSESSION) - Fail %d\n", __FUNCTION__, error);
879                         break;
880                 }
881                 csedelete(fcr, cse);
882                 error = csefree(cse);
883                 break;
884         case CIOCCRYPT:
885                 dprintk("%s(CIOCCRYPT)\n", __FUNCTION__);
886                 if(copy_from_user(&cop, (void*)arg, sizeof(cop))) {
887                         dprintk("%s(CIOCCRYPT) - bad copy\n", __FUNCTION__);
888                         error = EFAULT;
889                         goto bail;
890                 }
891                 cse = csefind(fcr, cop.ses);
892                 if (cse == NULL) {
893                         error = EINVAL;
894                         dprintk("%s(CIOCCRYPT) - Fail %d\n", __FUNCTION__, error);
895                         break;
896                 }
897                 error = cryptodev_op(cse, &cop);
898                 if(copy_to_user((void*)arg, &cop, sizeof(cop))) {
899                         dprintk("%s(CIOCCRYPT) - bad return copy\n", __FUNCTION__);
900                         error = EFAULT;
901                         goto bail;
902                 }
903                 break;
904         case CIOCKEY:
905         case CIOCKEY2:
906                 dprintk("%s(CIOCKEY)\n", __FUNCTION__);
907                 if (!crypto_userasymcrypto)
908                         return (EPERM);         /* XXX compat? */
909                 if(copy_from_user(&kop, (void*)arg, sizeof(kop))) {
910                         dprintk("%s(CIOCKEY) - bad copy\n", __FUNCTION__);
911                         error = EFAULT;
912                         goto bail;
913                 }
914                 if (cmd == CIOCKEY) {
915                         /* NB: crypto core enforces s/w driver use */
916                         kop.crk_crid =
917                             CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE;
918                 }
919                 error = cryptodev_key(&kop);
920                 if(copy_to_user((void*)arg, &kop, sizeof(kop))) {
921                         dprintk("%s(CIOCGKEY) - bad return copy\n", __FUNCTION__);
922                         error = EFAULT;
923                         goto bail;
924                 }
925                 break;
926         case CIOCASYMFEAT:
927                 dprintk("%s(CIOCASYMFEAT)\n", __FUNCTION__);
928                 if (!crypto_userasymcrypto) {
929                         /*
930                          * NB: if user asym crypto operations are
931                          * not permitted return "no algorithms"
932                          * so well-behaved applications will just
933                          * fallback to doing them in software.
934                          */
935                         feat = 0;
936                 } else
937                         error = crypto_getfeat(&feat);
938                 if (!error) {
939                   error = copy_to_user((void*)arg, &feat, sizeof(feat));
940                 }
941                 break;
942         case CIOCFINDDEV:
943                 if (copy_from_user(&fop, (void*)arg, sizeof(fop))) {
944                         dprintk("%s(CIOCFINDDEV) - bad copy\n", __FUNCTION__);
945                         error = EFAULT;
946                         goto bail;
947                 }
948                 error = cryptodev_find(&fop);
949                 if (copy_to_user((void*)arg, &fop, sizeof(fop))) {
950                         dprintk("%s(CIOCFINDDEV) - bad return copy\n", __FUNCTION__);
951                         error = EFAULT;
952                         goto bail;
953                 }
954                 break;
955         default:
956                 dprintk("%s(unknown ioctl 0x%x)\n", __FUNCTION__, cmd);
957                 error = EINVAL;
958                 break;
959         }
960         return(-error);
961 }
962
963 #ifdef HAVE_UNLOCKED_IOCTL
964 static long
965 cryptodev_unlocked_ioctl(
966         struct file *filp,
967         unsigned int cmd,
968         unsigned long arg)
969 {
970         return cryptodev_ioctl(NULL, filp, cmd, arg);
971 }
972 #endif
973
974 static int
975 cryptodev_open(struct inode *inode, struct file *filp)
976 {
977         struct fcrypt *fcr;
978
979         dprintk("%s()\n", __FUNCTION__);
980 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
981         /*
982          * on 2.6.35 private_data points to a miscdevice structure, we override
983          * it,  which is currently safe to do.
984          */
985         if (filp->private_data) {
986                 printk("cryptodev: Private data already exists - %p!\n", filp->private_data);
987                 return(-ENODEV);
988         }
989 #endif
990
991         fcr = kmalloc(sizeof(*fcr), GFP_KERNEL);
992         if (!fcr) {
993                 dprintk("%s() - malloc failed\n", __FUNCTION__);
994                 return(-ENOMEM);
995         }
996         memset(fcr, 0, sizeof(*fcr));
997
998         INIT_LIST_HEAD(&fcr->csessions);
999         filp->private_data = fcr;
1000         return(0);
1001 }
1002
1003 static int
1004 cryptodev_release(struct inode *inode, struct file *filp)
1005 {
1006         struct fcrypt *fcr = filp->private_data;
1007         struct csession *cse, *tmp;
1008
1009         dprintk("%s()\n", __FUNCTION__);
1010         if (!filp) {
1011                 printk("cryptodev: No private data on release\n");
1012                 return(0);
1013         }
1014
1015         list_for_each_entry_safe(cse, tmp, &fcr->csessions, list) {
1016                 list_del(&cse->list);
1017                 (void)csefree(cse);
1018         }
1019         filp->private_data = NULL;
1020         kfree(fcr);
1021         return(0);
1022 }
1023
1024 static struct file_operations cryptodev_fops = {
1025         .owner = THIS_MODULE,
1026         .open = cryptodev_open,
1027         .release = cryptodev_release,
1028 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
1029         .ioctl = cryptodev_ioctl,
1030 #endif
1031 #ifdef HAVE_UNLOCKED_IOCTL
1032         .unlocked_ioctl = cryptodev_unlocked_ioctl,
1033 #endif
1034 };
1035
1036 static struct miscdevice cryptodev = {
1037         .minor = CRYPTODEV_MINOR,
1038         .name = "crypto",
1039         .fops = &cryptodev_fops,
1040 };
1041
1042 static int __init
1043 cryptodev_init(void)
1044 {
1045         int rc;
1046
1047         dprintk("%s(%p)\n", __FUNCTION__, cryptodev_init);
1048         rc = misc_register(&cryptodev);
1049         if (rc) {
1050                 printk(KERN_ERR "cryptodev: registration of /dev/crypto failed\n");
1051                 return(rc);
1052         }
1053
1054         return(0);
1055 }
1056
1057 static void __exit
1058 cryptodev_exit(void)
1059 {
1060         dprintk("%s()\n", __FUNCTION__);
1061         misc_deregister(&cryptodev);
1062 }
1063
1064 module_init(cryptodev_init);
1065 module_exit(cryptodev_exit);
1066
1067 MODULE_LICENSE("BSD");
1068 MODULE_AUTHOR("David McCullough <david_mccullough@mcafee.com>");
1069 MODULE_DESCRIPTION("Cryptodev (user interface to OCF)");