1 /* $FreeBSD: src/sys/opencrypto/cryptodev.c,v 1.41 2009/09/04 09:48:18 pjd Exp $ */
2 /* $OpenBSD: cryptodev.c,v 1.52 2002/06/19 07:22:46 deraadt Exp $ */
5 * Copyright (c) 2001 Theo de Raadt
6 * Copyright (c) 2002-2006 Sam Leffler, Errno Consulting
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 * Effort sponsored in part by the Defense Advanced Research Projects
32 * Agency (DARPA) and Air Force Research Laboratory, Air Force
33 * Materiel Command, USAF, under agreement number F30602-01-2-0537.
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/malloc.h>
39 #include <sys/device.h>
42 #include <sys/sysctl.h>
44 #include <sys/filedesc.h>
45 #include <sys/errno.h>
47 #include <sys/random.h>
49 #include <sys/module.h>
50 #include <sys/kernel.h>
51 #include <sys/fcntl.h>
54 #include <sys/file2.h>
55 #include <sys/thread2.h>
56 #include <sys/mplock2.h>
58 #include <opencrypto/cryptodev.h>
59 #include <opencrypto/xform.h>
62 TAILQ_ENTRY(csession
) next
;
68 struct enc_xform
*txform
;
70 struct auth_hash
*thash
;
74 u_char tmp_iv
[EALG_MAX_BLOCK_LEN
];
85 TAILQ_HEAD(csessionlist
, csession
) csessions
;
89 static int cryptof_rw(struct file
*fp
, struct uio
*uio
,
90 struct ucred
*cred
, int flags
);
91 static int cryptof_ioctl(struct file
*, u_long
, caddr_t
,
92 struct ucred
*, struct sysmsg
*);
93 static int cryptof_poll(struct file
*, int, struct ucred
*);
94 static int cryptof_kqfilter(struct file
*, struct knote
*);
95 static int cryptof_stat(struct file
*, struct stat
*, struct ucred
*);
96 static int cryptof_close(struct file
*);
98 static struct fileops cryptofops
= {
99 .fo_read
= cryptof_rw
,
100 .fo_write
= cryptof_rw
,
101 .fo_ioctl
= cryptof_ioctl
,
102 .fo_poll
= cryptof_poll
,
103 .fo_kqfilter
= cryptof_kqfilter
,
104 .fo_stat
= cryptof_stat
,
105 .fo_close
= cryptof_close
,
106 .fo_shutdown
= nofo_shutdown
109 static struct csession
*csefind(struct fcrypt
*, u_int
);
110 static int csedelete(struct fcrypt
*, struct csession
*);
111 static struct csession
*cseadd(struct fcrypt
*, struct csession
*);
112 static struct csession
*csecreate(struct fcrypt
*, u_int64_t
, caddr_t
,
113 u_int64_t
, caddr_t
, u_int64_t
, u_int32_t
, u_int32_t
, struct enc_xform
*,
115 static int csefree(struct csession
*);
117 static int cryptodev_op(struct csession
*, struct crypt_op
*, struct ucred
*);
118 static int cryptodev_key(struct crypt_kop
*);
119 static int cryptodev_find(struct crypt_find_op
*);
125 struct ucred
*active_cred
,
132 * Check a crypto identifier to see if it requested
133 * a software device/driver. This can be done either
134 * by device name/class or through search constraints.
137 checkforsoftware(int crid
)
139 if (crid
& CRYPTOCAP_F_SOFTWARE
)
140 return EINVAL
; /* XXX */
141 if ((crid
& CRYPTOCAP_F_HARDWARE
) == 0 &&
142 (crypto_getcaps(crid
) & CRYPTOCAP_F_HARDWARE
) == 0)
143 return EINVAL
; /* XXX */
149 cryptof_ioctl(struct file
*fp
, u_long cmd
, caddr_t data
,
150 struct ucred
*cred
, struct sysmsg
*msg
)
152 #define SES2(p) ((struct session2_op *)p)
153 struct cryptoini cria
, crie
;
154 struct fcrypt
*fcr
= fp
->f_data
;
155 struct csession
*cse
;
156 struct session_op
*sop
;
157 struct crypt_op
*cop
;
158 struct enc_xform
*txform
= NULL
;
159 struct auth_hash
*thash
= NULL
;
160 struct crypt_kop
*kop
;
168 sop
= (struct session_op
*)data
;
169 switch (sop
->cipher
) {
173 txform
= &enc_xform_des
;
175 case CRYPTO_3DES_CBC
:
176 txform
= &enc_xform_3des
;
179 txform
= &enc_xform_blf
;
181 case CRYPTO_CAST_CBC
:
182 txform
= &enc_xform_cast5
;
184 case CRYPTO_SKIPJACK_CBC
:
185 txform
= &enc_xform_skipjack
;
188 txform
= &enc_xform_rijndael128
;
190 case CRYPTO_NULL_CBC
:
191 txform
= &enc_xform_null
;
194 txform
= &enc_xform_arc4
;
196 case CRYPTO_CAMELLIA_CBC
:
197 txform
= &enc_xform_camellia
;
206 case CRYPTO_MD5_HMAC
:
207 thash
= &auth_hash_hmac_md5
;
209 case CRYPTO_SHA1_HMAC
:
210 thash
= &auth_hash_hmac_sha1
;
212 case CRYPTO_SHA2_256_HMAC
:
213 thash
= &auth_hash_hmac_sha2_256
;
215 case CRYPTO_SHA2_384_HMAC
:
216 thash
= &auth_hash_hmac_sha2_384
;
218 case CRYPTO_SHA2_512_HMAC
:
219 thash
= &auth_hash_hmac_sha2_512
;
221 case CRYPTO_RIPEMD160_HMAC
:
222 thash
= &auth_hash_hmac_ripemd_160
;
226 thash
= &auth_hash_md5
;
229 thash
= &auth_hash_sha1
;
232 case CRYPTO_NULL_HMAC
:
233 thash
= &auth_hash_null
;
239 bzero(&crie
, sizeof(crie
));
240 bzero(&cria
, sizeof(cria
));
243 crie
.cri_alg
= txform
->type
;
244 crie
.cri_klen
= sop
->keylen
* 8;
245 if (sop
->keylen
> txform
->maxkey
||
246 sop
->keylen
< txform
->minkey
) {
251 crie
.cri_key
= kmalloc(crie
.cri_klen
/ 8,
253 if ((error
= copyin(sop
->key
, crie
.cri_key
,
257 crie
.cri_next
= &cria
;
261 cria
.cri_alg
= thash
->type
;
262 cria
.cri_klen
= sop
->mackeylen
* 8;
263 if (sop
->mackeylen
!= thash
->keysize
) {
269 cria
.cri_key
= kmalloc(cria
.cri_klen
/ 8,
271 if ((error
= copyin(sop
->mackey
, cria
.cri_key
,
277 /* NB: CIOGSESSION2 has the crid */
278 if (cmd
== CIOCGSESSION2
) {
279 crid
= SES2(sop
)->crid
;
280 error
= checkforsoftware(crid
);
284 crid
= CRYPTOCAP_F_HARDWARE
;
285 error
= crypto_newsession(&sid
, (txform
? &crie
: &cria
), crid
);
289 cse
= csecreate(fcr
, sid
, crie
.cri_key
, crie
.cri_klen
,
290 cria
.cri_key
, cria
.cri_klen
, sop
->cipher
, sop
->mac
, txform
,
294 crypto_freesession(sid
);
299 if (cmd
== CIOCGSESSION2
) {
300 /* return hardware/driver id */
301 SES2(sop
)->crid
= CRYPTO_SESID2HID(cse
->sid
);
306 kfree(crie
.cri_key
, M_XDATA
);
308 kfree(cria
.cri_key
, M_XDATA
);
312 ses
= *(u_int32_t
*)data
;
313 cse
= csefind(fcr
, ses
);
317 error
= csefree(cse
);
320 cop
= (struct crypt_op
*)data
;
321 cse
= csefind(fcr
, cop
->ses
);
324 error
= cryptodev_op(cse
, cop
, cred
);
328 if (!crypto_userasymcrypto
)
329 return (EPERM
); /* XXX compat? */
331 kop
= (struct crypt_kop
*)data
;
332 if (cmd
== CIOCKEY
) {
333 /* NB: crypto core enforces s/w driver use */
335 CRYPTOCAP_F_HARDWARE
| CRYPTOCAP_F_SOFTWARE
;
337 error
= cryptodev_key(kop
);
341 if (!crypto_userasymcrypto
) {
343 * NB: if user asym crypto operations are
344 * not permitted return "no algorithms"
345 * so well-behaved applications will just
346 * fallback to doing them in software.
350 error
= crypto_getfeat((int *)data
);
353 error
= cryptodev_find((struct crypt_find_op
*)data
);
363 static int cryptodev_cb(void *);
367 cryptodev_op(struct csession
*cse
, struct crypt_op
*cop
,
368 struct ucred
*active_cred
)
370 struct cryptop
*crp
= NULL
;
371 struct cryptodesc
*crde
= NULL
, *crda
= NULL
;
374 if (cop
->len
> 256*1024-4)
378 if (cop
->len
== 0 || (cop
->len
% cse
->txform
->blocksize
) != 0)
382 bzero(&cse
->uio
, sizeof(cse
->uio
));
383 cse
->uio
.uio_iov
= &cse
->iovec
;
384 cse
->uio
.uio_iovcnt
= 1;
385 cse
->uio
.uio_offset
= 0;
386 cse
->uio
.uio_resid
= cop
->len
;
387 cse
->uio
.uio_segflg
= UIO_SYSSPACE
;
388 cse
->uio
.uio_rw
= UIO_WRITE
;
389 /* XXX: not sure, was td, now curthread? */
390 cse
->uio
.uio_td
= curthread
;
391 cse
->uio
.uio_iov
[0].iov_len
= cop
->len
;
393 cse
->uio
.uio_iov
[0].iov_len
+= cse
->thash
->hashsize
;
394 cse
->uio
.uio_resid
+= cse
->thash
->hashsize
;
396 cse
->uio
.uio_iov
[0].iov_base
= kmalloc(cse
->uio
.uio_iov
[0].iov_len
,
399 crp
= crypto_getreq((cse
->txform
!= NULL
) + (cse
->thash
!= NULL
));
406 crda
= crp
->crp_desc
;
408 crde
= crda
->crd_next
;
411 crde
= crp
->crp_desc
;
418 if ((error
= copyin(cop
->src
, cse
->uio
.uio_iov
[0].iov_base
, cop
->len
)))
423 crda
->crd_len
= cop
->len
;
424 crda
->crd_inject
= cop
->len
;
426 crda
->crd_alg
= cse
->mac
;
427 crda
->crd_key
= cse
->mackey
;
428 crda
->crd_klen
= cse
->mackeylen
* 8;
432 if (cop
->op
== COP_ENCRYPT
)
433 crde
->crd_flags
|= CRD_F_ENCRYPT
;
435 crde
->crd_flags
&= ~CRD_F_ENCRYPT
;
436 crde
->crd_len
= cop
->len
;
437 crde
->crd_inject
= 0;
439 crde
->crd_alg
= cse
->cipher
;
440 crde
->crd_key
= cse
->key
;
441 crde
->crd_klen
= cse
->keylen
* 8;
444 crp
->crp_ilen
= cop
->len
;
445 crp
->crp_flags
= CRYPTO_F_IOV
| CRYPTO_F_CBIMM
446 | (cop
->flags
& COP_F_BATCH
);
447 crp
->crp_buf
= (caddr_t
)&cse
->uio
;
448 crp
->crp_callback
= (int (*) (struct cryptop
*)) cryptodev_cb
;
449 crp
->crp_sid
= cse
->sid
;
450 crp
->crp_opaque
= (void *)cse
;
457 if (cse
->cipher
== CRYPTO_ARC4
) { /* XXX use flag? */
461 if ((error
= copyin(cop
->iv
, cse
->tmp_iv
, cse
->txform
->blocksize
)))
463 bcopy(cse
->tmp_iv
, crde
->crd_iv
, cse
->txform
->blocksize
);
464 crde
->crd_flags
|= CRD_F_IV_EXPLICIT
| CRD_F_IV_PRESENT
;
466 } else if (cse
->cipher
== CRYPTO_ARC4
) { /* XXX use flag? */
469 crde
->crd_flags
|= CRD_F_IV_PRESENT
;
470 crde
->crd_skip
= cse
->txform
->blocksize
;
471 crde
->crd_len
-= cse
->txform
->blocksize
;
474 if (cop
->mac
&& crda
== NULL
) {
481 * Let the dispatch run unlocked, then, interlock against the
482 * callback before checking if the operation completed and going
483 * to sleep. This insures drivers don't inherit our lock which
484 * results in a lock order reversal between crypto_dispatch forced
485 * entry and the crypto_done callback into us.
487 error
= crypto_dispatch(crp
);
488 lockmgr(&cse
->lock
, LK_EXCLUSIVE
);
489 if (error
== 0 && (crp
->crp_flags
& CRYPTO_F_DONE
) == 0)
490 error
= lksleep(crp
, &cse
->lock
, 0, "crydev", 0);
491 lockmgr(&cse
->lock
, LK_RELEASE
);
496 if (crp
->crp_etype
== EAGAIN
) {
498 crp
->crp_flags
&= ~CRYPTO_F_DONE
;
502 if (crp
->crp_etype
!= 0) {
503 error
= crp
->crp_etype
;
513 (error
= copyout(cse
->uio
.uio_iov
[0].iov_base
, cop
->dst
, cop
->len
)))
517 (error
= copyout((caddr_t
)cse
->uio
.uio_iov
[0].iov_base
+ cop
->len
,
518 cop
->mac
, cse
->thash
->hashsize
)))
524 if (cse
->uio
.uio_iov
[0].iov_base
)
525 kfree(cse
->uio
.uio_iov
[0].iov_base
, M_XDATA
);
531 cryptodev_cb(void *op
)
533 struct cryptop
*crp
= (struct cryptop
*) op
;
534 struct csession
*cse
= (struct csession
*)crp
->crp_opaque
;
536 lockmgr(&cse
->lock
, LK_EXCLUSIVE
);
537 cse
->error
= crp
->crp_etype
;
539 lockmgr(&cse
->lock
, LK_RELEASE
);
544 cryptodevkey_cb(void *op
)
546 struct cryptkop
*krp
= (struct cryptkop
*) op
;
553 cryptodev_key(struct crypt_kop
*kop
)
555 struct cryptkop
*krp
= NULL
;
557 int in
, out
, size
, i
;
559 if (kop
->crk_iparams
+ kop
->crk_oparams
> CRK_MAXPARAM
) {
563 in
= kop
->crk_iparams
;
564 out
= kop
->crk_oparams
;
565 switch (kop
->crk_op
) {
567 if (in
== 3 && out
== 1)
570 case CRK_MOD_EXP_CRT
:
571 if (in
== 6 && out
== 1)
575 if (in
== 5 && out
== 2)
579 if (in
== 7 && out
== 0)
582 case CRK_DH_COMPUTE_KEY
:
583 if (in
== 3 && out
== 1)
590 krp
= (struct cryptkop
*)kmalloc(sizeof *krp
, M_XDATA
, M_WAITOK
| M_ZERO
);
591 krp
->krp_op
= kop
->crk_op
;
592 krp
->krp_status
= kop
->crk_status
;
593 krp
->krp_iparams
= kop
->crk_iparams
;
594 krp
->krp_oparams
= kop
->crk_oparams
;
595 krp
->krp_crid
= kop
->crk_crid
;
597 krp
->krp_callback
= (int (*) (struct cryptkop
*)) cryptodevkey_cb
;
599 for (i
= 0; i
< CRK_MAXPARAM
; i
++) {
600 if (kop
->crk_param
[i
].crp_nbits
> 65536)
601 /* Limit is the same as in OpenBSD */
603 krp
->krp_param
[i
].crp_nbits
= kop
->crk_param
[i
].crp_nbits
;
605 for (i
= 0; i
< krp
->krp_iparams
+ krp
->krp_oparams
; i
++) {
606 size
= (krp
->krp_param
[i
].crp_nbits
+ 7) / 8;
609 krp
->krp_param
[i
].crp_p
= kmalloc(size
, M_XDATA
, M_WAITOK
);
610 if (i
>= krp
->krp_iparams
)
612 error
= copyin(kop
->crk_param
[i
].crp_p
, krp
->krp_param
[i
].crp_p
, size
);
617 error
= crypto_kdispatch(krp
);
620 error
= tsleep(krp
, 0, "crydev", 0);
622 /* XXX can this happen? if so, how do we recover? */
626 kop
->crk_crid
= krp
->krp_crid
; /* device that did the work */
627 if (krp
->krp_status
!= 0) {
628 error
= krp
->krp_status
;
632 for (i
= krp
->krp_iparams
; i
< krp
->krp_iparams
+ krp
->krp_oparams
; i
++) {
633 size
= (krp
->krp_param
[i
].crp_nbits
+ 7) / 8;
636 error
= copyout(krp
->krp_param
[i
].crp_p
, kop
->crk_param
[i
].crp_p
, size
);
643 kop
->crk_status
= krp
->krp_status
;
644 for (i
= 0; i
< CRK_MAXPARAM
; i
++) {
645 if (krp
->krp_param
[i
].crp_p
)
646 kfree(krp
->krp_param
[i
].crp_p
, M_XDATA
);
654 cryptodev_find(struct crypt_find_op
*find
)
658 if (find
->crid
!= -1) {
659 dev
= crypto_find_device_byhid(find
->crid
);
662 strlcpy(find
->name
, device_get_nameunit(dev
),
665 find
->crid
= crypto_find_driver(find
->name
);
666 if (find
->crid
== -1)
676 cryptof_poll(struct file
*fp
, int events
, struct ucred
*active_cred
)
685 cryptof_kqfilter(struct file
*fp
, struct knote
*kn
)
695 cryptof_stat(struct file
*fp
, struct stat
*sb
, struct ucred
*cred
)
701 * MPALMOSTSAFE - acquires mplock
704 cryptof_close(struct file
*fp
)
706 struct fcrypt
*fcr
= fp
->f_data
;
707 struct csession
*cse
;
710 fcr
= (struct fcrypt
*)fp
->f_data
;
711 while ((cse
= TAILQ_FIRST(&fcr
->csessions
))) {
712 TAILQ_REMOVE(&fcr
->csessions
, cse
, next
);
722 static struct csession
*
723 csefind(struct fcrypt
*fcr
, u_int ses
)
725 struct csession
*cse
;
727 TAILQ_FOREACH(cse
, &fcr
->csessions
, next
)
734 csedelete(struct fcrypt
*fcr
, struct csession
*cse_del
)
736 struct csession
*cse
;
738 TAILQ_FOREACH(cse
, &fcr
->csessions
, next
) {
739 if (cse
== cse_del
) {
740 TAILQ_REMOVE(&fcr
->csessions
, cse
, next
);
747 static struct csession
*
748 cseadd(struct fcrypt
*fcr
, struct csession
*cse
)
750 TAILQ_INSERT_TAIL(&fcr
->csessions
, cse
, next
);
751 cse
->ses
= fcr
->sesn
++;
756 csecreate(struct fcrypt
*fcr
, u_int64_t sid
, caddr_t key
, u_int64_t keylen
,
757 caddr_t mackey
, u_int64_t mackeylen
, u_int32_t cipher
, u_int32_t mac
,
758 struct enc_xform
*txform
, struct auth_hash
*thash
)
760 struct csession
*cse
;
762 cse
= kmalloc(sizeof(struct csession
), M_XDATA
, M_NOWAIT
);
765 lockinit(&cse
->lock
, "cryptodev", 0, LK_CANRECURSE
);
767 cse
->keylen
= keylen
/8;
768 cse
->mackey
= mackey
;
769 cse
->mackeylen
= mackeylen
/8;
771 cse
->cipher
= cipher
;
773 cse
->txform
= txform
;
780 csefree(struct csession
*cse
)
784 error
= crypto_freesession(cse
->sid
);
785 lockuninit(&cse
->lock
);
787 kfree(cse
->key
, M_XDATA
);
789 kfree(cse
->mackey
, M_XDATA
);
795 cryptoopen(struct dev_open_args
*ap
)
801 cryptoread(struct dev_read_args
*ap
)
807 cryptowrite(struct dev_write_args
*ap
)
813 cryptoioctl(struct dev_ioctl_args
*ap
)
815 struct thread
*td
= curthread
;
822 fcr
= kmalloc(sizeof(struct fcrypt
), M_XDATA
, M_WAITOK
);
823 TAILQ_INIT(&fcr
->csessions
);
826 KKASSERT(td
->td_lwp
);
827 error
= falloc(td
->td_lwp
, &f
, &fd
);
833 /* falloc automatically provides an extra reference to 'f'. */
834 f
->f_flag
= FREAD
| FWRITE
;
835 f
->f_type
= DTYPE_CRYPTO
;
836 f
->f_ops
= &cryptofops
;
838 fsetfd(td
->td_proc
->p_fd
, f
, fd
);
839 *(u_int32_t
*)ap
->a_data
= fd
;
844 error
= cryptodev_find((struct crypt_find_op
*)ap
->a_data
);
847 error
= crypto_getfeat((int *)ap
->a_data
);
856 static struct dev_ops crypto_ops
= {
858 .d_open
= cryptoopen
,
859 .d_read
= cryptoread
,
860 .d_write
= cryptowrite
,
861 .d_ioctl
= cryptoioctl
,
865 * Initialization code, both for static and dynamic loading.
868 cryptodev_modevent(module_t mod
, int type
, void *unused
)
873 kprintf("crypto: <crypto device>\n");
874 make_dev(&crypto_ops
, 0, UID_ROOT
, GID_WHEEL
,
878 /*XXX disallow if active sessions */
879 //dev_ops_remove(&crypto_ops, 0, 0);
880 dev_ops_remove_all(&crypto_ops
);
886 static moduledata_t cryptodev_mod
= {
891 MODULE_VERSION(cryptodev
, 1);
892 DECLARE_MODULE(cryptodev
, cryptodev_mod
, SI_SUB_PSEUDO
, SI_ORDER_ANY
);
893 MODULE_DEPEND(cryptodev
, crypto
, 1, 1, 1);
894 MODULE_DEPEND(cryptodev
, zlib
, 1, 1, 1);