xref: /freebsd/sys/opencrypto/cryptodev.c (revision 6b806d21d144c25f4fad714e1c0cf780f5e27d7e)
1 /*	$OpenBSD: cryptodev.c,v 1.52 2002/06/19 07:22:46 deraadt Exp $	*/
2 
3 /*-
4  * Copyright (c) 2001 Theo de Raadt
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *   notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in the
14  *   documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  *   derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  * Effort sponsored in part by the Defense Advanced Research Projects
30  * Agency (DARPA) and Air Force Research Laboratory, Air Force
31  * Materiel Command, USAF, under agreement number F30602-01-2-0537.
32  */
33 
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
36 
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/malloc.h>
40 #include <sys/mbuf.h>
41 #include <sys/lock.h>
42 #include <sys/mutex.h>
43 #include <sys/sysctl.h>
44 #include <sys/file.h>
45 #include <sys/filedesc.h>
46 #include <sys/errno.h>
47 #include <sys/uio.h>
48 #include <sys/random.h>
49 #include <sys/conf.h>
50 #include <sys/kernel.h>
51 #include <sys/module.h>
52 #include <sys/fcntl.h>
53 
54 #include <opencrypto/cryptodev.h>
55 #include <opencrypto/xform.h>
56 
57 struct csession {
58 	TAILQ_ENTRY(csession) next;
59 	u_int64_t	sid;
60 	u_int32_t	ses;
61 	struct mtx	lock;		/* for op submission */
62 
63 	u_int32_t	cipher;
64 	struct enc_xform *txform;
65 	u_int32_t	mac;
66 	struct auth_hash *thash;
67 
68 	caddr_t		key;
69 	int		keylen;
70 	u_char		tmp_iv[EALG_MAX_BLOCK_LEN];
71 
72 	caddr_t		mackey;
73 	int		mackeylen;
74 	u_char		tmp_mac[CRYPTO_MAX_MAC_LEN];
75 
76 	struct iovec	iovec;
77 	struct uio	uio;
78 	int		error;
79 };
80 
81 struct fcrypt {
82 	TAILQ_HEAD(csessionlist, csession) csessions;
83 	int		sesn;
84 };
85 
86 static	int cryptof_rw(struct file *fp, struct uio *uio,
87 		    struct ucred *cred, int flags, struct thread *);
88 static	int cryptof_ioctl(struct file *, u_long, void *,
89 		    struct ucred *, struct thread *);
90 static	int cryptof_poll(struct file *, int, struct ucred *, struct thread *);
91 static	int cryptof_kqfilter(struct file *, struct knote *);
92 static	int cryptof_stat(struct file *, struct stat *,
93 		    struct ucred *, struct thread *);
94 static	int cryptof_close(struct file *, struct thread *);
95 
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 };
105 
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 *,
111     struct auth_hash *);
112 static int csefree(struct csession *);
113 
114 static	int cryptodev_op(struct csession *, struct crypt_op *,
115 			struct ucred *, struct thread *td);
116 static	int cryptodev_key(struct crypt_kop *);
117 
118 static int
119 cryptof_rw(
120 	struct file *fp,
121 	struct uio *uio,
122 	struct ucred *active_cred,
123 	int flags,
124 	struct thread *td)
125 {
126 
127 	return (EIO);
128 }
129 
130 /* ARGSUSED */
131 static int
132 cryptof_ioctl(
133 	struct file *fp,
134 	u_long cmd,
135 	void *data,
136 	struct ucred *active_cred,
137 	struct thread *td)
138 {
139 	struct cryptoini cria, crie;
140 	struct fcrypt *fcr = fp->f_data;
141 	struct csession *cse;
142 	struct session_op *sop;
143 	struct crypt_op *cop;
144 	struct enc_xform *txform = NULL;
145 	struct auth_hash *thash = NULL;
146 	u_int64_t sid;
147 	u_int32_t ses;
148 	int error = 0;
149 
150 	/*
151 	 * XXX: Not sure Giant is needed, but better safe than sorry
152 	 */
153 	mtx_lock(&Giant);
154 	switch (cmd) {
155 	case CIOCGSESSION:
156 		sop = (struct session_op *)data;
157 		switch (sop->cipher) {
158 		case 0:
159 			break;
160 		case CRYPTO_DES_CBC:
161 			txform = &enc_xform_des;
162 			break;
163 		case CRYPTO_3DES_CBC:
164 			txform = &enc_xform_3des;
165 			break;
166 		case CRYPTO_BLF_CBC:
167 			txform = &enc_xform_blf;
168 			break;
169 		case CRYPTO_CAST_CBC:
170 			txform = &enc_xform_cast5;
171 			break;
172 		case CRYPTO_SKIPJACK_CBC:
173 			txform = &enc_xform_skipjack;
174 			break;
175 		case CRYPTO_AES_CBC:
176 			txform = &enc_xform_rijndael128;
177 			break;
178 		case CRYPTO_NULL_CBC:
179 			txform = &enc_xform_null;
180 			break;
181 		case CRYPTO_ARC4:
182 			txform = &enc_xform_arc4;
183 			break;
184 		default:
185 			mtx_unlock(&Giant);
186 			return (EINVAL);
187 		}
188 
189 		switch (sop->mac) {
190 		case 0:
191 			break;
192 		case CRYPTO_MD5_HMAC:
193 			thash = &auth_hash_hmac_md5_96;
194 			break;
195 		case CRYPTO_SHA1_HMAC:
196 			thash = &auth_hash_hmac_sha1_96;
197 			break;
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;
205 			else {
206 				mtx_unlock(&Giant);
207 				return (EINVAL);
208 			}
209 			break;
210 		case CRYPTO_RIPEMD160_HMAC:
211 			thash = &auth_hash_hmac_ripemd_160_96;
212 			break;
213 #ifdef notdef
214 		case CRYPTO_MD5:
215 			thash = &auth_hash_md5;
216 			break;
217 		case CRYPTO_SHA1:
218 			thash = &auth_hash_sha1;
219 			break;
220 #endif
221 		case CRYPTO_NULL_HMAC:
222 			thash = &auth_hash_null;
223 			break;
224 		default:
225 			mtx_unlock(&Giant);
226 			return (EINVAL);
227 		}
228 
229 		bzero(&crie, sizeof(crie));
230 		bzero(&cria, sizeof(cria));
231 
232 		if (txform) {
233 			crie.cri_alg = txform->type;
234 			crie.cri_klen = sop->keylen * 8;
235 			if (sop->keylen > txform->maxkey ||
236 			    sop->keylen < txform->minkey) {
237 				error = EINVAL;
238 				goto bail;
239 			}
240 
241 			MALLOC(crie.cri_key, u_int8_t *,
242 			    crie.cri_klen / 8, M_XDATA, M_WAITOK);
243 			if ((error = copyin(sop->key, crie.cri_key,
244 			    crie.cri_klen / 8)))
245 				goto bail;
246 			if (thash)
247 				crie.cri_next = &cria;
248 		}
249 
250 		if (thash) {
251 			cria.cri_alg = thash->type;
252 			cria.cri_klen = sop->mackeylen * 8;
253 			if (sop->mackeylen != thash->keysize) {
254 				error = EINVAL;
255 				goto bail;
256 			}
257 
258 			if (cria.cri_klen) {
259 				MALLOC(cria.cri_key, u_int8_t *,
260 				    cria.cri_klen / 8, M_XDATA, M_WAITOK);
261 				if ((error = copyin(sop->mackey, cria.cri_key,
262 				    cria.cri_klen / 8)))
263 					goto bail;
264 			}
265 		}
266 
267 		error = crypto_newsession(&sid, (txform ? &crie : &cria), 1);
268 		if (error)
269 			goto bail;
270 
271 		cse = csecreate(fcr, sid, crie.cri_key, crie.cri_klen,
272 		    cria.cri_key, cria.cri_klen, sop->cipher, sop->mac, txform,
273 		    thash);
274 
275 		if (cse == NULL) {
276 			crypto_freesession(sid);
277 			error = EINVAL;
278 			goto bail;
279 		}
280 		sop->ses = cse->ses;
281 
282 bail:
283 		if (error) {
284 			if (crie.cri_key)
285 				FREE(crie.cri_key, M_XDATA);
286 			if (cria.cri_key)
287 				FREE(cria.cri_key, M_XDATA);
288 		}
289 		break;
290 	case CIOCFSESSION:
291 		ses = *(u_int32_t *)data;
292 		cse = csefind(fcr, ses);
293 		if (cse == NULL) {
294 			mtx_unlock(&Giant);
295 			return (EINVAL);
296 		}
297 		csedelete(fcr, cse);
298 		error = csefree(cse);
299 		break;
300 	case CIOCCRYPT:
301 		cop = (struct crypt_op *)data;
302 		cse = csefind(fcr, cop->ses);
303 		if (cse == NULL) {
304 			mtx_unlock(&Giant);
305 			return (EINVAL);
306 		}
307 		error = cryptodev_op(cse, cop, active_cred, td);
308 		break;
309 	case CIOCKEY:
310 		error = cryptodev_key((struct crypt_kop *)data);
311 		break;
312 	case CIOCASYMFEAT:
313 		error = crypto_getfeat((int *)data);
314 		break;
315 	default:
316 		error = EINVAL;
317 	}
318 	mtx_unlock(&Giant);
319 	return (error);
320 }
321 
322 static int cryptodev_cb(void *);
323 
324 
325 static int
326 cryptodev_op(
327 	struct csession *cse,
328 	struct crypt_op *cop,
329 	struct ucred *active_cred,
330 	struct thread *td)
331 {
332 	struct cryptop *crp = NULL;
333 	struct cryptodesc *crde = NULL, *crda = NULL;
334 	int error;
335 
336 	if (cop->len > 256*1024-4)
337 		return (E2BIG);
338 
339 	if (cse->txform && (cop->len % cse->txform->blocksize) != 0)
340 		return (EINVAL);
341 
342 	cse->uio.uio_iov = &cse->iovec;
343 	cse->uio.uio_iovcnt = 1;
344 	cse->uio.uio_offset = 0;
345 	cse->uio.uio_resid = cop->len;
346 	cse->uio.uio_segflg = UIO_SYSSPACE;
347 	cse->uio.uio_rw = UIO_WRITE;
348 	cse->uio.uio_td = td;
349 	cse->uio.uio_iov[0].iov_len = cop->len;
350 	cse->uio.uio_iov[0].iov_base = malloc(cop->len, M_XDATA, M_WAITOK);
351 
352 	crp = crypto_getreq((cse->txform != NULL) + (cse->thash != NULL));
353 	if (crp == NULL) {
354 		error = ENOMEM;
355 		goto bail;
356 	}
357 
358 	if (cse->thash) {
359 		crda = crp->crp_desc;
360 		if (cse->txform)
361 			crde = crda->crd_next;
362 	} else {
363 		if (cse->txform)
364 			crde = crp->crp_desc;
365 		else {
366 			error = EINVAL;
367 			goto bail;
368 		}
369 	}
370 
371 	if ((error = copyin(cop->src, cse->uio.uio_iov[0].iov_base, cop->len)))
372 		goto bail;
373 
374 	if (crda) {
375 		crda->crd_skip = 0;
376 		crda->crd_len = cop->len;
377 		crda->crd_inject = 0;	/* ??? */
378 
379 		crda->crd_alg = cse->mac;
380 		crda->crd_key = cse->mackey;
381 		crda->crd_klen = cse->mackeylen * 8;
382 	}
383 
384 	if (crde) {
385 		if (cop->op == COP_ENCRYPT)
386 			crde->crd_flags |= CRD_F_ENCRYPT;
387 		else
388 			crde->crd_flags &= ~CRD_F_ENCRYPT;
389 		crde->crd_len = cop->len;
390 		crde->crd_inject = 0;
391 
392 		crde->crd_alg = cse->cipher;
393 		crde->crd_key = cse->key;
394 		crde->crd_klen = cse->keylen * 8;
395 	}
396 
397 	crp->crp_ilen = cop->len;
398 	crp->crp_flags = CRYPTO_F_IOV | CRYPTO_F_CBIMM
399 		       | (cop->flags & COP_F_BATCH);
400 	crp->crp_buf = (caddr_t)&cse->uio;
401 	crp->crp_callback = (int (*) (struct cryptop *)) cryptodev_cb;
402 	crp->crp_sid = cse->sid;
403 	crp->crp_opaque = (void *)cse;
404 
405 	if (cop->iv) {
406 		if (crde == NULL) {
407 			error = EINVAL;
408 			goto bail;
409 		}
410 		if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
411 			error = EINVAL;
412 			goto bail;
413 		}
414 		if ((error = copyin(cop->iv, cse->tmp_iv, cse->txform->blocksize)))
415 			goto bail;
416 		bcopy(cse->tmp_iv, crde->crd_iv, cse->txform->blocksize);
417 		crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
418 		crde->crd_skip = 0;
419 	} else if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
420 		crde->crd_skip = 0;
421 	} else if (crde) {
422 		crde->crd_flags |= CRD_F_IV_PRESENT;
423 		crde->crd_skip = cse->txform->blocksize;
424 		crde->crd_len -= cse->txform->blocksize;
425 	}
426 
427 	if (cop->mac) {
428 		if (crda == NULL) {
429 			error = EINVAL;
430 			goto bail;
431 		}
432 		crp->crp_mac=cse->tmp_mac;
433 	}
434 
435 	/*
436 	 * Let the dispatch run unlocked, then, interlock against the
437 	 * callback before checking if the operation completed and going
438 	 * to sleep.  This insures drivers don't inherit our lock which
439 	 * results in a lock order reversal between crypto_dispatch forced
440 	 * entry and the crypto_done callback into us.
441 	 */
442 	error = crypto_dispatch(crp);
443 	mtx_lock(&cse->lock);
444 	if (error == 0 && (crp->crp_flags & CRYPTO_F_DONE) == 0)
445 		error = msleep(crp, &cse->lock, PWAIT, "crydev", 0);
446 	mtx_unlock(&cse->lock);
447 
448 	if (error != 0)
449 		goto bail;
450 
451 	if (crp->crp_etype != 0) {
452 		error = crp->crp_etype;
453 		goto bail;
454 	}
455 
456 	if (cse->error) {
457 		error = cse->error;
458 		goto bail;
459 	}
460 
461 	if (cop->dst &&
462 	    (error = copyout(cse->uio.uio_iov[0].iov_base, cop->dst, cop->len)))
463 		goto bail;
464 
465 	if (cop->mac &&
466 	    (error = copyout(crp->crp_mac, cop->mac, cse->thash->authsize)))
467 		goto bail;
468 
469 bail:
470 	if (crp)
471 		crypto_freereq(crp);
472 	if (cse->uio.uio_iov[0].iov_base)
473 		free(cse->uio.uio_iov[0].iov_base, M_XDATA);
474 
475 	return (error);
476 }
477 
478 static int
479 cryptodev_cb(void *op)
480 {
481 	struct cryptop *crp = (struct cryptop *) op;
482 	struct csession *cse = (struct csession *)crp->crp_opaque;
483 
484 	cse->error = crp->crp_etype;
485 	if (crp->crp_etype == EAGAIN)
486 		return crypto_dispatch(crp);
487 	mtx_lock(&cse->lock);
488 	wakeup_one(crp);
489 	mtx_unlock(&cse->lock);
490 	return (0);
491 }
492 
493 static int
494 cryptodevkey_cb(void *op)
495 {
496 	struct cryptkop *krp = (struct cryptkop *) op;
497 
498 	wakeup(krp);
499 	return (0);
500 }
501 
502 static int
503 cryptodev_key(struct crypt_kop *kop)
504 {
505 	struct cryptkop *krp = NULL;
506 	int error = EINVAL;
507 	int in, out, size, i;
508 
509 	if (kop->crk_iparams + kop->crk_oparams > CRK_MAXPARAM) {
510 		return (EFBIG);
511 	}
512 
513 	in = kop->crk_iparams;
514 	out = kop->crk_oparams;
515 	switch (kop->crk_op) {
516 	case CRK_MOD_EXP:
517 		if (in == 3 && out == 1)
518 			break;
519 		return (EINVAL);
520 	case CRK_MOD_EXP_CRT:
521 		if (in == 6 && out == 1)
522 			break;
523 		return (EINVAL);
524 	case CRK_DSA_SIGN:
525 		if (in == 5 && out == 2)
526 			break;
527 		return (EINVAL);
528 	case CRK_DSA_VERIFY:
529 		if (in == 7 && out == 0)
530 			break;
531 		return (EINVAL);
532 	case CRK_DH_COMPUTE_KEY:
533 		if (in == 3 && out == 1)
534 			break;
535 		return (EINVAL);
536 	default:
537 		return (EINVAL);
538 	}
539 
540 	krp = (struct cryptkop *)malloc(sizeof *krp, M_XDATA, M_WAITOK);
541 	if (!krp)
542 		return (ENOMEM);
543 	bzero(krp, sizeof *krp);
544 	krp->krp_op = kop->crk_op;
545 	krp->krp_status = kop->crk_status;
546 	krp->krp_iparams = kop->crk_iparams;
547 	krp->krp_oparams = kop->crk_oparams;
548 	krp->krp_status = 0;
549 	krp->krp_callback = (int (*) (struct cryptkop *)) cryptodevkey_cb;
550 
551 	for (i = 0; i < CRK_MAXPARAM; i++)
552 		krp->krp_param[i].crp_nbits = kop->crk_param[i].crp_nbits;
553 	for (i = 0; i < krp->krp_iparams + krp->krp_oparams; i++) {
554 		size = (krp->krp_param[i].crp_nbits + 7) / 8;
555 		if (size == 0)
556 			continue;
557 		MALLOC(krp->krp_param[i].crp_p, caddr_t, size, M_XDATA, M_WAITOK);
558 		if (i >= krp->krp_iparams)
559 			continue;
560 		error = copyin(kop->crk_param[i].crp_p, krp->krp_param[i].crp_p, size);
561 		if (error)
562 			goto fail;
563 	}
564 
565 	error = crypto_kdispatch(krp);
566 	if (error)
567 		goto fail;
568 	error = tsleep(krp, PSOCK, "crydev", 0);
569 	if (error) {
570 		/* XXX can this happen?  if so, how do we recover? */
571 		goto fail;
572 	}
573 
574 	if (krp->krp_status != 0) {
575 		error = krp->krp_status;
576 		goto fail;
577 	}
578 
579 	for (i = krp->krp_iparams; i < krp->krp_iparams + krp->krp_oparams; i++) {
580 		size = (krp->krp_param[i].crp_nbits + 7) / 8;
581 		if (size == 0)
582 			continue;
583 		error = copyout(krp->krp_param[i].crp_p, kop->crk_param[i].crp_p, size);
584 		if (error)
585 			goto fail;
586 	}
587 
588 fail:
589 	if (krp) {
590 		kop->crk_status = krp->krp_status;
591 		for (i = 0; i < CRK_MAXPARAM; i++) {
592 			if (krp->krp_param[i].crp_p)
593 				FREE(krp->krp_param[i].crp_p, M_XDATA);
594 		}
595 		free(krp, M_XDATA);
596 	}
597 	return (error);
598 }
599 
600 /* ARGSUSED */
601 static int
602 cryptof_poll(
603 	struct file *fp,
604 	int events,
605 	struct ucred *active_cred,
606 	struct thread *td)
607 {
608 
609 	return (0);
610 }
611 
612 /* ARGSUSED */
613 static int
614 cryptof_kqfilter(struct file *fp, struct knote *kn)
615 {
616 
617 	return (0);
618 }
619 
620 /* ARGSUSED */
621 static int
622 cryptof_stat(
623 	struct file *fp,
624 	struct stat *sb,
625 	struct ucred *active_cred,
626 	struct thread *td)
627 {
628 
629 	return (EOPNOTSUPP);
630 }
631 
632 /* ARGSUSED */
633 static int
634 cryptof_close(struct file *fp, struct thread *td)
635 {
636 	struct fcrypt *fcr = fp->f_data;
637 	struct csession *cse;
638 
639 	while ((cse = TAILQ_FIRST(&fcr->csessions))) {
640 		TAILQ_REMOVE(&fcr->csessions, cse, next);
641 		(void)csefree(cse);
642 	}
643 	FREE(fcr, M_XDATA);
644 	fp->f_data = NULL;
645 	return 0;
646 }
647 
648 static struct csession *
649 csefind(struct fcrypt *fcr, u_int ses)
650 {
651 	struct csession *cse;
652 
653 	TAILQ_FOREACH(cse, &fcr->csessions, next)
654 		if (cse->ses == ses)
655 			return (cse);
656 	return (NULL);
657 }
658 
659 static int
660 csedelete(struct fcrypt *fcr, struct csession *cse_del)
661 {
662 	struct csession *cse;
663 
664 	TAILQ_FOREACH(cse, &fcr->csessions, next) {
665 		if (cse == cse_del) {
666 			TAILQ_REMOVE(&fcr->csessions, cse, next);
667 			return (1);
668 		}
669 	}
670 	return (0);
671 }
672 
673 static struct csession *
674 cseadd(struct fcrypt *fcr, struct csession *cse)
675 {
676 	TAILQ_INSERT_TAIL(&fcr->csessions, cse, next);
677 	cse->ses = fcr->sesn++;
678 	return (cse);
679 }
680 
681 struct csession *
682 csecreate(struct fcrypt *fcr, u_int64_t sid, caddr_t key, u_int64_t keylen,
683     caddr_t mackey, u_int64_t mackeylen, u_int32_t cipher, u_int32_t mac,
684     struct enc_xform *txform, struct auth_hash *thash)
685 {
686 	struct csession *cse;
687 
688 #ifdef INVARIANTS
689 	/* NB: required when mtx_init is built with INVARIANTS */
690 	MALLOC(cse, struct csession *, sizeof(struct csession),
691 	    M_XDATA, M_NOWAIT | M_ZERO);
692 #else
693 	MALLOC(cse, struct csession *, sizeof(struct csession),
694 	    M_XDATA, M_NOWAIT);
695 #endif
696 	if (cse == NULL)
697 		return NULL;
698 	mtx_init(&cse->lock, "cryptodev", "crypto session lock", MTX_DEF);
699 	cse->key = key;
700 	cse->keylen = keylen/8;
701 	cse->mackey = mackey;
702 	cse->mackeylen = mackeylen/8;
703 	cse->sid = sid;
704 	cse->cipher = cipher;
705 	cse->mac = mac;
706 	cse->txform = txform;
707 	cse->thash = thash;
708 	cseadd(fcr, cse);
709 	return (cse);
710 }
711 
712 static int
713 csefree(struct csession *cse)
714 {
715 	int error;
716 
717 	error = crypto_freesession(cse->sid);
718 	mtx_destroy(&cse->lock);
719 	if (cse->key)
720 		FREE(cse->key, M_XDATA);
721 	if (cse->mackey)
722 		FREE(cse->mackey, M_XDATA);
723 	FREE(cse, M_XDATA);
724 	return (error);
725 }
726 
727 static int
728 cryptoopen(struct cdev *dev, int oflags, int devtype, struct thread *td)
729 {
730 	return (0);
731 }
732 
733 static int
734 cryptoread(struct cdev *dev, struct uio *uio, int ioflag)
735 {
736 	return (EIO);
737 }
738 
739 static int
740 cryptowrite(struct cdev *dev, struct uio *uio, int ioflag)
741 {
742 	return (EIO);
743 }
744 
745 static int
746 cryptoioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
747 {
748 	struct file *f;
749 	struct fcrypt *fcr;
750 	int fd, error;
751 
752 	switch (cmd) {
753 	case CRIOGET:
754 		MALLOC(fcr, struct fcrypt *,
755 		    sizeof(struct fcrypt), M_XDATA, M_WAITOK);
756 		TAILQ_INIT(&fcr->csessions);
757 		fcr->sesn = 0;
758 
759 		error = falloc(td, &f, &fd);
760 
761 		if (error) {
762 			FREE(fcr, M_XDATA);
763 			return (error);
764 		}
765 		/* falloc automatically provides an extra reference to 'f'. */
766 		f->f_flag = FREAD | FWRITE;
767 		f->f_type = DTYPE_CRYPTO;
768 		f->f_ops = &cryptofops;
769 		f->f_data = fcr;
770 		*(u_int32_t *)data = fd;
771 		fdrop(f, td);
772 		break;
773 	default:
774 		error = EINVAL;
775 		break;
776 	}
777 	return (error);
778 }
779 
780 #define	CRYPTO_MAJOR	70		/* from openbsd */
781 static struct cdevsw crypto_cdevsw = {
782 	.d_version =	D_VERSION,
783 	.d_flags =	D_NEEDGIANT,
784 	.d_open =	cryptoopen,
785 	.d_read =	cryptoread,
786 	.d_write =	cryptowrite,
787 	.d_ioctl =	cryptoioctl,
788 	.d_name =	"crypto",
789 	.d_maj =	CRYPTO_MAJOR,
790 };
791 static struct cdev *crypto_dev;
792 
793 /*
794  * Initialization code, both for static and dynamic loading.
795  */
796 static int
797 cryptodev_modevent(module_t mod, int type, void *unused)
798 {
799 	switch (type) {
800 	case MOD_LOAD:
801 		if (bootverbose)
802 			printf("crypto: <crypto device>\n");
803 		crypto_dev = make_dev(&crypto_cdevsw, 0,
804 				      UID_ROOT, GID_WHEEL, 0666,
805 				      "crypto");
806 		return 0;
807 	case MOD_UNLOAD:
808 		/*XXX disallow if active sessions */
809 		destroy_dev(crypto_dev);
810 		return 0;
811 	}
812 	return EINVAL;
813 }
814 
815 static moduledata_t cryptodev_mod = {
816 	"cryptodev",
817 	cryptodev_modevent,
818 	0
819 };
820 MODULE_VERSION(cryptodev, 1);
821 DECLARE_MODULE(cryptodev, cryptodev_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
822 MODULE_DEPEND(cryptodev, crypto, 1, 1, 1);
823