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 * Copyright (c) 2002-2006 Sam Leffler, Errno Consulting
6 * Copyright (c) 2014 The FreeBSD Foundation
7 * All rights reserved.
8 *
9 * Portions of this software were developed by John-Mark Gurney
10 * under sponsorship of the FreeBSD Foundation and
11 * Rubicon Communications, LLC (Netgate).
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 *
17 * 1. Redistributions of source code must retain the above copyright
18 *   notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 *   notice, this list of conditions and the following disclaimer in the
21 *   documentation and/or other materials provided with the distribution.
22 * 3. The name of the author may not be used to endorse or promote products
23 *   derived from this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 *
36 * Effort sponsored in part by the Defense Advanced Research Projects
37 * Agency (DARPA) and Air Force Research Laboratory, Air Force
38 * Materiel Command, USAF, under agreement number F30602-01-2-0537.
39 */
40
41#include <sys/cdefs.h>
42__FBSDID("$FreeBSD: stable/11/sys/opencrypto/cryptodev.c 356908 2020-01-20 11:19:55Z jhb $");
43
44#include "opt_compat.h"
45
46#include <sys/param.h>
47#include <sys/systm.h>
48#include <sys/malloc.h>
49#include <sys/mbuf.h>
50#include <sys/lock.h>
51#include <sys/mutex.h>
52#include <sys/sysctl.h>
53#include <sys/file.h>
54#include <sys/filedesc.h>
55#include <sys/errno.h>
56#include <sys/uio.h>
57#include <sys/random.h>
58#include <sys/conf.h>
59#include <sys/kernel.h>
60#include <sys/module.h>
61#include <sys/fcntl.h>
62#include <sys/bus.h>
63#include <sys/user.h>
64#include <sys/sdt.h>
65
66#include <opencrypto/cryptodev.h>
67#include <opencrypto/xform.h>
68
69SDT_PROVIDER_DECLARE(opencrypto);
70
71SDT_PROBE_DEFINE1(opencrypto, dev, ioctl, error, "int"/*line number*/);
72
73#ifdef COMPAT_FREEBSD32
74#include <sys/mount.h>
75#include <compat/freebsd32/freebsd32.h>
76
77struct session_op32 {
78	u_int32_t	cipher;
79	u_int32_t	mac;
80	u_int32_t	keylen;
81	u_int32_t	key;
82	int		mackeylen;
83	u_int32_t	mackey;
84	u_int32_t	ses;
85};
86
87struct session2_op32 {
88	u_int32_t	cipher;
89	u_int32_t	mac;
90	u_int32_t	keylen;
91	u_int32_t	key;
92	int		mackeylen;
93	u_int32_t	mackey;
94	u_int32_t	ses;
95	int		crid;
96	int		pad[4];
97};
98
99struct crypt_op32 {
100	u_int32_t	ses;
101	u_int16_t	op;
102	u_int16_t	flags;
103	u_int		len;
104	u_int32_t	src, dst;
105	u_int32_t	mac;
106	u_int32_t	iv;
107};
108
109struct crparam32 {
110	u_int32_t	crp_p;
111	u_int		crp_nbits;
112};
113
114struct crypt_kop32 {
115	u_int		crk_op;
116	u_int		crk_status;
117	u_short		crk_iparams;
118	u_short		crk_oparams;
119	u_int		crk_crid;
120	struct crparam32	crk_param[CRK_MAXPARAM];
121};
122
123struct cryptotstat32 {
124	struct timespec32	acc;
125	struct timespec32	min;
126	struct timespec32	max;
127	u_int32_t	count;
128};
129
130struct cryptostats32 {
131	u_int32_t	cs_ops;
132	u_int32_t	cs_errs;
133	u_int32_t	cs_kops;
134	u_int32_t	cs_kerrs;
135	u_int32_t	cs_intrs;
136	u_int32_t	cs_rets;
137	u_int32_t	cs_blocks;
138	u_int32_t	cs_kblocks;
139	struct cryptotstat32 cs_invoke;
140	struct cryptotstat32 cs_done;
141	struct cryptotstat32 cs_cb;
142	struct cryptotstat32 cs_finis;
143};
144
145#define	CIOCGSESSION32	_IOWR('c', 101, struct session_op32)
146#define	CIOCCRYPT32	_IOWR('c', 103, struct crypt_op32)
147#define	CIOCKEY32	_IOWR('c', 104, struct crypt_kop32)
148#define	CIOCGSESSION232	_IOWR('c', 106, struct session2_op32)
149#define	CIOCKEY232	_IOWR('c', 107, struct crypt_kop32)
150
151static void
152session_op_from_32(const struct session_op32 *from, struct session_op *to)
153{
154
155	CP(*from, *to, cipher);
156	CP(*from, *to, mac);
157	CP(*from, *to, keylen);
158	PTRIN_CP(*from, *to, key);
159	CP(*from, *to, mackeylen);
160	PTRIN_CP(*from, *to, mackey);
161	CP(*from, *to, ses);
162}
163
164static void
165session2_op_from_32(const struct session2_op32 *from, struct session2_op *to)
166{
167
168	session_op_from_32((const struct session_op32 *)from,
169	    (struct session_op *)to);
170	CP(*from, *to, crid);
171}
172
173static void
174session_op_to_32(const struct session_op *from, struct session_op32 *to)
175{
176
177	CP(*from, *to, cipher);
178	CP(*from, *to, mac);
179	CP(*from, *to, keylen);
180	PTROUT_CP(*from, *to, key);
181	CP(*from, *to, mackeylen);
182	PTROUT_CP(*from, *to, mackey);
183	CP(*from, *to, ses);
184}
185
186static void
187session2_op_to_32(const struct session2_op *from, struct session2_op32 *to)
188{
189
190	session_op_to_32((const struct session_op *)from,
191	    (struct session_op32 *)to);
192	CP(*from, *to, crid);
193}
194
195static void
196crypt_op_from_32(const struct crypt_op32 *from, struct crypt_op *to)
197{
198
199	CP(*from, *to, ses);
200	CP(*from, *to, op);
201	CP(*from, *to, flags);
202	CP(*from, *to, len);
203	PTRIN_CP(*from, *to, src);
204	PTRIN_CP(*from, *to, dst);
205	PTRIN_CP(*from, *to, mac);
206	PTRIN_CP(*from, *to, iv);
207}
208
209static void
210crypt_op_to_32(const struct crypt_op *from, struct crypt_op32 *to)
211{
212
213	CP(*from, *to, ses);
214	CP(*from, *to, op);
215	CP(*from, *to, flags);
216	CP(*from, *to, len);
217	PTROUT_CP(*from, *to, src);
218	PTROUT_CP(*from, *to, dst);
219	PTROUT_CP(*from, *to, mac);
220	PTROUT_CP(*from, *to, iv);
221}
222
223static void
224crparam_from_32(const struct crparam32 *from, struct crparam *to)
225{
226
227	PTRIN_CP(*from, *to, crp_p);
228	CP(*from, *to, crp_nbits);
229}
230
231static void
232crparam_to_32(const struct crparam *from, struct crparam32 *to)
233{
234
235	PTROUT_CP(*from, *to, crp_p);
236	CP(*from, *to, crp_nbits);
237}
238
239static void
240crypt_kop_from_32(const struct crypt_kop32 *from, struct crypt_kop *to)
241{
242	int i;
243
244	CP(*from, *to, crk_op);
245	CP(*from, *to, crk_status);
246	CP(*from, *to, crk_iparams);
247	CP(*from, *to, crk_oparams);
248	CP(*from, *to, crk_crid);
249	for (i = 0; i < CRK_MAXPARAM; i++)
250		crparam_from_32(&from->crk_param[i], &to->crk_param[i]);
251}
252
253static void
254crypt_kop_to_32(const struct crypt_kop *from, struct crypt_kop32 *to)
255{
256	int i;
257
258	CP(*from, *to, crk_op);
259	CP(*from, *to, crk_status);
260	CP(*from, *to, crk_iparams);
261	CP(*from, *to, crk_oparams);
262	CP(*from, *to, crk_crid);
263	for (i = 0; i < CRK_MAXPARAM; i++)
264		crparam_to_32(&from->crk_param[i], &to->crk_param[i]);
265}
266#endif
267
268struct csession {
269	TAILQ_ENTRY(csession) next;
270	u_int64_t	sid;
271	volatile u_int	refs;
272	u_int32_t	ses;
273	struct mtx	lock;		/* for op submission */
274
275	u_int32_t	cipher;
276	struct enc_xform *txform;
277	u_int32_t	mac;
278	struct auth_hash *thash;
279
280	caddr_t		key;
281	int		keylen;
282
283	caddr_t		mackey;
284	int		mackeylen;
285};
286
287struct cryptop_data {
288	struct csession *cse;
289
290	struct iovec	iovec[1];
291	struct uio	uio;
292	bool		done;
293};
294
295struct fcrypt {
296	TAILQ_HEAD(csessionlist, csession) csessions;
297	int		sesn;
298	struct mtx	lock;
299};
300
301static struct timeval warninterval = { .tv_sec = 60, .tv_usec = 0 };
302SYSCTL_TIMEVAL_SEC(_kern, OID_AUTO, cryptodev_warn_interval, CTLFLAG_RW,
303    &warninterval,
304    "Delay in seconds between warnings of deprecated /dev/crypto algorithms");
305
306static	int cryptof_ioctl(struct file *, u_long, void *,
307		    struct ucred *, struct thread *);
308static	int cryptof_stat(struct file *, struct stat *,
309		    struct ucred *, struct thread *);
310static	int cryptof_close(struct file *, struct thread *);
311static	int cryptof_fill_kinfo(struct file *, struct kinfo_file *,
312		    struct filedesc *);
313
314static struct fileops cryptofops = {
315    .fo_read = invfo_rdwr,
316    .fo_write = invfo_rdwr,
317    .fo_truncate = invfo_truncate,
318    .fo_ioctl = cryptof_ioctl,
319    .fo_poll = invfo_poll,
320    .fo_kqfilter = invfo_kqfilter,
321    .fo_stat = cryptof_stat,
322    .fo_close = cryptof_close,
323    .fo_chmod = invfo_chmod,
324    .fo_chown = invfo_chown,
325    .fo_sendfile = invfo_sendfile,
326    .fo_fill_kinfo = cryptof_fill_kinfo,
327};
328
329static struct csession *csefind(struct fcrypt *, u_int);
330static int csedelete(struct fcrypt *, u_int);
331static struct csession *csecreate(struct fcrypt *, u_int64_t, caddr_t,
332    u_int64_t, caddr_t, u_int64_t, u_int32_t, u_int32_t, struct enc_xform *,
333    struct auth_hash *);
334static int csefree(struct csession *);
335
336static	int cryptodev_op(struct csession *, struct crypt_op *,
337			struct ucred *, struct thread *td);
338static	int cryptodev_aead(struct csession *, struct crypt_aead *,
339			struct ucred *, struct thread *);
340static	int cryptodev_key(struct crypt_kop *);
341static	int cryptodev_find(struct crypt_find_op *);
342
343/*
344 * Check a crypto identifier to see if it requested
345 * a software device/driver.  This can be done either
346 * by device name/class or through search constraints.
347 */
348static int
349checkforsoftware(int *cridp)
350{
351	int crid;
352
353	crid = *cridp;
354
355	if (!crypto_devallowsoft) {
356		if (crid & CRYPTOCAP_F_SOFTWARE) {
357			if (crid & CRYPTOCAP_F_HARDWARE) {
358				*cridp = CRYPTOCAP_F_HARDWARE;
359				return 0;
360			}
361			return EINVAL;
362		}
363		if ((crid & CRYPTOCAP_F_HARDWARE) == 0 &&
364		    (crypto_getcaps(crid) & CRYPTOCAP_F_HARDWARE) == 0)
365			return EINVAL;
366	}
367	return 0;
368}
369
370/* ARGSUSED */
371static int
372cryptof_ioctl(
373	struct file *fp,
374	u_long cmd,
375	void *data,
376	struct ucred *active_cred,
377	struct thread *td)
378{
379#define	SES2(p)	((struct session2_op *)p)
380	struct cryptoini cria, crie;
381	struct fcrypt *fcr = fp->f_data;
382	struct csession *cse;
383	struct session_op *sop;
384	struct crypt_op *cop;
385	struct crypt_aead *caead;
386	struct enc_xform *txform = NULL;
387	struct auth_hash *thash = NULL;
388	struct crypt_kop *kop;
389	u_int64_t sid;
390	u_int32_t ses;
391	int error = 0, crid;
392#ifdef COMPAT_FREEBSD32
393	struct session2_op sopc;
394	struct crypt_op copc;
395	struct crypt_kop kopc;
396#endif
397
398	switch (cmd) {
399	case CIOCGSESSION:
400	case CIOCGSESSION2:
401#ifdef COMPAT_FREEBSD32
402	case CIOCGSESSION32:
403	case CIOCGSESSION232:
404		if (cmd == CIOCGSESSION32) {
405			session_op_from_32(data, (struct session_op *)&sopc);
406			sop = (struct session_op *)&sopc;
407		} else if (cmd == CIOCGSESSION232) {
408			session2_op_from_32(data, &sopc);
409			sop = (struct session_op *)&sopc;
410		} else
411#endif
412			sop = (struct session_op *)data;
413		switch (sop->cipher) {
414		case 0:
415			break;
416		case CRYPTO_DES_CBC:
417			txform = &enc_xform_des;
418			break;
419		case CRYPTO_3DES_CBC:
420			txform = &enc_xform_3des;
421			break;
422		case CRYPTO_BLF_CBC:
423			txform = &enc_xform_blf;
424			break;
425		case CRYPTO_CAST_CBC:
426			txform = &enc_xform_cast5;
427			break;
428		case CRYPTO_SKIPJACK_CBC:
429			txform = &enc_xform_skipjack;
430			break;
431		case CRYPTO_AES_CBC:
432			txform = &enc_xform_rijndael128;
433			break;
434		case CRYPTO_AES_XTS:
435			txform = &enc_xform_aes_xts;
436			break;
437		case CRYPTO_NULL_CBC:
438			txform = &enc_xform_null;
439			break;
440		case CRYPTO_ARC4:
441			txform = &enc_xform_arc4;
442			break;
443 		case CRYPTO_CAMELLIA_CBC:
444 			txform = &enc_xform_camellia;
445 			break;
446		case CRYPTO_AES_ICM:
447			txform = &enc_xform_aes_icm;
448 			break;
449		case CRYPTO_AES_NIST_GCM_16:
450			txform = &enc_xform_aes_nist_gcm;
451 			break;
452
453		default:
454			CRYPTDEB("invalid cipher");
455			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
456			return (EINVAL);
457		}
458
459		switch (sop->mac) {
460		case 0:
461			break;
462		case CRYPTO_MD5_HMAC:
463			thash = &auth_hash_hmac_md5;
464			break;
465		case CRYPTO_SHA1_HMAC:
466			thash = &auth_hash_hmac_sha1;
467			break;
468		case CRYPTO_SHA2_256_HMAC:
469			thash = &auth_hash_hmac_sha2_256;
470			break;
471		case CRYPTO_SHA2_384_HMAC:
472			thash = &auth_hash_hmac_sha2_384;
473			break;
474		case CRYPTO_SHA2_512_HMAC:
475			thash = &auth_hash_hmac_sha2_512;
476			break;
477		case CRYPTO_RIPEMD160_HMAC:
478			thash = &auth_hash_hmac_ripemd_160;
479			break;
480		case CRYPTO_AES_128_NIST_GMAC:
481			thash = &auth_hash_nist_gmac_aes_128;
482			break;
483		case CRYPTO_AES_192_NIST_GMAC:
484			thash = &auth_hash_nist_gmac_aes_192;
485			break;
486		case CRYPTO_AES_256_NIST_GMAC:
487			thash = &auth_hash_nist_gmac_aes_256;
488			break;
489
490#ifdef notdef
491		case CRYPTO_MD5:
492			thash = &auth_hash_md5;
493			break;
494		case CRYPTO_SHA1:
495			thash = &auth_hash_sha1;
496			break;
497#endif
498		case CRYPTO_NULL_HMAC:
499			thash = &auth_hash_null;
500			break;
501		default:
502			CRYPTDEB("invalid mac");
503			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
504			return (EINVAL);
505		}
506
507		bzero(&crie, sizeof(crie));
508		bzero(&cria, sizeof(cria));
509
510		if (txform) {
511			crie.cri_alg = txform->type;
512			crie.cri_klen = sop->keylen * 8;
513			if (sop->keylen > txform->maxkey ||
514			    sop->keylen < txform->minkey) {
515				CRYPTDEB("invalid cipher parameters");
516				error = EINVAL;
517				SDT_PROBE1(opencrypto, dev, ioctl, error,
518				    __LINE__);
519				goto bail;
520			}
521
522			crie.cri_key = malloc(crie.cri_klen / 8,
523			    M_XDATA, M_WAITOK);
524			if ((error = copyin(sop->key, crie.cri_key,
525			    crie.cri_klen / 8))) {
526				CRYPTDEB("invalid key");
527				SDT_PROBE1(opencrypto, dev, ioctl, error,
528				    __LINE__);
529				goto bail;
530			}
531			if (thash)
532				crie.cri_next = &cria;
533		}
534
535		if (thash) {
536			cria.cri_alg = thash->type;
537			cria.cri_klen = sop->mackeylen * 8;
538			if (sop->mackeylen != thash->keysize) {
539				CRYPTDEB("invalid mac key length");
540				error = EINVAL;
541				SDT_PROBE1(opencrypto, dev, ioctl, error,
542				    __LINE__);
543				goto bail;
544			}
545
546			if (cria.cri_klen) {
547				cria.cri_key = malloc(cria.cri_klen / 8,
548				    M_XDATA, M_WAITOK);
549				if ((error = copyin(sop->mackey, cria.cri_key,
550				    cria.cri_klen / 8))) {
551					CRYPTDEB("invalid mac key");
552					SDT_PROBE1(opencrypto, dev, ioctl,
553					    error, __LINE__);
554					goto bail;
555				}
556			}
557		}
558
559		/* NB: CIOCGSESSION2 has the crid */
560		if (cmd == CIOCGSESSION2
561#ifdef COMPAT_FREEBSD32
562		    || cmd == CIOCGSESSION232
563#endif
564			) {
565			crid = SES2(sop)->crid;
566			error = checkforsoftware(&crid);
567			if (error) {
568				CRYPTDEB("checkforsoftware");
569				SDT_PROBE1(opencrypto, dev, ioctl, error,
570				    __LINE__);
571				goto bail;
572			}
573		} else
574			crid = CRYPTOCAP_F_HARDWARE;
575		error = crypto_newsession(&sid, (txform ? &crie : &cria), crid);
576		if (error) {
577			CRYPTDEB("crypto_newsession");
578			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
579			goto bail;
580		}
581
582		cse = csecreate(fcr, sid, crie.cri_key, crie.cri_klen,
583		    cria.cri_key, cria.cri_klen, sop->cipher, sop->mac, txform,
584		    thash);
585
586		if (cse == NULL) {
587			crypto_freesession(sid);
588			error = EINVAL;
589			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
590			CRYPTDEB("csecreate");
591			goto bail;
592		}
593		sop->ses = cse->ses;
594		if (cmd == CIOCGSESSION2
595#ifdef COMPAT_FREEBSD32
596		    || cmd == CIOCGSESSION232
597#endif
598		    ) {
599			/* return hardware/driver id */
600			SES2(sop)->crid = CRYPTO_SESID2HID(cse->sid);
601		}
602bail:
603		if (error) {
604			if (crie.cri_key)
605				free(crie.cri_key, M_XDATA);
606			if (cria.cri_key)
607				free(cria.cri_key, M_XDATA);
608		}
609#ifdef COMPAT_FREEBSD32
610		else {
611			if (cmd == CIOCGSESSION32)
612				session_op_to_32(sop, data);
613			else if (cmd == CIOCGSESSION232)
614				session2_op_to_32((struct session2_op *)sop,
615				    data);
616		}
617#endif
618		break;
619	case CIOCFSESSION:
620		ses = *(u_int32_t *)data;
621		error = csedelete(fcr, ses);
622		if (error != 0)
623			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
624		break;
625	case CIOCCRYPT:
626#ifdef COMPAT_FREEBSD32
627	case CIOCCRYPT32:
628		if (cmd == CIOCCRYPT32) {
629			cop = &copc;
630			crypt_op_from_32(data, cop);
631		} else
632#endif
633			cop = (struct crypt_op *)data;
634		cse = csefind(fcr, cop->ses);
635		if (cse == NULL) {
636			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
637			return (EINVAL);
638		}
639		error = cryptodev_op(cse, cop, active_cred, td);
640		(void)csefree(cse);
641#ifdef COMPAT_FREEBSD32
642		if (error == 0 && cmd == CIOCCRYPT32)
643			crypt_op_to_32(cop, data);
644#endif
645		break;
646	case CIOCKEY:
647	case CIOCKEY2:
648#ifdef COMPAT_FREEBSD32
649	case CIOCKEY32:
650	case CIOCKEY232:
651#endif
652		if (!crypto_userasymcrypto) {
653			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
654			return (EPERM);		/* XXX compat? */
655		}
656#ifdef COMPAT_FREEBSD32
657		if (cmd == CIOCKEY32 || cmd == CIOCKEY232) {
658			kop = &kopc;
659			crypt_kop_from_32(data, kop);
660		} else
661#endif
662			kop = (struct crypt_kop *)data;
663		if (cmd == CIOCKEY
664#ifdef COMPAT_FREEBSD32
665		    || cmd == CIOCKEY32
666#endif
667		    ) {
668			/* NB: crypto core enforces s/w driver use */
669			kop->crk_crid =
670			    CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE;
671		}
672		mtx_lock(&Giant);
673		error = cryptodev_key(kop);
674		mtx_unlock(&Giant);
675#ifdef COMPAT_FREEBSD32
676		if (cmd == CIOCKEY32 || cmd == CIOCKEY232)
677			crypt_kop_to_32(kop, data);
678#endif
679		break;
680	case CIOCASYMFEAT:
681		if (!crypto_userasymcrypto) {
682			/*
683			 * NB: if user asym crypto operations are
684			 * not permitted return "no algorithms"
685			 * so well-behaved applications will just
686			 * fallback to doing them in software.
687			 */
688			*(int *)data = 0;
689		} else {
690			error = crypto_getfeat((int *)data);
691			if (error)
692				SDT_PROBE1(opencrypto, dev, ioctl, error,
693				    __LINE__);
694		}
695		break;
696	case CIOCFINDDEV:
697		error = cryptodev_find((struct crypt_find_op *)data);
698		break;
699	case CIOCCRYPTAEAD:
700		caead = (struct crypt_aead *)data;
701		cse = csefind(fcr, caead->ses);
702		if (cse == NULL) {
703			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
704			return (EINVAL);
705		}
706		error = cryptodev_aead(cse, caead, active_cred, td);
707		(void)csefree(cse);
708		break;
709	default:
710		error = EINVAL;
711		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
712		break;
713	}
714	return (error);
715#undef SES2
716}
717
718static int cryptodev_cb(struct cryptop *);
719
720static struct cryptop_data *
721cod_alloc(struct csession *cse, size_t len, struct thread *td)
722{
723	struct cryptop_data *cod;
724	struct uio *uio;
725
726	cod = malloc(sizeof(struct cryptop_data), M_XDATA, M_WAITOK | M_ZERO);
727
728	cod->cse = cse;
729	uio = &cod->uio;
730	uio->uio_iov = cod->iovec;
731	uio->uio_iovcnt = 1;
732	uio->uio_resid = len;
733	uio->uio_segflg = UIO_SYSSPACE;
734	uio->uio_rw = UIO_WRITE;
735	uio->uio_td = td;
736	uio->uio_iov[0].iov_len = len;
737	uio->uio_iov[0].iov_base = malloc(len, M_XDATA, M_WAITOK);
738	return (cod);
739}
740
741static void
742cod_free(struct cryptop_data *cod)
743{
744
745	free(cod->uio.uio_iov[0].iov_base, M_XDATA);
746	free(cod, M_XDATA);
747}
748
749static void
750cryptodev_warn(struct csession *cse)
751{
752	static struct timeval arc4warn, blfwarn, castwarn, deswarn, md5warn;
753	static struct timeval skipwarn, tdeswarn;
754
755	switch (cse->cipher) {
756	case CRYPTO_DES_CBC:
757		if (ratecheck(&deswarn, &warninterval))
758			gone_in(13, "DES cipher via /dev/crypto");
759		break;
760	case CRYPTO_3DES_CBC:
761		if (ratecheck(&tdeswarn, &warninterval))
762			gone_in(13, "3DES cipher via /dev/crypto");
763		break;
764	case CRYPTO_BLF_CBC:
765		if (ratecheck(&blfwarn, &warninterval))
766			gone_in(13, "Blowfish cipher via /dev/crypto");
767		break;
768	case CRYPTO_CAST_CBC:
769		if (ratecheck(&castwarn, &warninterval))
770			gone_in(13, "CAST128 cipher via /dev/crypto");
771		break;
772	case CRYPTO_SKIPJACK_CBC:
773		if (ratecheck(&skipwarn, &warninterval))
774			gone_in(13, "Skipjack cipher via /dev/crypto");
775		break;
776	case CRYPTO_ARC4:
777		if (ratecheck(&arc4warn, &warninterval))
778			gone_in(13, "ARC4 cipher via /dev/crypto");
779		break;
780	}
781
782	switch (cse->mac) {
783	case CRYPTO_MD5_HMAC:
784		if (ratecheck(&md5warn, &warninterval))
785			gone_in(13, "MD5-HMAC authenticator via /dev/crypto");
786		break;
787	}
788}
789
790static int
791cryptodev_op(
792	struct csession *cse,
793	struct crypt_op *cop,
794	struct ucred *active_cred,
795	struct thread *td)
796{
797	struct cryptop_data *cod = NULL;
798	struct cryptop *crp = NULL;
799	struct cryptodesc *crde = NULL, *crda = NULL;
800	int error;
801
802	if (cop->len > 256*1024-4) {
803		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
804		return (E2BIG);
805	}
806
807	if (cse->txform) {
808		if (cop->len == 0 || (cop->len % cse->txform->blocksize) != 0) {
809			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
810			return (EINVAL);
811		}
812	}
813
814	if (cse->thash)
815		cod = cod_alloc(cse, cop->len + cse->thash->hashsize, td);
816	else
817		cod = cod_alloc(cse, cop->len, td);
818
819	crp = crypto_getreq((cse->txform != NULL) + (cse->thash != NULL));
820	if (crp == NULL) {
821		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
822		error = ENOMEM;
823		goto bail;
824	}
825
826	if (cse->thash && cse->txform) {
827		if (cop->flags & COP_F_CIPHER_FIRST) {
828			crde = crp->crp_desc;
829			crda = crde->crd_next;
830		} else {
831			crda = crp->crp_desc;
832			crde = crda->crd_next;
833		}
834	} else if (cse->thash) {
835		crda = crp->crp_desc;
836	} else if (cse->txform) {
837		crde = crp->crp_desc;
838	} else {
839		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
840		error = EINVAL;
841		goto bail;
842	}
843
844	if ((error = copyin(cop->src, cod->uio.uio_iov[0].iov_base,
845	    cop->len))) {
846		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
847		goto bail;
848	}
849
850	if (crda) {
851		crda->crd_skip = 0;
852		crda->crd_len = cop->len;
853		crda->crd_inject = cop->len;
854
855		crda->crd_alg = cse->mac;
856		crda->crd_key = cse->mackey;
857		crda->crd_klen = cse->mackeylen * 8;
858	}
859
860	if (crde) {
861		if (cop->op == COP_ENCRYPT)
862			crde->crd_flags |= CRD_F_ENCRYPT;
863		else
864			crde->crd_flags &= ~CRD_F_ENCRYPT;
865		crde->crd_len = cop->len;
866		crde->crd_inject = 0;
867
868		crde->crd_alg = cse->cipher;
869		crde->crd_key = cse->key;
870		crde->crd_klen = cse->keylen * 8;
871	}
872
873	crp->crp_ilen = cop->len;
874	crp->crp_flags = CRYPTO_F_IOV | CRYPTO_F_CBIMM
875		       | (cop->flags & COP_F_BATCH);
876	crp->crp_uio = &cod->uio;
877	crp->crp_callback = cryptodev_cb;
878	crp->crp_sid = cse->sid;
879	crp->crp_opaque = cod;
880
881	if (cop->iv) {
882		if (crde == NULL) {
883			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
884			error = EINVAL;
885			goto bail;
886		}
887		if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
888			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
889			error = EINVAL;
890			goto bail;
891		}
892		if ((error = copyin(cop->iv, crde->crd_iv,
893		    cse->txform->blocksize))) {
894			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
895			goto bail;
896		}
897		crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
898		crde->crd_skip = 0;
899	} else if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
900		crde->crd_skip = 0;
901	} else if (crde) {
902		crde->crd_flags |= CRD_F_IV_PRESENT;
903		crde->crd_skip = cse->txform->blocksize;
904		crde->crd_len -= cse->txform->blocksize;
905	}
906
907	if (cop->mac && crda == NULL) {
908		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
909		error = EINVAL;
910		goto bail;
911	}
912	cryptodev_warn(cse);
913
914again:
915	/*
916	 * Let the dispatch run unlocked, then, interlock against the
917	 * callback before checking if the operation completed and going
918	 * to sleep.  This insures drivers don't inherit our lock which
919	 * results in a lock order reversal between crypto_dispatch forced
920	 * entry and the crypto_done callback into us.
921	 */
922	error = crypto_dispatch(crp);
923	if (error != 0) {
924		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
925		goto bail;
926	}
927
928	mtx_lock(&cse->lock);
929	while (!cod->done)
930		mtx_sleep(cod, &cse->lock, PWAIT, "crydev", 0);
931	mtx_unlock(&cse->lock);
932
933	if (crp->crp_etype == EAGAIN) {
934		crp->crp_etype = 0;
935		crp->crp_flags &= ~CRYPTO_F_DONE;
936		cod->done = false;
937		goto again;
938	}
939
940	if (crp->crp_etype != 0) {
941		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
942		error = crp->crp_etype;
943		goto bail;
944	}
945
946	if (cop->dst &&
947	    (error = copyout(cod->uio.uio_iov[0].iov_base, cop->dst,
948	    cop->len))) {
949		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
950		goto bail;
951	}
952
953	if (cop->mac &&
954	    (error = copyout((caddr_t)cod->uio.uio_iov[0].iov_base + cop->len,
955	    cop->mac, cse->thash->hashsize))) {
956		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
957		goto bail;
958	}
959
960bail:
961	if (crp)
962		crypto_freereq(crp);
963	if (cod)
964		cod_free(cod);
965
966	return (error);
967}
968
969static int
970cryptodev_aead(
971	struct csession *cse,
972	struct crypt_aead *caead,
973	struct ucred *active_cred,
974	struct thread *td)
975{
976	struct cryptop_data *cod = NULL;
977	struct cryptop *crp = NULL;
978	struct cryptodesc *crde = NULL, *crda = NULL;
979	int error;
980
981	if (caead->len > 256*1024-4 || caead->aadlen > 256*1024-4) {
982		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
983		return (E2BIG);
984	}
985
986	if (cse->txform == NULL || cse->thash == NULL || caead->tag == NULL ||
987	    (caead->len % cse->txform->blocksize) != 0) {
988		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
989		return (EINVAL);
990	}
991
992	cod = cod_alloc(cse, caead->aadlen + caead->len + cse->thash->hashsize,
993	    td);
994
995	crp = crypto_getreq(2);
996	if (crp == NULL) {
997		error = ENOMEM;
998		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
999		goto bail;
1000	}
1001
1002	if (caead->flags & COP_F_CIPHER_FIRST) {
1003		crde = crp->crp_desc;
1004		crda = crde->crd_next;
1005	} else {
1006		crda = crp->crp_desc;
1007		crde = crda->crd_next;
1008	}
1009
1010	if ((error = copyin(caead->aad, cod->uio.uio_iov[0].iov_base,
1011	    caead->aadlen))) {
1012		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
1013		goto bail;
1014	}
1015
1016	if ((error = copyin(caead->src, (char *)cod->uio.uio_iov[0].iov_base +
1017	    caead->aadlen, caead->len))) {
1018		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
1019		goto bail;
1020	}
1021
1022	/*
1023	 * For GCM, crd_len covers only the AAD.  For other ciphers
1024	 * chained with an HMAC, crd_len covers both the AAD and the
1025	 * cipher text.
1026	 */
1027	crda->crd_skip = 0;
1028	if (cse->cipher == CRYPTO_AES_NIST_GCM_16)
1029		crda->crd_len = caead->aadlen;
1030	else
1031		crda->crd_len = caead->aadlen + caead->len;
1032	crda->crd_inject = caead->aadlen + caead->len;
1033
1034	crda->crd_alg = cse->mac;
1035	crda->crd_key = cse->mackey;
1036	crda->crd_klen = cse->mackeylen * 8;
1037
1038	if (caead->op == COP_ENCRYPT)
1039		crde->crd_flags |= CRD_F_ENCRYPT;
1040	else
1041		crde->crd_flags &= ~CRD_F_ENCRYPT;
1042	crde->crd_skip = caead->aadlen;
1043	crde->crd_len = caead->len;
1044	crde->crd_inject = caead->aadlen;
1045
1046	crde->crd_alg = cse->cipher;
1047	crde->crd_key = cse->key;
1048	crde->crd_klen = cse->keylen * 8;
1049
1050	crp->crp_ilen = caead->aadlen + caead->len;
1051	crp->crp_flags = CRYPTO_F_IOV | CRYPTO_F_CBIMM
1052		       | (caead->flags & COP_F_BATCH);
1053	crp->crp_uio = &cod->uio;
1054	crp->crp_callback = cryptodev_cb;
1055	crp->crp_sid = cse->sid;
1056	crp->crp_opaque = cod;
1057
1058	if (caead->iv) {
1059		if (caead->ivlen > sizeof(crde->crd_iv)) {
1060			error = EINVAL;
1061			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
1062			goto bail;
1063		}
1064
1065		if ((error = copyin(caead->iv, crde->crd_iv, caead->ivlen))) {
1066			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
1067			goto bail;
1068		}
1069		crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
1070	} else {
1071		crde->crd_flags |= CRD_F_IV_PRESENT;
1072		crde->crd_skip += cse->txform->blocksize;
1073		crde->crd_len -= cse->txform->blocksize;
1074	}
1075
1076	if ((error = copyin(caead->tag, (caddr_t)cod->uio.uio_iov[0].iov_base +
1077	    caead->len + caead->aadlen, cse->thash->hashsize))) {
1078		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
1079		goto bail;
1080	}
1081	cryptodev_warn(cse);
1082again:
1083	/*
1084	 * Let the dispatch run unlocked, then, interlock against the
1085	 * callback before checking if the operation completed and going
1086	 * to sleep.  This insures drivers don't inherit our lock which
1087	 * results in a lock order reversal between crypto_dispatch forced
1088	 * entry and the crypto_done callback into us.
1089	 */
1090	error = crypto_dispatch(crp);
1091	if (error != 0) {
1092		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
1093		goto bail;
1094	}
1095
1096	mtx_lock(&cse->lock);
1097	while (!cod->done)
1098		mtx_sleep(cod, &cse->lock, PWAIT, "crydev", 0);
1099	mtx_unlock(&cse->lock);
1100
1101	if (crp->crp_etype == EAGAIN) {
1102		crp->crp_etype = 0;
1103		crp->crp_flags &= ~CRYPTO_F_DONE;
1104		cod->done = false;
1105		goto again;
1106	}
1107
1108	if (crp->crp_etype != 0) {
1109		error = crp->crp_etype;
1110		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
1111		goto bail;
1112	}
1113
1114	if (caead->dst && (error = copyout(
1115	    (caddr_t)cod->uio.uio_iov[0].iov_base + caead->aadlen, caead->dst,
1116	    caead->len))) {
1117		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
1118		goto bail;
1119	}
1120
1121	if ((error = copyout((caddr_t)cod->uio.uio_iov[0].iov_base +
1122	    caead->aadlen + caead->len, caead->tag, cse->thash->hashsize))) {
1123		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
1124		goto bail;
1125	}
1126
1127bail:
1128	crypto_freereq(crp);
1129	if (cod)
1130		cod_free(cod);
1131
1132	return (error);
1133}
1134
1135static int
1136cryptodev_cb(struct cryptop *crp)
1137{
1138	struct cryptop_data *cod = crp->crp_opaque;
1139
1140	/*
1141	 * Lock to ensure the wakeup() is not missed by the loops
1142	 * waiting on cod->done in cryptodev_op() and
1143	 * cryptodev_aead().
1144	 */
1145	mtx_lock(&cod->cse->lock);
1146	cod->done = true;
1147	mtx_unlock(&cod->cse->lock);
1148	wakeup(cod);
1149	return (0);
1150}
1151
1152static int
1153cryptodevkey_cb(void *op)
1154{
1155	struct cryptkop *krp = (struct cryptkop *) op;
1156
1157	wakeup_one(krp);
1158	return (0);
1159}
1160
1161static int
1162cryptodev_key(struct crypt_kop *kop)
1163{
1164	struct cryptkop *krp = NULL;
1165	int error = EINVAL;
1166	int in, out, size, i;
1167
1168	if (kop->crk_iparams + kop->crk_oparams > CRK_MAXPARAM) {
1169		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
1170		return (EFBIG);
1171	}
1172
1173	in = kop->crk_iparams;
1174	out = kop->crk_oparams;
1175	switch (kop->crk_op) {
1176	case CRK_MOD_EXP:
1177		if (in == 3 && out == 1)
1178			break;
1179		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
1180		return (EINVAL);
1181	case CRK_MOD_EXP_CRT:
1182		if (in == 6 && out == 1)
1183			break;
1184		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
1185		return (EINVAL);
1186	case CRK_DSA_SIGN:
1187		if (in == 5 && out == 2)
1188			break;
1189		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
1190		return (EINVAL);
1191	case CRK_DSA_VERIFY:
1192		if (in == 7 && out == 0)
1193			break;
1194		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
1195		return (EINVAL);
1196	case CRK_DH_COMPUTE_KEY:
1197		if (in == 3 && out == 1)
1198			break;
1199		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
1200		return (EINVAL);
1201	default:
1202		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
1203		return (EINVAL);
1204	}
1205
1206	krp = (struct cryptkop *)malloc(sizeof *krp, M_XDATA, M_WAITOK|M_ZERO);
1207	if (!krp) {
1208		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
1209		return (ENOMEM);
1210	}
1211	krp->krp_op = kop->crk_op;
1212	krp->krp_status = kop->crk_status;
1213	krp->krp_iparams = kop->crk_iparams;
1214	krp->krp_oparams = kop->crk_oparams;
1215	krp->krp_crid = kop->crk_crid;
1216	krp->krp_status = 0;
1217	krp->krp_callback = (int (*) (struct cryptkop *)) cryptodevkey_cb;
1218
1219	for (i = 0; i < CRK_MAXPARAM; i++) {
1220		if (kop->crk_param[i].crp_nbits > 65536) {
1221			/* Limit is the same as in OpenBSD */
1222			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
1223			goto fail;
1224		}
1225		krp->krp_param[i].crp_nbits = kop->crk_param[i].crp_nbits;
1226	}
1227	for (i = 0; i < krp->krp_iparams + krp->krp_oparams; i++) {
1228		size = (krp->krp_param[i].crp_nbits + 7) / 8;
1229		if (size == 0)
1230			continue;
1231		krp->krp_param[i].crp_p = malloc(size, M_XDATA, M_WAITOK);
1232		if (i >= krp->krp_iparams)
1233			continue;
1234		error = copyin(kop->crk_param[i].crp_p, krp->krp_param[i].crp_p, size);
1235		if (error) {
1236			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
1237			goto fail;
1238		}
1239	}
1240
1241	error = crypto_kdispatch(krp);
1242	if (error) {
1243		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
1244		goto fail;
1245	}
1246	error = tsleep(krp, PSOCK, "crydev", 0);
1247	if (error) {
1248		/* XXX can this happen?  if so, how do we recover? */
1249		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
1250		goto fail;
1251	}
1252
1253	kop->crk_crid = krp->krp_crid;		/* device that did the work */
1254	if (krp->krp_status != 0) {
1255		error = krp->krp_status;
1256		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
1257		goto fail;
1258	}
1259
1260	for (i = krp->krp_iparams; i < krp->krp_iparams + krp->krp_oparams; i++) {
1261		size = (krp->krp_param[i].crp_nbits + 7) / 8;
1262		if (size == 0)
1263			continue;
1264		error = copyout(krp->krp_param[i].crp_p, kop->crk_param[i].crp_p, size);
1265		if (error) {
1266			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
1267			goto fail;
1268		}
1269	}
1270
1271fail:
1272	if (krp) {
1273		kop->crk_status = krp->krp_status;
1274		for (i = 0; i < CRK_MAXPARAM; i++) {
1275			if (krp->krp_param[i].crp_p)
1276				free(krp->krp_param[i].crp_p, M_XDATA);
1277		}
1278		free(krp, M_XDATA);
1279	}
1280	return (error);
1281}
1282
1283static int
1284cryptodev_find(struct crypt_find_op *find)
1285{
1286	device_t dev;
1287	size_t fnlen = sizeof find->name;
1288
1289	if (find->crid != -1) {
1290		dev = crypto_find_device_byhid(find->crid);
1291		if (dev == NULL)
1292			return (ENOENT);
1293		strncpy(find->name, device_get_nameunit(dev), fnlen);
1294		find->name[fnlen - 1] = '\x0';
1295	} else {
1296		find->name[fnlen - 1] = '\x0';
1297		find->crid = crypto_find_driver(find->name);
1298		if (find->crid == -1)
1299			return (ENOENT);
1300	}
1301	return (0);
1302}
1303
1304/* ARGSUSED */
1305static int
1306cryptof_stat(
1307	struct file *fp,
1308	struct stat *sb,
1309	struct ucred *active_cred,
1310	struct thread *td)
1311{
1312
1313	return (EOPNOTSUPP);
1314}
1315
1316/* ARGSUSED */
1317static int
1318cryptof_close(struct file *fp, struct thread *td)
1319{
1320	struct fcrypt *fcr = fp->f_data;
1321	struct csession *cse;
1322
1323	while ((cse = TAILQ_FIRST(&fcr->csessions))) {
1324		TAILQ_REMOVE(&fcr->csessions, cse, next);
1325		KASSERT(cse->refs == 1,
1326		    ("%s: crypto session %p with %d refs", __func__, cse,
1327		    cse->refs));
1328		(void)csefree(cse);
1329	}
1330	free(fcr, M_XDATA);
1331	fp->f_data = NULL;
1332	return 0;
1333}
1334
1335static int
1336cryptof_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
1337{
1338
1339	kif->kf_type = KF_TYPE_CRYPTO;
1340	return (0);
1341}
1342
1343static struct csession *
1344csefind(struct fcrypt *fcr, u_int ses)
1345{
1346	struct csession *cse;
1347
1348	mtx_lock(&fcr->lock);
1349	TAILQ_FOREACH(cse, &fcr->csessions, next) {
1350		if (cse->ses == ses) {
1351			refcount_acquire(&cse->refs);
1352			mtx_unlock(&fcr->lock);
1353			return (cse);
1354		}
1355	}
1356	mtx_unlock(&fcr->lock);
1357	return (NULL);
1358}
1359
1360static int
1361csedelete(struct fcrypt *fcr, u_int ses)
1362{
1363	struct csession *cse;
1364
1365	mtx_lock(&fcr->lock);
1366	TAILQ_FOREACH(cse, &fcr->csessions, next) {
1367		if (cse->ses == ses) {
1368			TAILQ_REMOVE(&fcr->csessions, cse, next);
1369			mtx_unlock(&fcr->lock);
1370			return (csefree(cse));
1371		}
1372	}
1373	mtx_unlock(&fcr->lock);
1374	return (EINVAL);
1375}
1376
1377struct csession *
1378csecreate(struct fcrypt *fcr, u_int64_t sid, caddr_t key, u_int64_t keylen,
1379    caddr_t mackey, u_int64_t mackeylen, u_int32_t cipher, u_int32_t mac,
1380    struct enc_xform *txform, struct auth_hash *thash)
1381{
1382	struct csession *cse;
1383
1384	cse = malloc(sizeof(struct csession), M_XDATA, M_NOWAIT | M_ZERO);
1385	if (cse == NULL)
1386		return NULL;
1387	mtx_init(&cse->lock, "cryptodev", "crypto session lock", MTX_DEF);
1388	refcount_init(&cse->refs, 1);
1389	cse->key = key;
1390	cse->keylen = keylen/8;
1391	cse->mackey = mackey;
1392	cse->mackeylen = mackeylen/8;
1393	cse->sid = sid;
1394	cse->cipher = cipher;
1395	cse->mac = mac;
1396	cse->txform = txform;
1397	cse->thash = thash;
1398	mtx_lock(&fcr->lock);
1399	TAILQ_INSERT_TAIL(&fcr->csessions, cse, next);
1400	cse->ses = fcr->sesn++;
1401	mtx_unlock(&fcr->lock);
1402	return (cse);
1403}
1404
1405static int
1406csefree(struct csession *cse)
1407{
1408	int error;
1409
1410	if (!refcount_release(&cse->refs))
1411		return (0);
1412	error = crypto_freesession(cse->sid);
1413	mtx_destroy(&cse->lock);
1414	if (cse->key)
1415		free(cse->key, M_XDATA);
1416	if (cse->mackey)
1417		free(cse->mackey, M_XDATA);
1418	free(cse, M_XDATA);
1419	return (error);
1420}
1421
1422static int
1423cryptoopen(struct cdev *dev, int oflags, int devtype, struct thread *td)
1424{
1425	return (0);
1426}
1427
1428static int
1429cryptoread(struct cdev *dev, struct uio *uio, int ioflag)
1430{
1431	return (EIO);
1432}
1433
1434static int
1435cryptowrite(struct cdev *dev, struct uio *uio, int ioflag)
1436{
1437	return (EIO);
1438}
1439
1440static int
1441cryptoioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
1442{
1443	struct file *f;
1444	struct fcrypt *fcr;
1445	int fd, error;
1446
1447	switch (cmd) {
1448	case CRIOGET:
1449		fcr = malloc(sizeof(struct fcrypt), M_XDATA, M_WAITOK | M_ZERO);
1450		TAILQ_INIT(&fcr->csessions);
1451		mtx_init(&fcr->lock, "fcrypt", NULL, MTX_DEF);
1452
1453		error = falloc(td, &f, &fd, 0);
1454
1455		if (error) {
1456			mtx_destroy(&fcr->lock);
1457			free(fcr, M_XDATA);
1458			return (error);
1459		}
1460		/* falloc automatically provides an extra reference to 'f'. */
1461		finit(f, FREAD | FWRITE, DTYPE_CRYPTO, fcr, &cryptofops);
1462		*(u_int32_t *)data = fd;
1463		fdrop(f, td);
1464		break;
1465	case CRIOFINDDEV:
1466		error = cryptodev_find((struct crypt_find_op *)data);
1467		break;
1468	case CRIOASYMFEAT:
1469		error = crypto_getfeat((int *)data);
1470		break;
1471	default:
1472		error = EINVAL;
1473		break;
1474	}
1475	return (error);
1476}
1477
1478static struct cdevsw crypto_cdevsw = {
1479	.d_version =	D_VERSION,
1480	.d_flags =	D_NEEDGIANT,
1481	.d_open =	cryptoopen,
1482	.d_read =	cryptoread,
1483	.d_write =	cryptowrite,
1484	.d_ioctl =	cryptoioctl,
1485	.d_name =	"crypto",
1486};
1487static struct cdev *crypto_dev;
1488
1489/*
1490 * Initialization code, both for static and dynamic loading.
1491 */
1492static int
1493cryptodev_modevent(module_t mod, int type, void *unused)
1494{
1495	switch (type) {
1496	case MOD_LOAD:
1497		if (bootverbose)
1498			printf("crypto: <crypto device>\n");
1499		crypto_dev = make_dev(&crypto_cdevsw, 0,
1500				      UID_ROOT, GID_WHEEL, 0666,
1501				      "crypto");
1502		return 0;
1503	case MOD_UNLOAD:
1504		/*XXX disallow if active sessions */
1505		destroy_dev(crypto_dev);
1506		return 0;
1507	}
1508	return EINVAL;
1509}
1510
1511static moduledata_t cryptodev_mod = {
1512	"cryptodev",
1513	cryptodev_modevent,
1514	0
1515};
1516MODULE_VERSION(cryptodev, 1);
1517DECLARE_MODULE(cryptodev, cryptodev_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
1518MODULE_DEPEND(cryptodev, crypto, 1, 1, 1);
1519MODULE_DEPEND(cryptodev, zlib, 1, 1, 1);
1520