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