1 /* $FreeBSD: src/sys/opencrypto/cryptodev.c,v 1.4.2.4 2003/06/03 00:09:02 sam Exp $ */
2 /* $DragonFly: src/sys/opencrypto/cryptodev.c,v 1.23 2008/01/06 16:55:53 swildner Exp $ */
3 /* $OpenBSD: cryptodev.c,v 1.52 2002/06/19 07:22:46 deraadt Exp $ */
6 * Copyright (c) 2001 Theo de Raadt
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.
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/malloc.h>
41 #include <sys/sysctl.h>
44 #include <sys/filedesc.h>
45 #include <sys/errno.h>
47 #include <sys/random.h>
49 #include <sys/device.h>
50 #include <sys/kernel.h>
51 #include <sys/fcntl.h>
53 #include <sys/file2.h>
54 #include <sys/thread2.h>
56 #include <opencrypto/cryptodev.h>
57 #include <opencrypto/xform.h>
60 TAILQ_ENTRY(csession
) next
;
65 struct enc_xform
*txform
;
67 struct auth_hash
*thash
;
71 u_char tmp_iv
[EALG_MAX_BLOCK_LEN
];
75 u_char tmp_mac
[CRYPTO_MAX_MAC_LEN
];
77 struct iovec iovec
[UIO_MAXIOV
];
83 TAILQ_HEAD(csessionlist
, csession
) csessions
;
87 static int cryptof_rw(struct file
*fp
, struct uio
*uio
,
88 struct ucred
*cred
, int flags
);
89 static int cryptof_ioctl(struct file
*, u_long
, caddr_t
, struct ucred
*);
90 static int cryptof_poll(struct file
*, int, struct ucred
*);
91 static int cryptof_kqfilter(struct file
*, struct knote
*);
92 static int cryptof_stat(struct file
*, struct stat
*, struct ucred
*);
93 static int cryptof_close(struct file
*);
95 static struct fileops cryptofops
= {
96 .fo_read
= cryptof_rw
,
97 .fo_write
= cryptof_rw
,
98 .fo_ioctl
= cryptof_ioctl
,
99 .fo_poll
= cryptof_poll
,
100 .fo_kqfilter
= cryptof_kqfilter
,
101 .fo_stat
= cryptof_stat
,
102 .fo_close
= cryptof_close
,
103 .fo_shutdown
= nofo_shutdown
106 static struct csession
*csefind(struct fcrypt
*, u_int
);
107 static int csedelete(struct fcrypt
*, struct csession
*);
108 static struct csession
*cseadd(struct fcrypt
*, struct csession
*);
109 static struct csession
*csecreate(struct fcrypt
*, u_int64_t
, caddr_t
,
110 u_int64_t
, caddr_t
, u_int64_t
, u_int32_t
, u_int32_t
, struct enc_xform
*,
112 static int csefree(struct csession
*);
114 static int cryptodev_op(struct csession
*, struct crypt_op
*);
115 static int cryptodev_key(struct crypt_kop
*);
124 struct ucred
*active_cred
,
131 * MPALMOSTSAFE - acquires mplock
140 struct cryptoini cria
, crie
;
142 struct csession
*cse
;
143 struct session_op
*sop
;
144 struct crypt_op
*cop
;
145 struct enc_xform
*txform
= NULL
;
146 struct auth_hash
*thash
= NULL
;
152 fcr
= (struct fcrypt
*)fp
->f_data
;
156 sop
= (struct session_op
*)data
;
157 switch (sop
->cipher
) {
161 txform
= &enc_xform_des
;
163 case CRYPTO_3DES_CBC
:
164 txform
= &enc_xform_3des
;
167 txform
= &enc_xform_blf
;
169 case CRYPTO_CAST_CBC
:
170 txform
= &enc_xform_cast5
;
172 case CRYPTO_SKIPJACK_CBC
:
173 txform
= &enc_xform_skipjack
;
176 txform
= &enc_xform_rijndael128
;
178 case CRYPTO_NULL_CBC
:
179 txform
= &enc_xform_null
;
182 txform
= &enc_xform_arc4
;
194 case CRYPTO_MD5_HMAC
:
195 thash
= &auth_hash_hmac_md5_96
;
197 case CRYPTO_SHA1_HMAC
:
198 thash
= &auth_hash_hmac_sha1_96
;
200 case CRYPTO_SHA2_HMAC
:
201 if (sop
->mackeylen
== auth_hash_hmac_sha2_256
.keysize
)
202 thash
= &auth_hash_hmac_sha2_256
;
203 else if (sop
->mackeylen
== auth_hash_hmac_sha2_384
.keysize
)
204 thash
= &auth_hash_hmac_sha2_384
;
205 else if (sop
->mackeylen
== auth_hash_hmac_sha2_512
.keysize
)
206 thash
= &auth_hash_hmac_sha2_512
;
212 case CRYPTO_RIPEMD160_HMAC
:
213 thash
= &auth_hash_hmac_ripemd_160_96
;
217 thash
= &auth_hash_md5
;
220 thash
= &auth_hash_sha1
;
223 case CRYPTO_NULL_HMAC
:
224 thash
= &auth_hash_null
;
233 bzero(&crie
, sizeof(crie
));
234 bzero(&cria
, sizeof(cria
));
237 crie
.cri_alg
= txform
->type
;
238 crie
.cri_klen
= sop
->keylen
* 8;
239 if (sop
->keylen
> txform
->maxkey
||
240 sop
->keylen
< txform
->minkey
) {
245 MALLOC(crie
.cri_key
, u_int8_t
*,
246 crie
.cri_klen
/ 8, M_XDATA
, M_WAITOK
);
247 if ((error
= copyin(sop
->key
, crie
.cri_key
,
251 crie
.cri_next
= &cria
;
255 cria
.cri_alg
= thash
->type
;
256 cria
.cri_klen
= sop
->mackeylen
* 8;
257 if (sop
->mackeylen
!= thash
->keysize
) {
263 MALLOC(cria
.cri_key
, u_int8_t
*,
264 cria
.cri_klen
/ 8, M_XDATA
, M_WAITOK
);
265 if ((error
= copyin(sop
->mackey
, cria
.cri_key
,
271 error
= crypto_newsession(&sid
, (txform
? &crie
: &cria
), 1);
275 cse
= csecreate(fcr
, sid
, crie
.cri_key
, crie
.cri_klen
,
276 cria
.cri_key
, cria
.cri_klen
, sop
->cipher
, sop
->mac
, txform
,
280 crypto_freesession(sid
);
289 FREE(crie
.cri_key
, M_XDATA
);
291 FREE(cria
.cri_key
, M_XDATA
);
295 ses
= *(u_int32_t
*)data
;
296 cse
= csefind(fcr
, ses
);
302 error
= csefree(cse
);
305 cop
= (struct crypt_op
*)data
;
306 cse
= csefind(fcr
, cop
->ses
);
311 error
= cryptodev_op(cse
, cop
);
314 error
= cryptodev_key((struct crypt_kop
*)data
);
317 error
= crypto_getfeat((int *)data
);
327 static int cryptodev_cb(void *);
331 cryptodev_op(struct csession
*cse
, struct crypt_op
*cop
)
333 struct cryptop
*crp
= NULL
;
334 struct cryptodesc
*crde
= NULL
, *crda
= NULL
;
337 if (cop
->len
> 256*1024-4)
340 if (cse
->txform
&& (cop
->len
% cse
->txform
->blocksize
) != 0)
343 bzero(&cse
->uio
, sizeof(cse
->uio
));
344 cse
->uio
.uio_iovcnt
= 1;
345 cse
->uio
.uio_resid
= 0;
346 cse
->uio
.uio_segflg
= UIO_SYSSPACE
;
347 cse
->uio
.uio_rw
= UIO_WRITE
;
348 cse
->uio
.uio_td
= curthread
;
349 cse
->uio
.uio_iov
= cse
->iovec
;
350 bzero(&cse
->iovec
, sizeof(cse
->iovec
));
351 cse
->uio
.uio_iov
[0].iov_len
= cop
->len
;
352 cse
->uio
.uio_iov
[0].iov_base
= kmalloc(cop
->len
, M_XDATA
, M_WAITOK
);
353 for (i
= 0; i
< cse
->uio
.uio_iovcnt
; i
++)
354 cse
->uio
.uio_resid
+= cse
->uio
.uio_iov
[0].iov_len
;
356 crp
= crypto_getreq((cse
->txform
!= NULL
) + (cse
->thash
!= NULL
));
363 crda
= crp
->crp_desc
;
365 crde
= crda
->crd_next
;
368 crde
= crp
->crp_desc
;
375 if ((error
= copyin(cop
->src
, cse
->uio
.uio_iov
[0].iov_base
, cop
->len
)))
380 crda
->crd_len
= cop
->len
;
381 crda
->crd_inject
= 0; /* ??? */
383 crda
->crd_alg
= cse
->mac
;
384 crda
->crd_key
= cse
->mackey
;
385 crda
->crd_klen
= cse
->mackeylen
* 8;
389 if (cop
->op
== COP_ENCRYPT
)
390 crde
->crd_flags
|= CRD_F_ENCRYPT
;
392 crde
->crd_flags
&= ~CRD_F_ENCRYPT
;
393 crde
->crd_len
= cop
->len
;
394 crde
->crd_inject
= 0;
396 crde
->crd_alg
= cse
->cipher
;
397 crde
->crd_key
= cse
->key
;
398 crde
->crd_klen
= cse
->keylen
* 8;
401 crp
->crp_ilen
= cop
->len
;
402 crp
->crp_flags
= CRYPTO_F_IOV
| CRYPTO_F_CBIMM
403 | (cop
->flags
& COP_F_BATCH
);
404 crp
->crp_buf
= (caddr_t
)&cse
->uio
;
405 crp
->crp_callback
= (int (*) (struct cryptop
*)) cryptodev_cb
;
406 crp
->crp_sid
= cse
->sid
;
407 crp
->crp_opaque
= (void *)cse
;
414 if (cse
->cipher
== CRYPTO_ARC4
) { /* XXX use flag? */
418 if ((error
= copyin(cop
->iv
, cse
->tmp_iv
, cse
->txform
->blocksize
)))
420 bcopy(cse
->tmp_iv
, crde
->crd_iv
, cse
->txform
->blocksize
);
421 crde
->crd_flags
|= CRD_F_IV_EXPLICIT
| CRD_F_IV_PRESENT
;
423 } else if (cse
->cipher
== CRYPTO_ARC4
) { /* XXX use flag? */
426 crde
->crd_flags
|= CRD_F_IV_PRESENT
;
427 crde
->crd_skip
= cse
->txform
->blocksize
;
428 crde
->crd_len
-= cse
->txform
->blocksize
;
436 crp
->crp_mac
=cse
->tmp_mac
;
440 error
= crypto_dispatch(crp
);
441 if (error
== 0 && (crp
->crp_flags
& CRYPTO_F_DONE
) == 0)
442 error
= tsleep(crp
, 0, "crydev", 0);
447 if (crp
->crp_etype
!= 0) {
448 error
= crp
->crp_etype
;
458 (error
= copyout(cse
->uio
.uio_iov
[0].iov_base
, cop
->dst
, cop
->len
)))
462 (error
= copyout(crp
->crp_mac
, cop
->mac
, cse
->thash
->authsize
)))
468 if (cse
->uio
.uio_iov
[0].iov_base
)
469 kfree(cse
->uio
.uio_iov
[0].iov_base
, M_XDATA
);
475 cryptodev_cb(void *op
)
477 struct cryptop
*crp
= (struct cryptop
*) op
;
478 struct csession
*cse
= (struct csession
*)crp
->crp_opaque
;
480 cse
->error
= crp
->crp_etype
;
481 if (crp
->crp_etype
== EAGAIN
)
482 return crypto_dispatch(crp
);
488 cryptodevkey_cb(void *op
)
490 struct cryptkop
*krp
= (struct cryptkop
*) op
;
497 cryptodev_key(struct crypt_kop
*kop
)
499 struct cryptkop
*krp
= NULL
;
501 int in
, out
, size
, i
;
503 if (kop
->crk_iparams
+ kop
->crk_oparams
> CRK_MAXPARAM
) {
507 in
= kop
->crk_iparams
;
508 out
= kop
->crk_oparams
;
509 switch (kop
->crk_op
) {
511 if (in
== 3 && out
== 1)
514 case CRK_MOD_EXP_CRT
:
515 if (in
== 6 && out
== 1)
519 if (in
== 5 && out
== 2)
523 if (in
== 7 && out
== 0)
526 case CRK_DH_COMPUTE_KEY
:
527 if (in
== 3 && out
== 1)
534 krp
= (struct cryptkop
*)kmalloc(sizeof *krp
, M_XDATA
, M_WAITOK
| M_ZERO
);
535 krp
->krp_op
= kop
->crk_op
;
536 krp
->krp_status
= kop
->crk_status
;
537 krp
->krp_iparams
= kop
->crk_iparams
;
538 krp
->krp_oparams
= kop
->crk_oparams
;
540 krp
->krp_callback
= (int (*) (struct cryptkop
*)) cryptodevkey_cb
;
542 for (i
= 0; i
< CRK_MAXPARAM
; i
++)
543 krp
->krp_param
[i
].crp_nbits
= kop
->crk_param
[i
].crp_nbits
;
544 for (i
= 0; i
< krp
->krp_iparams
+ krp
->krp_oparams
; i
++) {
545 size
= (krp
->krp_param
[i
].crp_nbits
+ 7) / 8;
548 MALLOC(krp
->krp_param
[i
].crp_p
, caddr_t
, size
, M_XDATA
, M_WAITOK
);
549 if (i
>= krp
->krp_iparams
)
551 error
= copyin(kop
->crk_param
[i
].crp_p
, krp
->krp_param
[i
].crp_p
, size
);
556 error
= crypto_kdispatch(krp
);
558 error
= tsleep(krp
, 0, "crydev", 0);
562 if (krp
->krp_status
!= 0) {
563 error
= krp
->krp_status
;
567 for (i
= krp
->krp_iparams
; i
< krp
->krp_iparams
+ krp
->krp_oparams
; i
++) {
568 size
= (krp
->krp_param
[i
].crp_nbits
+ 7) / 8;
571 error
= copyout(krp
->krp_param
[i
].crp_p
, kop
->crk_param
[i
].crp_p
, size
);
578 kop
->crk_status
= krp
->krp_status
;
579 for (i
= 0; i
< CRK_MAXPARAM
; i
++) {
580 if (krp
->krp_param
[i
].crp_p
)
581 FREE(krp
->krp_param
[i
].crp_p
, M_XDATA
);
592 cryptof_poll(struct file
*fp
, int events
, struct ucred
*active_cred
)
601 cryptof_kqfilter(struct file
*fp
, struct knote
*kn
)
611 cryptof_stat(struct file
*fp
, struct stat
*sb
, struct ucred
*cred
)
617 * MPALMOSTSAFE - acquires mplock
620 cryptof_close(struct file
*fp
)
623 struct csession
*cse
;
626 fcr
= (struct fcrypt
*)fp
->f_data
;
627 while ((cse
= TAILQ_FIRST(&fcr
->csessions
))) {
628 TAILQ_REMOVE(&fcr
->csessions
, cse
, next
);
638 static struct csession
*
639 csefind(struct fcrypt
*fcr
, u_int ses
)
641 struct csession
*cse
;
643 TAILQ_FOREACH(cse
, &fcr
->csessions
, next
)
650 csedelete(struct fcrypt
*fcr
, struct csession
*cse_del
)
652 struct csession
*cse
;
654 TAILQ_FOREACH(cse
, &fcr
->csessions
, next
) {
655 if (cse
== cse_del
) {
656 TAILQ_REMOVE(&fcr
->csessions
, cse
, next
);
663 static struct csession
*
664 cseadd(struct fcrypt
*fcr
, struct csession
*cse
)
666 TAILQ_INSERT_TAIL(&fcr
->csessions
, cse
, next
);
667 cse
->ses
= fcr
->sesn
++;
672 csecreate(struct fcrypt
*fcr
, u_int64_t sid
, caddr_t key
, u_int64_t keylen
,
673 caddr_t mackey
, u_int64_t mackeylen
, u_int32_t cipher
, u_int32_t mac
,
674 struct enc_xform
*txform
, struct auth_hash
*thash
)
676 struct csession
*cse
;
678 MALLOC(cse
, struct csession
*, sizeof(struct csession
),
683 cse
->keylen
= keylen
/8;
684 cse
->mackey
= mackey
;
685 cse
->mackeylen
= mackeylen
/8;
687 cse
->cipher
= cipher
;
689 cse
->txform
= txform
;
696 csefree(struct csession
*cse
)
700 error
= crypto_freesession(cse
->sid
);
702 FREE(cse
->key
, M_XDATA
);
704 FREE(cse
->mackey
, M_XDATA
);
710 cryptoopen(struct dev_open_args
*ap
)
712 if (crypto_usercrypto
== 0)
718 cryptoread(struct dev_read_args
*ap
)
724 cryptowrite(struct dev_write_args
*ap
)
730 cryptoioctl(struct dev_ioctl_args
*ap
)
738 MALLOC(fcr
, struct fcrypt
*,
739 sizeof(struct fcrypt
), M_XDATA
, M_WAITOK
);
740 TAILQ_INIT(&fcr
->csessions
);
744 error
= falloc(curproc
, &f
, &fd
);
750 f
->f_type
= DTYPE_CRYPTO
;
751 f
->f_flag
= FREAD
| FWRITE
;
752 f
->f_ops
= &cryptofops
;
754 fsetfd(curproc
, f
, fd
);
755 *(u_int32_t
*)ap
->a_data
= fd
;
765 #define CRYPTO_MAJOR 70 /* from openbsd */
766 static struct dev_ops crypto_ops
= {
767 { "crypto", CRYPTO_MAJOR
, 0 },
768 .d_open
= cryptoopen
,
769 .d_close
= nullclose
,
770 .d_read
= cryptoread
,
771 .d_write
= cryptowrite
,
772 .d_ioctl
= cryptoioctl
,
776 * Initialization code, both for static and dynamic loading.
779 cryptodev_modevent(module_t mod
, int type
, void *unused
)
784 kprintf("crypto: <crypto device>\n");
785 dev_ops_add(&crypto_ops
, 0, 0);
786 make_dev(&crypto_ops
, 0, UID_ROOT
, GID_WHEEL
,
790 /*XXX disallow if active sessions */
791 dev_ops_remove(&crypto_ops
, 0, 0);
797 static moduledata_t cryptodev_mod
= {
802 MODULE_VERSION(cryptodev
, 1);
803 DECLARE_MODULE(cryptodev
, cryptodev_mod
, SI_SUB_PSEUDO
, SI_ORDER_ANY
);
805 MODULE_DEPEND(cryptodev
, crypto
, 1, 1, 1);