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