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
,
90 struct ucred
*, struct sysmsg
*);
91 static int cryptof_poll(struct file
*, int, struct ucred
*);
92 static int cryptof_kqfilter(struct file
*, struct knote
*);
93 static int cryptof_stat(struct file
*, struct stat
*, struct ucred
*);
94 static int cryptof_close(struct file
*);
96 static struct fileops cryptofops
= {
97 .fo_read
= cryptof_rw
,
98 .fo_write
= cryptof_rw
,
99 .fo_ioctl
= cryptof_ioctl
,
100 .fo_poll
= cryptof_poll
,
101 .fo_kqfilter
= cryptof_kqfilter
,
102 .fo_stat
= cryptof_stat
,
103 .fo_close
= cryptof_close
,
104 .fo_shutdown
= nofo_shutdown
107 static struct csession
*csefind(struct fcrypt
*, u_int
);
108 static int csedelete(struct fcrypt
*, struct csession
*);
109 static struct csession
*cseadd(struct fcrypt
*, struct csession
*);
110 static struct csession
*csecreate(struct fcrypt
*, u_int64_t
, caddr_t
,
111 u_int64_t
, caddr_t
, u_int64_t
, u_int32_t
, u_int32_t
, struct enc_xform
*,
113 static int csefree(struct csession
*);
115 static int cryptodev_op(struct csession
*, struct crypt_op
*);
116 static int cryptodev_key(struct crypt_kop
*);
125 struct ucred
*active_cred
,
132 * MPALMOSTSAFE - acquires mplock
135 cryptof_ioctl(struct file
*fp
, u_long cmd
, caddr_t data
,
136 struct ucred
*cred
, struct sysmsg
*msg
)
138 struct cryptoini cria
, crie
;
140 struct csession
*cse
;
141 struct session_op
*sop
;
142 struct crypt_op
*cop
;
143 struct enc_xform
*txform
= NULL
;
144 struct auth_hash
*thash
= NULL
;
150 fcr
= (struct fcrypt
*)fp
->f_data
;
154 sop
= (struct session_op
*)data
;
155 switch (sop
->cipher
) {
159 txform
= &enc_xform_des
;
161 case CRYPTO_3DES_CBC
:
162 txform
= &enc_xform_3des
;
165 txform
= &enc_xform_blf
;
167 case CRYPTO_CAST_CBC
:
168 txform
= &enc_xform_cast5
;
170 case CRYPTO_SKIPJACK_CBC
:
171 txform
= &enc_xform_skipjack
;
174 txform
= &enc_xform_rijndael128
;
176 case CRYPTO_NULL_CBC
:
177 txform
= &enc_xform_null
;
180 txform
= &enc_xform_arc4
;
192 case CRYPTO_MD5_HMAC
:
193 thash
= &auth_hash_hmac_md5_96
;
195 case CRYPTO_SHA1_HMAC
:
196 thash
= &auth_hash_hmac_sha1_96
;
198 case CRYPTO_SHA2_HMAC
:
199 if (sop
->mackeylen
== auth_hash_hmac_sha2_256
.keysize
)
200 thash
= &auth_hash_hmac_sha2_256
;
201 else if (sop
->mackeylen
== auth_hash_hmac_sha2_384
.keysize
)
202 thash
= &auth_hash_hmac_sha2_384
;
203 else if (sop
->mackeylen
== auth_hash_hmac_sha2_512
.keysize
)
204 thash
= &auth_hash_hmac_sha2_512
;
210 case CRYPTO_RIPEMD160_HMAC
:
211 thash
= &auth_hash_hmac_ripemd_160_96
;
215 thash
= &auth_hash_md5
;
218 thash
= &auth_hash_sha1
;
221 case CRYPTO_NULL_HMAC
:
222 thash
= &auth_hash_null
;
231 bzero(&crie
, sizeof(crie
));
232 bzero(&cria
, sizeof(cria
));
235 crie
.cri_alg
= txform
->type
;
236 crie
.cri_klen
= sop
->keylen
* 8;
237 if (sop
->keylen
> txform
->maxkey
||
238 sop
->keylen
< txform
->minkey
) {
243 MALLOC(crie
.cri_key
, u_int8_t
*,
244 crie
.cri_klen
/ 8, M_XDATA
, M_WAITOK
);
245 if ((error
= copyin(sop
->key
, crie
.cri_key
,
249 crie
.cri_next
= &cria
;
253 cria
.cri_alg
= thash
->type
;
254 cria
.cri_klen
= sop
->mackeylen
* 8;
255 if (sop
->mackeylen
!= thash
->keysize
) {
261 MALLOC(cria
.cri_key
, u_int8_t
*,
262 cria
.cri_klen
/ 8, M_XDATA
, M_WAITOK
);
263 if ((error
= copyin(sop
->mackey
, cria
.cri_key
,
269 error
= crypto_newsession(&sid
, (txform
? &crie
: &cria
), 1);
273 cse
= csecreate(fcr
, sid
, crie
.cri_key
, crie
.cri_klen
,
274 cria
.cri_key
, cria
.cri_klen
, sop
->cipher
, sop
->mac
, txform
,
278 crypto_freesession(sid
);
287 FREE(crie
.cri_key
, M_XDATA
);
289 FREE(cria
.cri_key
, M_XDATA
);
293 ses
= *(u_int32_t
*)data
;
294 cse
= csefind(fcr
, ses
);
300 error
= csefree(cse
);
303 cop
= (struct crypt_op
*)data
;
304 cse
= csefind(fcr
, cop
->ses
);
309 error
= cryptodev_op(cse
, cop
);
312 error
= cryptodev_key((struct crypt_kop
*)data
);
315 error
= crypto_getfeat((int *)data
);
325 static int cryptodev_cb(void *);
329 cryptodev_op(struct csession
*cse
, struct crypt_op
*cop
)
331 struct cryptop
*crp
= NULL
;
332 struct cryptodesc
*crde
= NULL
, *crda
= NULL
;
335 if (cop
->len
> 256*1024-4)
338 if (cse
->txform
&& (cop
->len
% cse
->txform
->blocksize
) != 0)
341 bzero(&cse
->uio
, sizeof(cse
->uio
));
342 cse
->uio
.uio_iovcnt
= 1;
343 cse
->uio
.uio_resid
= 0;
344 cse
->uio
.uio_segflg
= UIO_SYSSPACE
;
345 cse
->uio
.uio_rw
= UIO_WRITE
;
346 cse
->uio
.uio_td
= curthread
;
347 cse
->uio
.uio_iov
= cse
->iovec
;
348 bzero(&cse
->iovec
, sizeof(cse
->iovec
));
349 cse
->uio
.uio_iov
[0].iov_len
= cop
->len
;
350 cse
->uio
.uio_iov
[0].iov_base
= kmalloc(cop
->len
, M_XDATA
, M_WAITOK
);
351 for (i
= 0; i
< cse
->uio
.uio_iovcnt
; i
++)
352 cse
->uio
.uio_resid
+= cse
->uio
.uio_iov
[0].iov_len
;
354 crp
= crypto_getreq((cse
->txform
!= NULL
) + (cse
->thash
!= NULL
));
361 crda
= crp
->crp_desc
;
363 crde
= crda
->crd_next
;
366 crde
= crp
->crp_desc
;
373 if ((error
= copyin(cop
->src
, cse
->uio
.uio_iov
[0].iov_base
, cop
->len
)))
378 crda
->crd_len
= cop
->len
;
379 crda
->crd_inject
= 0; /* ??? */
381 crda
->crd_alg
= cse
->mac
;
382 crda
->crd_key
= cse
->mackey
;
383 crda
->crd_klen
= cse
->mackeylen
* 8;
387 if (cop
->op
== COP_ENCRYPT
)
388 crde
->crd_flags
|= CRD_F_ENCRYPT
;
390 crde
->crd_flags
&= ~CRD_F_ENCRYPT
;
391 crde
->crd_len
= cop
->len
;
392 crde
->crd_inject
= 0;
394 crde
->crd_alg
= cse
->cipher
;
395 crde
->crd_key
= cse
->key
;
396 crde
->crd_klen
= cse
->keylen
* 8;
399 crp
->crp_ilen
= cop
->len
;
400 crp
->crp_flags
= CRYPTO_F_IOV
| CRYPTO_F_CBIMM
401 | (cop
->flags
& COP_F_BATCH
);
402 crp
->crp_buf
= (caddr_t
)&cse
->uio
;
403 crp
->crp_callback
= (int (*) (struct cryptop
*)) cryptodev_cb
;
404 crp
->crp_sid
= cse
->sid
;
405 crp
->crp_opaque
= (void *)cse
;
412 if (cse
->cipher
== CRYPTO_ARC4
) { /* XXX use flag? */
416 if ((error
= copyin(cop
->iv
, cse
->tmp_iv
, cse
->txform
->blocksize
)))
418 bcopy(cse
->tmp_iv
, crde
->crd_iv
, cse
->txform
->blocksize
);
419 crde
->crd_flags
|= CRD_F_IV_EXPLICIT
| CRD_F_IV_PRESENT
;
421 } else if (cse
->cipher
== CRYPTO_ARC4
) { /* XXX use flag? */
424 crde
->crd_flags
|= CRD_F_IV_PRESENT
;
425 crde
->crd_skip
= cse
->txform
->blocksize
;
426 crde
->crd_len
-= cse
->txform
->blocksize
;
434 crp
->crp_mac
=cse
->tmp_mac
;
438 error
= crypto_dispatch(crp
);
439 if (error
== 0 && (crp
->crp_flags
& CRYPTO_F_DONE
) == 0)
440 error
= tsleep(crp
, 0, "crydev", 0);
445 if (crp
->crp_etype
!= 0) {
446 error
= crp
->crp_etype
;
456 (error
= copyout(cse
->uio
.uio_iov
[0].iov_base
, cop
->dst
, cop
->len
)))
460 (error
= copyout(crp
->crp_mac
, cop
->mac
, cse
->thash
->authsize
)))
466 if (cse
->uio
.uio_iov
[0].iov_base
)
467 kfree(cse
->uio
.uio_iov
[0].iov_base
, M_XDATA
);
473 cryptodev_cb(void *op
)
475 struct cryptop
*crp
= (struct cryptop
*) op
;
476 struct csession
*cse
= (struct csession
*)crp
->crp_opaque
;
478 cse
->error
= crp
->crp_etype
;
479 if (crp
->crp_etype
== EAGAIN
)
480 return crypto_dispatch(crp
);
486 cryptodevkey_cb(void *op
)
488 struct cryptkop
*krp
= (struct cryptkop
*) op
;
495 cryptodev_key(struct crypt_kop
*kop
)
497 struct cryptkop
*krp
= NULL
;
499 int in
, out
, size
, i
;
501 if (kop
->crk_iparams
+ kop
->crk_oparams
> CRK_MAXPARAM
) {
505 in
= kop
->crk_iparams
;
506 out
= kop
->crk_oparams
;
507 switch (kop
->crk_op
) {
509 if (in
== 3 && out
== 1)
512 case CRK_MOD_EXP_CRT
:
513 if (in
== 6 && out
== 1)
517 if (in
== 5 && out
== 2)
521 if (in
== 7 && out
== 0)
524 case CRK_DH_COMPUTE_KEY
:
525 if (in
== 3 && out
== 1)
532 krp
= (struct cryptkop
*)kmalloc(sizeof *krp
, M_XDATA
, M_WAITOK
| M_ZERO
);
533 krp
->krp_op
= kop
->crk_op
;
534 krp
->krp_status
= kop
->crk_status
;
535 krp
->krp_iparams
= kop
->crk_iparams
;
536 krp
->krp_oparams
= kop
->crk_oparams
;
538 krp
->krp_callback
= (int (*) (struct cryptkop
*)) cryptodevkey_cb
;
540 for (i
= 0; i
< CRK_MAXPARAM
; i
++)
541 krp
->krp_param
[i
].crp_nbits
= kop
->crk_param
[i
].crp_nbits
;
542 for (i
= 0; i
< krp
->krp_iparams
+ krp
->krp_oparams
; i
++) {
543 size
= (krp
->krp_param
[i
].crp_nbits
+ 7) / 8;
546 MALLOC(krp
->krp_param
[i
].crp_p
, caddr_t
, size
, M_XDATA
, M_WAITOK
);
547 if (i
>= krp
->krp_iparams
)
549 error
= copyin(kop
->crk_param
[i
].crp_p
, krp
->krp_param
[i
].crp_p
, size
);
554 error
= crypto_kdispatch(krp
);
556 error
= tsleep(krp
, 0, "crydev", 0);
560 if (krp
->krp_status
!= 0) {
561 error
= krp
->krp_status
;
565 for (i
= krp
->krp_iparams
; i
< krp
->krp_iparams
+ krp
->krp_oparams
; i
++) {
566 size
= (krp
->krp_param
[i
].crp_nbits
+ 7) / 8;
569 error
= copyout(krp
->krp_param
[i
].crp_p
, kop
->crk_param
[i
].crp_p
, size
);
576 kop
->crk_status
= krp
->krp_status
;
577 for (i
= 0; i
< CRK_MAXPARAM
; i
++) {
578 if (krp
->krp_param
[i
].crp_p
)
579 FREE(krp
->krp_param
[i
].crp_p
, M_XDATA
);
590 cryptof_poll(struct file
*fp
, int events
, struct ucred
*active_cred
)
599 cryptof_kqfilter(struct file
*fp
, struct knote
*kn
)
609 cryptof_stat(struct file
*fp
, struct stat
*sb
, struct ucred
*cred
)
615 * MPALMOSTSAFE - acquires mplock
618 cryptof_close(struct file
*fp
)
621 struct csession
*cse
;
624 fcr
= (struct fcrypt
*)fp
->f_data
;
625 while ((cse
= TAILQ_FIRST(&fcr
->csessions
))) {
626 TAILQ_REMOVE(&fcr
->csessions
, cse
, next
);
636 static struct csession
*
637 csefind(struct fcrypt
*fcr
, u_int ses
)
639 struct csession
*cse
;
641 TAILQ_FOREACH(cse
, &fcr
->csessions
, next
)
648 csedelete(struct fcrypt
*fcr
, struct csession
*cse_del
)
650 struct csession
*cse
;
652 TAILQ_FOREACH(cse
, &fcr
->csessions
, next
) {
653 if (cse
== cse_del
) {
654 TAILQ_REMOVE(&fcr
->csessions
, cse
, next
);
661 static struct csession
*
662 cseadd(struct fcrypt
*fcr
, struct csession
*cse
)
664 TAILQ_INSERT_TAIL(&fcr
->csessions
, cse
, next
);
665 cse
->ses
= fcr
->sesn
++;
670 csecreate(struct fcrypt
*fcr
, u_int64_t sid
, caddr_t key
, u_int64_t keylen
,
671 caddr_t mackey
, u_int64_t mackeylen
, u_int32_t cipher
, u_int32_t mac
,
672 struct enc_xform
*txform
, struct auth_hash
*thash
)
674 struct csession
*cse
;
676 MALLOC(cse
, struct csession
*, sizeof(struct csession
),
681 cse
->keylen
= keylen
/8;
682 cse
->mackey
= mackey
;
683 cse
->mackeylen
= mackeylen
/8;
685 cse
->cipher
= cipher
;
687 cse
->txform
= txform
;
694 csefree(struct csession
*cse
)
698 error
= crypto_freesession(cse
->sid
);
700 FREE(cse
->key
, M_XDATA
);
702 FREE(cse
->mackey
, M_XDATA
);
708 cryptoopen(struct dev_open_args
*ap
)
710 if (crypto_usercrypto
== 0)
716 cryptoread(struct dev_read_args
*ap
)
722 cryptowrite(struct dev_write_args
*ap
)
728 cryptoioctl(struct dev_ioctl_args
*ap
)
736 MALLOC(fcr
, struct fcrypt
*,
737 sizeof(struct fcrypt
), M_XDATA
, M_WAITOK
);
738 TAILQ_INIT(&fcr
->csessions
);
742 error
= falloc(curproc
, &f
, &fd
);
748 f
->f_type
= DTYPE_CRYPTO
;
749 f
->f_flag
= FREAD
| FWRITE
;
750 f
->f_ops
= &cryptofops
;
752 fsetfd(curproc
, f
, fd
);
753 *(u_int32_t
*)ap
->a_data
= fd
;
763 #define CRYPTO_MAJOR 70 /* from openbsd */
764 static struct dev_ops crypto_ops
= {
765 { "crypto", CRYPTO_MAJOR
, 0 },
766 .d_open
= cryptoopen
,
767 .d_close
= nullclose
,
768 .d_read
= cryptoread
,
769 .d_write
= cryptowrite
,
770 .d_ioctl
= cryptoioctl
,
774 * Initialization code, both for static and dynamic loading.
777 cryptodev_modevent(module_t mod
, int type
, void *unused
)
782 kprintf("crypto: <crypto device>\n");
783 make_dev(&crypto_ops
, 0, UID_ROOT
, GID_WHEEL
,
787 /*XXX disallow if active sessions */
788 //dev_ops_remove(&crypto_ops, 0, 0);
789 dev_ops_remove_all(&crypto_ops
);
795 static moduledata_t cryptodev_mod
= {
800 MODULE_VERSION(cryptodev
, 1);
801 DECLARE_MODULE(cryptodev
, cryptodev_mod
, SI_SUB_PSEUDO
, SI_ORDER_ANY
);
803 MODULE_DEPEND(cryptodev
, crypto
, 1, 1, 1);