xref: /freebsd-src/sys/opencrypto/cryptodev.c (revision fdafd315ad0d0f28a11b9fb4476a9ab059c62b92)
1091d81d1SSam Leffler /*	$OpenBSD: cryptodev.c,v 1.52 2002/06/19 07:22:46 deraadt Exp $	*/
2091d81d1SSam Leffler 
360727d8bSWarner Losh /*-
4091d81d1SSam Leffler  * Copyright (c) 2001 Theo de Raadt
56810ad6fSSam Leffler  * Copyright (c) 2002-2006 Sam Leffler, Errno Consulting
6b4e0a27cSJohn Baldwin  * Copyright (c) 2014-2021 The FreeBSD Foundation
708fca7a5SJohn-Mark Gurney  * All rights reserved.
808fca7a5SJohn-Mark Gurney  *
908fca7a5SJohn-Mark Gurney  * Portions of this software were developed by John-Mark Gurney
1008fca7a5SJohn-Mark Gurney  * under sponsorship of the FreeBSD Foundation and
1108fca7a5SJohn-Mark Gurney  * Rubicon Communications, LLC (Netgate).
12091d81d1SSam Leffler  *
13b4e0a27cSJohn Baldwin  * Portions of this software were developed by Ararat River
14b4e0a27cSJohn Baldwin  * Consulting, LLC under sponsorship of the FreeBSD Foundation.
15b4e0a27cSJohn Baldwin  *
16091d81d1SSam Leffler  * Redistribution and use in source and binary forms, with or without
17091d81d1SSam Leffler  * modification, are permitted provided that the following conditions
18091d81d1SSam Leffler  * are met:
19091d81d1SSam Leffler  *
20091d81d1SSam Leffler  * 1. Redistributions of source code must retain the above copyright
21091d81d1SSam Leffler  *   notice, this list of conditions and the following disclaimer.
22091d81d1SSam Leffler  * 2. Redistributions in binary form must reproduce the above copyright
23091d81d1SSam Leffler  *   notice, this list of conditions and the following disclaimer in the
24091d81d1SSam Leffler  *   documentation and/or other materials provided with the distribution.
25091d81d1SSam Leffler  * 3. The name of the author may not be used to endorse or promote products
26091d81d1SSam Leffler  *   derived from this software without specific prior written permission.
27091d81d1SSam Leffler  *
28091d81d1SSam Leffler  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
29091d81d1SSam Leffler  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
30091d81d1SSam Leffler  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
31091d81d1SSam Leffler  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
32091d81d1SSam Leffler  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
33091d81d1SSam Leffler  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34091d81d1SSam Leffler  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35091d81d1SSam Leffler  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36091d81d1SSam Leffler  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
37091d81d1SSam Leffler  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38091d81d1SSam Leffler  *
39091d81d1SSam Leffler  * Effort sponsored in part by the Defense Advanced Research Projects
40091d81d1SSam Leffler  * Agency (DARPA) and Air Force Research Laboratory, Air Force
41091d81d1SSam Leffler  * Materiel Command, USAF, under agreement number F30602-01-2-0537.
42091d81d1SSam Leffler  */
43091d81d1SSam Leffler 
44091d81d1SSam Leffler #include <sys/param.h>
45091d81d1SSam Leffler #include <sys/systm.h>
46091d81d1SSam Leffler #include <sys/malloc.h>
47091d81d1SSam Leffler #include <sys/mbuf.h>
48091d81d1SSam Leffler #include <sys/lock.h>
49091d81d1SSam Leffler #include <sys/mutex.h>
50688f8b82SJohn Baldwin #include <sys/proc.h>
51091d81d1SSam Leffler #include <sys/sysctl.h>
52091d81d1SSam Leffler #include <sys/errno.h>
53091d81d1SSam Leffler #include <sys/random.h>
54091d81d1SSam Leffler #include <sys/conf.h>
55091d81d1SSam Leffler #include <sys/kernel.h>
565dba30f1SPoul-Henning Kamp #include <sys/module.h>
57091d81d1SSam Leffler #include <sys/fcntl.h>
586810ad6fSSam Leffler #include <sys/bus.h>
5908fca7a5SJohn-Mark Gurney #include <sys/sdt.h>
60688f8b82SJohn Baldwin #include <sys/syscallsubr.h>
61091d81d1SSam Leffler 
62091d81d1SSam Leffler #include <opencrypto/cryptodev.h>
63091d81d1SSam Leffler #include <opencrypto/xform.h>
64091d81d1SSam Leffler 
6508fca7a5SJohn-Mark Gurney SDT_PROVIDER_DECLARE(opencrypto);
6608fca7a5SJohn-Mark Gurney 
6708fca7a5SJohn-Mark Gurney SDT_PROBE_DEFINE1(opencrypto, dev, ioctl, error, "int"/*line number*/);
6808fca7a5SJohn-Mark Gurney 
69688f8b82SJohn Baldwin #ifdef COMPAT_FREEBSD12
70688f8b82SJohn Baldwin /*
71688f8b82SJohn Baldwin  * Previously, most ioctls were performed against a cloned descriptor
72688f8b82SJohn Baldwin  * of /dev/crypto obtained via CRIOGET.  Now all ioctls are performed
73688f8b82SJohn Baldwin  * against /dev/crypto directly.
74688f8b82SJohn Baldwin  */
75688f8b82SJohn Baldwin #define	CRIOGET		_IOWR('c', 100, uint32_t)
76688f8b82SJohn Baldwin #endif
77688f8b82SJohn Baldwin 
78688f8b82SJohn Baldwin /* the following are done against the cloned descriptor */
79688f8b82SJohn Baldwin 
804782e51eSKonstantin Belousov #ifdef COMPAT_FREEBSD32
814782e51eSKonstantin Belousov #include <sys/mount.h>
824782e51eSKonstantin Belousov #include <compat/freebsd32/freebsd32.h>
834782e51eSKonstantin Belousov 
844782e51eSKonstantin Belousov struct session_op32 {
85d3d79e96SJohn Baldwin 	uint32_t	cipher;
86d3d79e96SJohn Baldwin 	uint32_t	mac;
87d3d79e96SJohn Baldwin 	uint32_t	keylen;
88d3d79e96SJohn Baldwin 	uint32_t	key;
894782e51eSKonstantin Belousov 	int		mackeylen;
90d3d79e96SJohn Baldwin 	uint32_t	mackey;
91d3d79e96SJohn Baldwin 	uint32_t	ses;
924782e51eSKonstantin Belousov };
934782e51eSKonstantin Belousov 
944782e51eSKonstantin Belousov struct session2_op32 {
95d3d79e96SJohn Baldwin 	uint32_t	cipher;
96d3d79e96SJohn Baldwin 	uint32_t	mac;
97d3d79e96SJohn Baldwin 	uint32_t	keylen;
98d3d79e96SJohn Baldwin 	uint32_t	key;
994782e51eSKonstantin Belousov 	int		mackeylen;
100d3d79e96SJohn Baldwin 	uint32_t	mackey;
101d3d79e96SJohn Baldwin 	uint32_t	ses;
1024782e51eSKonstantin Belousov 	int		crid;
10316676123SJohn Baldwin 	int		ivlen;
10416676123SJohn Baldwin 	int		maclen;
10516676123SJohn Baldwin 	int		pad[2];
1064782e51eSKonstantin Belousov };
1074782e51eSKonstantin Belousov 
1084782e51eSKonstantin Belousov struct crypt_op32 {
109d3d79e96SJohn Baldwin 	uint32_t	ses;
110d3d79e96SJohn Baldwin 	uint16_t	op;
111d3d79e96SJohn Baldwin 	uint16_t	flags;
1124782e51eSKonstantin Belousov 	u_int		len;
113d3d79e96SJohn Baldwin 	uint32_t	src, dst;
114d3d79e96SJohn Baldwin 	uint32_t	mac;
115d3d79e96SJohn Baldwin 	uint32_t	iv;
1164782e51eSKonstantin Belousov };
1174782e51eSKonstantin Belousov 
118113bcc82SJohn Baldwin struct crypt_aead32 {
119d3d79e96SJohn Baldwin 	uint32_t	ses;
120d3d79e96SJohn Baldwin 	uint16_t	op;
121d3d79e96SJohn Baldwin 	uint16_t	flags;
122113bcc82SJohn Baldwin 	u_int		len;
123113bcc82SJohn Baldwin 	u_int		aadlen;
124113bcc82SJohn Baldwin 	u_int		ivlen;
125d3d79e96SJohn Baldwin 	uint32_t	src;
126d3d79e96SJohn Baldwin 	uint32_t	dst;
127d3d79e96SJohn Baldwin 	uint32_t	aad;
128d3d79e96SJohn Baldwin 	uint32_t	tag;
129d3d79e96SJohn Baldwin 	uint32_t	iv;
130113bcc82SJohn Baldwin };
131113bcc82SJohn Baldwin 
1324782e51eSKonstantin Belousov #define	CIOCGSESSION32	_IOWR('c', 101, struct session_op32)
1334782e51eSKonstantin Belousov #define	CIOCCRYPT32	_IOWR('c', 103, struct crypt_op32)
1344782e51eSKonstantin Belousov #define	CIOCGSESSION232	_IOWR('c', 106, struct session2_op32)
135113bcc82SJohn Baldwin #define	CIOCCRYPTAEAD32	_IOWR('c', 109, struct crypt_aead32)
1364782e51eSKonstantin Belousov 
1374782e51eSKonstantin Belousov static void
session_op_from_32(const struct session_op32 * from,struct session2_op * to)1385612fcb1SJohn Baldwin session_op_from_32(const struct session_op32 *from, struct session2_op *to)
1394782e51eSKonstantin Belousov {
1404782e51eSKonstantin Belousov 
1415612fcb1SJohn Baldwin 	memset(to, 0, sizeof(*to));
1424782e51eSKonstantin Belousov 	CP(*from, *to, cipher);
1434782e51eSKonstantin Belousov 	CP(*from, *to, mac);
1444782e51eSKonstantin Belousov 	CP(*from, *to, keylen);
1454782e51eSKonstantin Belousov 	PTRIN_CP(*from, *to, key);
1464782e51eSKonstantin Belousov 	CP(*from, *to, mackeylen);
1474782e51eSKonstantin Belousov 	PTRIN_CP(*from, *to, mackey);
1484782e51eSKonstantin Belousov 	CP(*from, *to, ses);
1495612fcb1SJohn Baldwin 	to->crid = CRYPTOCAP_F_HARDWARE;
1504782e51eSKonstantin Belousov }
1514782e51eSKonstantin Belousov 
1524782e51eSKonstantin Belousov static void
session2_op_from_32(const struct session2_op32 * from,struct session2_op * to)1534782e51eSKonstantin Belousov session2_op_from_32(const struct session2_op32 *from, struct session2_op *to)
1544782e51eSKonstantin Belousov {
1554782e51eSKonstantin Belousov 
1565612fcb1SJohn Baldwin 	session_op_from_32((const struct session_op32 *)from, to);
1574782e51eSKonstantin Belousov 	CP(*from, *to, crid);
15816676123SJohn Baldwin 	CP(*from, *to, ivlen);
15916676123SJohn Baldwin 	CP(*from, *to, maclen);
1604782e51eSKonstantin Belousov }
1614782e51eSKonstantin Belousov 
1624782e51eSKonstantin Belousov static void
session_op_to_32(const struct session2_op * from,struct session_op32 * to)1635612fcb1SJohn Baldwin session_op_to_32(const struct session2_op *from, struct session_op32 *to)
1644782e51eSKonstantin Belousov {
1654782e51eSKonstantin Belousov 
1664782e51eSKonstantin Belousov 	CP(*from, *to, cipher);
1674782e51eSKonstantin Belousov 	CP(*from, *to, mac);
1684782e51eSKonstantin Belousov 	CP(*from, *to, keylen);
1694782e51eSKonstantin Belousov 	PTROUT_CP(*from, *to, key);
1704782e51eSKonstantin Belousov 	CP(*from, *to, mackeylen);
1714782e51eSKonstantin Belousov 	PTROUT_CP(*from, *to, mackey);
1724782e51eSKonstantin Belousov 	CP(*from, *to, ses);
1734782e51eSKonstantin Belousov }
1744782e51eSKonstantin Belousov 
1754782e51eSKonstantin Belousov static void
session2_op_to_32(const struct session2_op * from,struct session2_op32 * to)1764782e51eSKonstantin Belousov session2_op_to_32(const struct session2_op *from, struct session2_op32 *to)
1774782e51eSKonstantin Belousov {
1784782e51eSKonstantin Belousov 
1795612fcb1SJohn Baldwin 	session_op_to_32(from, (struct session_op32 *)to);
1804782e51eSKonstantin Belousov 	CP(*from, *to, crid);
1814782e51eSKonstantin Belousov }
1824782e51eSKonstantin Belousov 
1834782e51eSKonstantin Belousov static void
crypt_op_from_32(const struct crypt_op32 * from,struct crypt_op * to)1844782e51eSKonstantin Belousov crypt_op_from_32(const struct crypt_op32 *from, struct crypt_op *to)
1854782e51eSKonstantin Belousov {
1864782e51eSKonstantin Belousov 
1874782e51eSKonstantin Belousov 	CP(*from, *to, ses);
1884782e51eSKonstantin Belousov 	CP(*from, *to, op);
1894782e51eSKonstantin Belousov 	CP(*from, *to, flags);
1904782e51eSKonstantin Belousov 	CP(*from, *to, len);
1914782e51eSKonstantin Belousov 	PTRIN_CP(*from, *to, src);
1924782e51eSKonstantin Belousov 	PTRIN_CP(*from, *to, dst);
1934782e51eSKonstantin Belousov 	PTRIN_CP(*from, *to, mac);
1944782e51eSKonstantin Belousov 	PTRIN_CP(*from, *to, iv);
1954782e51eSKonstantin Belousov }
1964782e51eSKonstantin Belousov 
1974782e51eSKonstantin Belousov static void
crypt_op_to_32(const struct crypt_op * from,struct crypt_op32 * to)1984782e51eSKonstantin Belousov crypt_op_to_32(const struct crypt_op *from, struct crypt_op32 *to)
1994782e51eSKonstantin Belousov {
2004782e51eSKonstantin Belousov 
2014782e51eSKonstantin Belousov 	CP(*from, *to, ses);
2024782e51eSKonstantin Belousov 	CP(*from, *to, op);
2034782e51eSKonstantin Belousov 	CP(*from, *to, flags);
2044782e51eSKonstantin Belousov 	CP(*from, *to, len);
2054782e51eSKonstantin Belousov 	PTROUT_CP(*from, *to, src);
2064782e51eSKonstantin Belousov 	PTROUT_CP(*from, *to, dst);
2074782e51eSKonstantin Belousov 	PTROUT_CP(*from, *to, mac);
2084782e51eSKonstantin Belousov 	PTROUT_CP(*from, *to, iv);
2094782e51eSKonstantin Belousov }
2104782e51eSKonstantin Belousov 
2114782e51eSKonstantin Belousov static void
crypt_aead_from_32(const struct crypt_aead32 * from,struct crypt_aead * to)212113bcc82SJohn Baldwin crypt_aead_from_32(const struct crypt_aead32 *from, struct crypt_aead *to)
213113bcc82SJohn Baldwin {
214113bcc82SJohn Baldwin 
215113bcc82SJohn Baldwin 	CP(*from, *to, ses);
216113bcc82SJohn Baldwin 	CP(*from, *to, op);
217113bcc82SJohn Baldwin 	CP(*from, *to, flags);
218113bcc82SJohn Baldwin 	CP(*from, *to, len);
219113bcc82SJohn Baldwin 	CP(*from, *to, aadlen);
220113bcc82SJohn Baldwin 	CP(*from, *to, ivlen);
221113bcc82SJohn Baldwin 	PTRIN_CP(*from, *to, src);
222113bcc82SJohn Baldwin 	PTRIN_CP(*from, *to, dst);
223113bcc82SJohn Baldwin 	PTRIN_CP(*from, *to, aad);
224113bcc82SJohn Baldwin 	PTRIN_CP(*from, *to, tag);
225113bcc82SJohn Baldwin 	PTRIN_CP(*from, *to, iv);
226113bcc82SJohn Baldwin }
227113bcc82SJohn Baldwin 
228113bcc82SJohn Baldwin static void
crypt_aead_to_32(const struct crypt_aead * from,struct crypt_aead32 * to)229113bcc82SJohn Baldwin crypt_aead_to_32(const struct crypt_aead *from, struct crypt_aead32 *to)
230113bcc82SJohn Baldwin {
231113bcc82SJohn Baldwin 
232113bcc82SJohn Baldwin 	CP(*from, *to, ses);
233113bcc82SJohn Baldwin 	CP(*from, *to, op);
234113bcc82SJohn Baldwin 	CP(*from, *to, flags);
235113bcc82SJohn Baldwin 	CP(*from, *to, len);
236113bcc82SJohn Baldwin 	CP(*from, *to, aadlen);
237113bcc82SJohn Baldwin 	CP(*from, *to, ivlen);
238113bcc82SJohn Baldwin 	PTROUT_CP(*from, *to, src);
239113bcc82SJohn Baldwin 	PTROUT_CP(*from, *to, dst);
240113bcc82SJohn Baldwin 	PTROUT_CP(*from, *to, aad);
241113bcc82SJohn Baldwin 	PTROUT_CP(*from, *to, tag);
242113bcc82SJohn Baldwin 	PTROUT_CP(*from, *to, iv);
243113bcc82SJohn Baldwin }
2444782e51eSKonstantin Belousov #endif
2454782e51eSKonstantin Belousov 
2465612fcb1SJohn Baldwin static void
session2_op_from_op(const struct session_op * from,struct session2_op * to)2475612fcb1SJohn Baldwin session2_op_from_op(const struct session_op *from, struct session2_op *to)
2485612fcb1SJohn Baldwin {
2495612fcb1SJohn Baldwin 
2505612fcb1SJohn Baldwin 	memset(to, 0, sizeof(*to));
2515612fcb1SJohn Baldwin 	memcpy(to, from, sizeof(*from));
2525612fcb1SJohn Baldwin 	to->crid = CRYPTOCAP_F_HARDWARE;
2535612fcb1SJohn Baldwin }
2545612fcb1SJohn Baldwin 
2555612fcb1SJohn Baldwin static void
session2_op_to_op(const struct session2_op * from,struct session_op * to)2565612fcb1SJohn Baldwin session2_op_to_op(const struct session2_op *from, struct session_op *to)
2575612fcb1SJohn Baldwin {
2585612fcb1SJohn Baldwin 
2595612fcb1SJohn Baldwin 	memcpy(to, from, sizeof(*to));
2605612fcb1SJohn Baldwin }
2615612fcb1SJohn Baldwin 
262091d81d1SSam Leffler struct csession {
263091d81d1SSam Leffler 	TAILQ_ENTRY(csession) next;
2641b0909d5SConrad Meyer 	crypto_session_t cses;
265d2cdaed1SJohn Baldwin 	volatile u_int	refs;
266d3d79e96SJohn Baldwin 	uint32_t	ses;
2673569ae7fSSam Leffler 	struct mtx	lock;		/* for op submission */
268091d81d1SSam Leffler 
26961ff0a1fSJohn Baldwin 	u_int		blocksize;
270c0341432SJohn Baldwin 	int		hashsize;
271c0341432SJohn Baldwin 	int		ivsize;
272091d81d1SSam Leffler 
273c0341432SJohn Baldwin 	void		*key;
274c0341432SJohn Baldwin 	void		*mackey;
2755425750fSJohn Baldwin };
276091d81d1SSam Leffler 
2775425750fSJohn Baldwin struct cryptop_data {
2785425750fSJohn Baldwin 	struct csession *cse;
2795425750fSJohn Baldwin 
280c0341432SJohn Baldwin 	char		*buf;
281ba63e5e7SJohn Baldwin 	char		*obuf;
2829b774dc0SJohn Baldwin 	char		*aad;
2835425750fSJohn Baldwin 	bool		done;
284091d81d1SSam Leffler };
285091d81d1SSam Leffler 
286091d81d1SSam Leffler struct fcrypt {
287091d81d1SSam Leffler 	TAILQ_HEAD(csessionlist, csession) csessions;
288091d81d1SSam Leffler 	int		sesn;
289d2cdaed1SJohn Baldwin 	struct mtx	lock;
290091d81d1SSam Leffler };
291091d81d1SSam Leffler 
292ba63e5e7SJohn Baldwin static bool use_outputbuffers;
293ba63e5e7SJohn Baldwin SYSCTL_BOOL(_kern_crypto, OID_AUTO, cryptodev_use_output, CTLFLAG_RW,
294ba63e5e7SJohn Baldwin     &use_outputbuffers, 0,
295ba63e5e7SJohn Baldwin     "Use separate output buffers for /dev/crypto requests.");
296ba63e5e7SJohn Baldwin 
2979b774dc0SJohn Baldwin static bool use_separate_aad;
2989b774dc0SJohn Baldwin SYSCTL_BOOL(_kern_crypto, OID_AUTO, cryptodev_separate_aad, CTLFLAG_RW,
2999b774dc0SJohn Baldwin     &use_separate_aad, 0,
3009b774dc0SJohn Baldwin     "Use separate AAD buffer for /dev/crypto requests.");
3019b774dc0SJohn Baldwin 
302*8f3f3fdfSJohn Baldwin static MALLOC_DEFINE(M_CRYPTODEV, "cryptodev", "/dev/crypto data buffers");
303*8f3f3fdfSJohn Baldwin 
3046810ad6fSSam Leffler /*
3056810ad6fSSam Leffler  * Check a crypto identifier to see if it requested
3066810ad6fSSam Leffler  * a software device/driver.  This can be done either
3076810ad6fSSam Leffler  * by device name/class or through search constraints.
3086810ad6fSSam Leffler  */
3096810ad6fSSam Leffler static int
checkforsoftware(int * cridp)31008fca7a5SJohn-Mark Gurney checkforsoftware(int *cridp)
3116810ad6fSSam Leffler {
31208fca7a5SJohn-Mark Gurney 	int crid;
31308fca7a5SJohn-Mark Gurney 
31408fca7a5SJohn-Mark Gurney 	crid = *cridp;
3156c20d7a3SJohn-Mark Gurney 
3166c20d7a3SJohn-Mark Gurney 	if (!crypto_devallowsoft) {
31708fca7a5SJohn-Mark Gurney 		if (crid & CRYPTOCAP_F_SOFTWARE) {
31808fca7a5SJohn-Mark Gurney 			if (crid & CRYPTOCAP_F_HARDWARE) {
31908fca7a5SJohn-Mark Gurney 				*cridp = CRYPTOCAP_F_HARDWARE;
32008fca7a5SJohn-Mark Gurney 				return 0;
32108fca7a5SJohn-Mark Gurney 			}
32208fca7a5SJohn-Mark Gurney 			return EINVAL;
32308fca7a5SJohn-Mark Gurney 		}
3246810ad6fSSam Leffler 		if ((crid & CRYPTOCAP_F_HARDWARE) == 0 &&
3256810ad6fSSam Leffler 		    (crypto_getcaps(crid) & CRYPTOCAP_F_HARDWARE) == 0)
32608fca7a5SJohn-Mark Gurney 			return EINVAL;
3276c20d7a3SJohn-Mark Gurney 	}
3286810ad6fSSam Leffler 	return 0;
3296810ad6fSSam Leffler }
3306810ad6fSSam Leffler 
331b19d4c07SJohn Baldwin static int
cse_create(struct fcrypt * fcr,struct session2_op * sop)332c423784dSJohn Baldwin cse_create(struct fcrypt *fcr, struct session2_op *sop)
333b19d4c07SJohn Baldwin {
334b19d4c07SJohn Baldwin 	struct crypto_session_params csp;
335b19d4c07SJohn Baldwin 	struct csession *cse;
336d8787d4fSMark Johnston 	const struct enc_xform *txform;
337d8787d4fSMark Johnston 	const struct auth_hash *thash;
338b19d4c07SJohn Baldwin 	void *key = NULL;
339b19d4c07SJohn Baldwin 	void *mackey = NULL;
340b19d4c07SJohn Baldwin 	crypto_session_t cses;
341c3907ef4SJohn Baldwin 	int crid, error, mac;
342b19d4c07SJohn Baldwin 
343c3907ef4SJohn Baldwin 	mac = sop->mac;
344b19d4c07SJohn Baldwin #ifdef COMPAT_FREEBSD12
345c3907ef4SJohn Baldwin 	switch (sop->mac) {
346b19d4c07SJohn Baldwin 	case CRYPTO_AES_128_NIST_GMAC:
347b19d4c07SJohn Baldwin 	case CRYPTO_AES_192_NIST_GMAC:
348b19d4c07SJohn Baldwin 	case CRYPTO_AES_256_NIST_GMAC:
349b19d4c07SJohn Baldwin 		/* Should always be paired with GCM. */
350b19d4c07SJohn Baldwin 		if (sop->cipher != CRYPTO_AES_NIST_GCM_16) {
351b19d4c07SJohn Baldwin 			CRYPTDEB("GMAC without GCM");
352b19d4c07SJohn Baldwin 			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
353b19d4c07SJohn Baldwin 			return (EINVAL);
354b19d4c07SJohn Baldwin 		}
355c3907ef4SJohn Baldwin 		if (sop->keylen != sop->mackeylen) {
356b19d4c07SJohn Baldwin 			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
357b19d4c07SJohn Baldwin 			return (EINVAL);
358b19d4c07SJohn Baldwin 		}
359c3907ef4SJohn Baldwin 		mac = 0;
360b19d4c07SJohn Baldwin 		break;
361b19d4c07SJohn Baldwin 	case CRYPTO_AES_CCM_CBC_MAC:
362c3907ef4SJohn Baldwin 		/* Should always be paired with CCM. */
363c3907ef4SJohn Baldwin 		if (sop->cipher != CRYPTO_AES_CCM_16) {
364c3907ef4SJohn Baldwin 			CRYPTDEB("CBC-MAC without CCM");
365b19d4c07SJohn Baldwin 			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
366b19d4c07SJohn Baldwin 			return (EINVAL);
367b19d4c07SJohn Baldwin 		}
368c3907ef4SJohn Baldwin 		if (sop->keylen != sop->mackeylen) {
369b19d4c07SJohn Baldwin 			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
370b19d4c07SJohn Baldwin 			return (EINVAL);
371b19d4c07SJohn Baldwin 		}
372c3907ef4SJohn Baldwin 		mac = 0;
373c3907ef4SJohn Baldwin 		break;
374b19d4c07SJohn Baldwin 	}
375c3907ef4SJohn Baldwin #endif
376b19d4c07SJohn Baldwin 
377b19d4c07SJohn Baldwin 	memset(&csp, 0, sizeof(csp));
378b19d4c07SJohn Baldwin 	if (use_outputbuffers)
379b19d4c07SJohn Baldwin 		csp.csp_flags |= CSP_F_SEPARATE_OUTPUT;
380c3907ef4SJohn Baldwin 	if (mac != 0) {
381c3907ef4SJohn Baldwin 		csp.csp_auth_alg = mac;
382c3907ef4SJohn Baldwin 		csp.csp_auth_klen = sop->mackeylen;
383c3907ef4SJohn Baldwin 	}
384c3907ef4SJohn Baldwin 	if (sop->cipher != 0) {
385c3907ef4SJohn Baldwin 		csp.csp_cipher_alg = sop->cipher;
386c3907ef4SJohn Baldwin 		csp.csp_cipher_klen = sop->keylen;
387c3907ef4SJohn Baldwin 	}
388c3907ef4SJohn Baldwin 	thash = crypto_auth_hash(&csp);
389c3907ef4SJohn Baldwin 	txform = crypto_cipher(&csp);
390b19d4c07SJohn Baldwin 
391c3907ef4SJohn Baldwin 	if (txform != NULL && txform->macsize != 0) {
392c3907ef4SJohn Baldwin 		if (mac != 0) {
393b19d4c07SJohn Baldwin 			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
394b19d4c07SJohn Baldwin 			return (EINVAL);
395b19d4c07SJohn Baldwin 		}
396b19d4c07SJohn Baldwin 		csp.csp_mode = CSP_MODE_AEAD;
397c3907ef4SJohn Baldwin 	} else if (txform != NULL && thash != NULL) {
398b19d4c07SJohn Baldwin 		csp.csp_mode = CSP_MODE_ETA;
399c3907ef4SJohn Baldwin 	} else if (txform != NULL) {
400b19d4c07SJohn Baldwin 		csp.csp_mode = CSP_MODE_CIPHER;
401c3907ef4SJohn Baldwin 	} else if (thash != NULL) {
402b19d4c07SJohn Baldwin 		csp.csp_mode = CSP_MODE_DIGEST;
403c3907ef4SJohn Baldwin 	} else {
404c3907ef4SJohn Baldwin 		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
405c3907ef4SJohn Baldwin 		return (EINVAL);
406c3907ef4SJohn Baldwin 	}
407b19d4c07SJohn Baldwin 
408b19d4c07SJohn Baldwin 	switch (csp.csp_mode) {
409b19d4c07SJohn Baldwin 	case CSP_MODE_AEAD:
410b19d4c07SJohn Baldwin 	case CSP_MODE_ETA:
411b19d4c07SJohn Baldwin 		if (use_separate_aad)
412b19d4c07SJohn Baldwin 			csp.csp_flags |= CSP_F_SEPARATE_AAD;
413b19d4c07SJohn Baldwin 		break;
414b19d4c07SJohn Baldwin 	}
415b19d4c07SJohn Baldwin 
416b19d4c07SJohn Baldwin 	if (txform != NULL) {
417b19d4c07SJohn Baldwin 		if (sop->keylen > txform->maxkey ||
418b19d4c07SJohn Baldwin 		    sop->keylen < txform->minkey) {
419b19d4c07SJohn Baldwin 			CRYPTDEB("invalid cipher parameters");
420b19d4c07SJohn Baldwin 			error = EINVAL;
421b19d4c07SJohn Baldwin 			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
422b19d4c07SJohn Baldwin 			goto bail;
423b19d4c07SJohn Baldwin 		}
424b19d4c07SJohn Baldwin 
425*8f3f3fdfSJohn Baldwin 		key = malloc(csp.csp_cipher_klen, M_CRYPTODEV, M_WAITOK);
426b19d4c07SJohn Baldwin 		error = copyin(sop->key, key, csp.csp_cipher_klen);
427b19d4c07SJohn Baldwin 		if (error) {
428b19d4c07SJohn Baldwin 			CRYPTDEB("invalid key");
429b19d4c07SJohn Baldwin 			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
430b19d4c07SJohn Baldwin 			goto bail;
431b19d4c07SJohn Baldwin 		}
432b19d4c07SJohn Baldwin 		csp.csp_cipher_key = key;
433b19d4c07SJohn Baldwin 		csp.csp_ivlen = txform->ivsize;
434b19d4c07SJohn Baldwin 	}
435b19d4c07SJohn Baldwin 
436b19d4c07SJohn Baldwin 	if (thash != NULL) {
437b19d4c07SJohn Baldwin 		if (sop->mackeylen > thash->keysize || sop->mackeylen < 0) {
438b19d4c07SJohn Baldwin 			CRYPTDEB("invalid mac key length");
439b19d4c07SJohn Baldwin 			error = EINVAL;
440b19d4c07SJohn Baldwin 			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
441b19d4c07SJohn Baldwin 			goto bail;
442b19d4c07SJohn Baldwin 		}
443b19d4c07SJohn Baldwin 
444b19d4c07SJohn Baldwin 		if (csp.csp_auth_klen != 0) {
445*8f3f3fdfSJohn Baldwin 			mackey = malloc(csp.csp_auth_klen, M_CRYPTODEV,
446*8f3f3fdfSJohn Baldwin 			    M_WAITOK);
447b19d4c07SJohn Baldwin 			error = copyin(sop->mackey, mackey, csp.csp_auth_klen);
448b19d4c07SJohn Baldwin 			if (error) {
449b19d4c07SJohn Baldwin 				CRYPTDEB("invalid mac key");
450b19d4c07SJohn Baldwin 				SDT_PROBE1(opencrypto, dev, ioctl, error,
451b19d4c07SJohn Baldwin 				    __LINE__);
452b19d4c07SJohn Baldwin 				goto bail;
453b19d4c07SJohn Baldwin 			}
454b19d4c07SJohn Baldwin 			csp.csp_auth_key = mackey;
455b19d4c07SJohn Baldwin 		}
456b19d4c07SJohn Baldwin 
457b19d4c07SJohn Baldwin 		if (csp.csp_auth_alg == CRYPTO_AES_NIST_GMAC)
458b19d4c07SJohn Baldwin 			csp.csp_ivlen = AES_GCM_IV_LEN;
459b19d4c07SJohn Baldwin 		if (csp.csp_auth_alg == CRYPTO_AES_CCM_CBC_MAC)
460b19d4c07SJohn Baldwin 			csp.csp_ivlen = AES_CCM_IV_LEN;
461b19d4c07SJohn Baldwin 	}
462b19d4c07SJohn Baldwin 
46316676123SJohn Baldwin 	if (sop->ivlen != 0) {
46416676123SJohn Baldwin 		if (csp.csp_ivlen == 0) {
46516676123SJohn Baldwin 			CRYPTDEB("does not support an IV");
46616676123SJohn Baldwin 			error = EINVAL;
46716676123SJohn Baldwin 			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
46816676123SJohn Baldwin 			goto bail;
46916676123SJohn Baldwin 		}
47016676123SJohn Baldwin 		csp.csp_ivlen = sop->ivlen;
47116676123SJohn Baldwin 	}
47216676123SJohn Baldwin 	if (sop->maclen != 0) {
47316676123SJohn Baldwin 		if (!(thash != NULL || csp.csp_mode == CSP_MODE_AEAD)) {
47416676123SJohn Baldwin 			CRYPTDEB("does not support a MAC");
47516676123SJohn Baldwin 			error = EINVAL;
47616676123SJohn Baldwin 			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
47716676123SJohn Baldwin 			goto bail;
47816676123SJohn Baldwin 		}
47916676123SJohn Baldwin 		csp.csp_auth_mlen = sop->maclen;
48016676123SJohn Baldwin 	}
48116676123SJohn Baldwin 
482b19d4c07SJohn Baldwin 	crid = sop->crid;
483b19d4c07SJohn Baldwin 	error = checkforsoftware(&crid);
484b19d4c07SJohn Baldwin 	if (error) {
485b19d4c07SJohn Baldwin 		CRYPTDEB("checkforsoftware");
486b19d4c07SJohn Baldwin 		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
487b19d4c07SJohn Baldwin 		goto bail;
488b19d4c07SJohn Baldwin 	}
489b19d4c07SJohn Baldwin 	error = crypto_newsession(&cses, &csp, crid);
490b19d4c07SJohn Baldwin 	if (error) {
491b19d4c07SJohn Baldwin 		CRYPTDEB("crypto_newsession");
492b19d4c07SJohn Baldwin 		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
493b19d4c07SJohn Baldwin 		goto bail;
494b19d4c07SJohn Baldwin 	}
495b19d4c07SJohn Baldwin 
496*8f3f3fdfSJohn Baldwin 	cse = malloc(sizeof(struct csession), M_CRYPTODEV, M_WAITOK | M_ZERO);
497c423784dSJohn Baldwin 	mtx_init(&cse->lock, "cryptodev", "crypto session lock", MTX_DEF);
498c423784dSJohn Baldwin 	refcount_init(&cse->refs, 1);
499c423784dSJohn Baldwin 	cse->key = key;
500c423784dSJohn Baldwin 	cse->mackey = mackey;
501c423784dSJohn Baldwin 	cse->cses = cses;
50216676123SJohn Baldwin 	if (sop->maclen != 0)
50316676123SJohn Baldwin 		cse->hashsize = sop->maclen;
50416676123SJohn Baldwin 	else if (thash != NULL)
505c423784dSJohn Baldwin 		cse->hashsize = thash->hashsize;
506ab91fb6cSJohn Baldwin 	else if (csp.csp_mode == CSP_MODE_AEAD)
507ab91fb6cSJohn Baldwin 		cse->hashsize = txform->macsize;
508c423784dSJohn Baldwin 	cse->ivsize = csp.csp_ivlen;
509b19d4c07SJohn Baldwin 
51061ff0a1fSJohn Baldwin 	/*
51161ff0a1fSJohn Baldwin 	 * NB: This isn't necessarily the block size of the underlying
51261ff0a1fSJohn Baldwin 	 * MAC or cipher but is instead a restriction on valid input
51361ff0a1fSJohn Baldwin 	 * sizes.
51461ff0a1fSJohn Baldwin 	 */
51561ff0a1fSJohn Baldwin 	if (txform != NULL)
51661ff0a1fSJohn Baldwin 		cse->blocksize = txform->blocksize;
51761ff0a1fSJohn Baldwin 	else
51861ff0a1fSJohn Baldwin 		cse->blocksize = 1;
51961ff0a1fSJohn Baldwin 
520c423784dSJohn Baldwin 	mtx_lock(&fcr->lock);
521c423784dSJohn Baldwin 	TAILQ_INSERT_TAIL(&fcr->csessions, cse, next);
522c423784dSJohn Baldwin 	cse->ses = fcr->sesn++;
523c423784dSJohn Baldwin 	mtx_unlock(&fcr->lock);
524c423784dSJohn Baldwin 
525b19d4c07SJohn Baldwin 	sop->ses = cse->ses;
526b19d4c07SJohn Baldwin 
527b19d4c07SJohn Baldwin 	/* return hardware/driver id */
528b19d4c07SJohn Baldwin 	sop->crid = crypto_ses2hid(cse->cses);
529b19d4c07SJohn Baldwin bail:
530b19d4c07SJohn Baldwin 	if (error) {
531*8f3f3fdfSJohn Baldwin 		free(key, M_CRYPTODEV);
532*8f3f3fdfSJohn Baldwin 		free(mackey, M_CRYPTODEV);
533b19d4c07SJohn Baldwin 	}
534b19d4c07SJohn Baldwin 	return (error);
535b19d4c07SJohn Baldwin }
536b19d4c07SJohn Baldwin 
537c423784dSJohn Baldwin static struct csession *
cse_find(struct fcrypt * fcr,u_int ses)538c423784dSJohn Baldwin cse_find(struct fcrypt *fcr, u_int ses)
539c423784dSJohn Baldwin {
540c423784dSJohn Baldwin 	struct csession *cse;
541c423784dSJohn Baldwin 
542c423784dSJohn Baldwin 	mtx_lock(&fcr->lock);
543c423784dSJohn Baldwin 	TAILQ_FOREACH(cse, &fcr->csessions, next) {
544c423784dSJohn Baldwin 		if (cse->ses == ses) {
545c423784dSJohn Baldwin 			refcount_acquire(&cse->refs);
546c423784dSJohn Baldwin 			mtx_unlock(&fcr->lock);
547c423784dSJohn Baldwin 			return (cse);
548c423784dSJohn Baldwin 		}
549c423784dSJohn Baldwin 	}
550c423784dSJohn Baldwin 	mtx_unlock(&fcr->lock);
551c423784dSJohn Baldwin 	return (NULL);
552c423784dSJohn Baldwin }
553c423784dSJohn Baldwin 
554c423784dSJohn Baldwin static void
cse_free(struct csession * cse)555c423784dSJohn Baldwin cse_free(struct csession *cse)
556c423784dSJohn Baldwin {
557c423784dSJohn Baldwin 
558c423784dSJohn Baldwin 	if (!refcount_release(&cse->refs))
559c423784dSJohn Baldwin 		return;
560c423784dSJohn Baldwin 	crypto_freesession(cse->cses);
561c423784dSJohn Baldwin 	mtx_destroy(&cse->lock);
562c423784dSJohn Baldwin 	if (cse->key)
563*8f3f3fdfSJohn Baldwin 		free(cse->key, M_CRYPTODEV);
564c423784dSJohn Baldwin 	if (cse->mackey)
565*8f3f3fdfSJohn Baldwin 		free(cse->mackey, M_CRYPTODEV);
566*8f3f3fdfSJohn Baldwin 	free(cse, M_CRYPTODEV);
567c423784dSJohn Baldwin }
568c423784dSJohn Baldwin 
569c423784dSJohn Baldwin static bool
cse_delete(struct fcrypt * fcr,u_int ses)570c423784dSJohn Baldwin cse_delete(struct fcrypt *fcr, u_int ses)
571c423784dSJohn Baldwin {
572c423784dSJohn Baldwin 	struct csession *cse;
573c423784dSJohn Baldwin 
574c423784dSJohn Baldwin 	mtx_lock(&fcr->lock);
575c423784dSJohn Baldwin 	TAILQ_FOREACH(cse, &fcr->csessions, next) {
576c423784dSJohn Baldwin 		if (cse->ses == ses) {
577c423784dSJohn Baldwin 			TAILQ_REMOVE(&fcr->csessions, cse, next);
578c423784dSJohn Baldwin 			mtx_unlock(&fcr->lock);
579c423784dSJohn Baldwin 			cse_free(cse);
580c423784dSJohn Baldwin 			return (true);
581c423784dSJohn Baldwin 		}
582c423784dSJohn Baldwin 	}
583c423784dSJohn Baldwin 	mtx_unlock(&fcr->lock);
584c423784dSJohn Baldwin 	return (false);
585c423784dSJohn Baldwin }
586c423784dSJohn Baldwin 
5875425750fSJohn Baldwin static struct cryptop_data *
cod_alloc(struct csession * cse,size_t aad_len,size_t len)588688f8b82SJohn Baldwin cod_alloc(struct csession *cse, size_t aad_len, size_t len)
5895425750fSJohn Baldwin {
5905425750fSJohn Baldwin 	struct cryptop_data *cod;
5915425750fSJohn Baldwin 
592*8f3f3fdfSJohn Baldwin 	cod = malloc(sizeof(struct cryptop_data), M_CRYPTODEV, M_WAITOK |
593*8f3f3fdfSJohn Baldwin 	    M_ZERO);
5945425750fSJohn Baldwin 
5955425750fSJohn Baldwin 	cod->cse = cse;
5969b774dc0SJohn Baldwin 	if (crypto_get_params(cse->cses)->csp_flags & CSP_F_SEPARATE_AAD) {
5979b774dc0SJohn Baldwin 		if (aad_len != 0)
598*8f3f3fdfSJohn Baldwin 			cod->aad = malloc(aad_len, M_CRYPTODEV, M_WAITOK);
599*8f3f3fdfSJohn Baldwin 		cod->buf = malloc(len, M_CRYPTODEV, M_WAITOK);
6009b774dc0SJohn Baldwin 	} else
601*8f3f3fdfSJohn Baldwin 		cod->buf = malloc(aad_len + len, M_CRYPTODEV, M_WAITOK);
602ba63e5e7SJohn Baldwin 	if (crypto_get_params(cse->cses)->csp_flags & CSP_F_SEPARATE_OUTPUT)
603*8f3f3fdfSJohn Baldwin 		cod->obuf = malloc(len, M_CRYPTODEV, M_WAITOK);
6045425750fSJohn Baldwin 	return (cod);
6055425750fSJohn Baldwin }
6065425750fSJohn Baldwin 
6075425750fSJohn Baldwin static void
cod_free(struct cryptop_data * cod)6085425750fSJohn Baldwin cod_free(struct cryptop_data *cod)
6095425750fSJohn Baldwin {
6105425750fSJohn Baldwin 
611*8f3f3fdfSJohn Baldwin 	free(cod->aad, M_CRYPTODEV);
612*8f3f3fdfSJohn Baldwin 	free(cod->obuf, M_CRYPTODEV);
613*8f3f3fdfSJohn Baldwin 	free(cod->buf, M_CRYPTODEV);
614*8f3f3fdfSJohn Baldwin 	free(cod, M_CRYPTODEV);
6155425750fSJohn Baldwin }
616091d81d1SSam Leffler 
617091d81d1SSam Leffler static int
cryptodev_cb(struct cryptop * crp)618c54004c6SJohn Baldwin cryptodev_cb(struct cryptop *crp)
619c54004c6SJohn Baldwin {
620c54004c6SJohn Baldwin 	struct cryptop_data *cod = crp->crp_opaque;
621c54004c6SJohn Baldwin 
622c54004c6SJohn Baldwin 	/*
623c54004c6SJohn Baldwin 	 * Lock to ensure the wakeup() is not missed by the loops
624c54004c6SJohn Baldwin 	 * waiting on cod->done in cryptodev_op() and
625c54004c6SJohn Baldwin 	 * cryptodev_aead().
626c54004c6SJohn Baldwin 	 */
627c54004c6SJohn Baldwin 	mtx_lock(&cod->cse->lock);
628c54004c6SJohn Baldwin 	cod->done = true;
629c54004c6SJohn Baldwin 	mtx_unlock(&cod->cse->lock);
630c54004c6SJohn Baldwin 	wakeup(cod);
631c54004c6SJohn Baldwin 	return (0);
632c54004c6SJohn Baldwin }
633c54004c6SJohn Baldwin 
634c54004c6SJohn Baldwin static int
cryptodev_op(struct csession * cse,const struct crypt_op * cop)635688f8b82SJohn Baldwin cryptodev_op(struct csession *cse, const struct crypt_op *cop)
636091d81d1SSam Leffler {
637b4e0a27cSJohn Baldwin 	const struct crypto_session_params *csp;
6385425750fSJohn Baldwin 	struct cryptop_data *cod = NULL;
639091d81d1SSam Leffler 	struct cryptop *crp = NULL;
64084fea065SJohn Baldwin 	char *dst;
64157053a10SSam Leffler 	int error;
642091d81d1SSam Leffler 
64308fca7a5SJohn-Mark Gurney 	if (cop->len > 256*1024-4) {
64408fca7a5SJohn-Mark Gurney 		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
645091d81d1SSam Leffler 		return (E2BIG);
64608fca7a5SJohn-Mark Gurney 	}
647091d81d1SSam Leffler 
64861ff0a1fSJohn Baldwin 	if ((cop->len % cse->blocksize) != 0) {
64908fca7a5SJohn-Mark Gurney 		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
650091d81d1SSam Leffler 		return (EINVAL);
651e6d944d7SPawel Jakub Dawidek 	}
652091d81d1SSam Leffler 
653c0341432SJohn Baldwin 	if (cop->mac && cse->hashsize == 0) {
65408fca7a5SJohn-Mark Gurney 		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
6551b96435aSJohn Baldwin 		return (EINVAL);
656091d81d1SSam Leffler 	}
657091d81d1SSam Leffler 
658c0341432SJohn Baldwin 	/*
659c0341432SJohn Baldwin 	 * The COP_F_CIPHER_FIRST flag predates explicit session
660c0341432SJohn Baldwin 	 * modes, but the only way it was used was for EtA so allow it
661c0341432SJohn Baldwin 	 * as long as it is consistent with EtA.
662c0341432SJohn Baldwin 	 */
663c0341432SJohn Baldwin 	if (cop->flags & COP_F_CIPHER_FIRST) {
664c0341432SJohn Baldwin 		if (cop->op != COP_ENCRYPT) {
665c0341432SJohn Baldwin 			SDT_PROBE1(opencrypto, dev, ioctl, error,  __LINE__);
666c0341432SJohn Baldwin 			return (EINVAL);
667c0341432SJohn Baldwin 		}
668c0341432SJohn Baldwin 	}
669c0341432SJohn Baldwin 
670688f8b82SJohn Baldwin 	cod = cod_alloc(cse, 0, cop->len + cse->hashsize);
67184fea065SJohn Baldwin 	dst = cop->dst;
672c0341432SJohn Baldwin 
673c0341432SJohn Baldwin 	crp = crypto_getreq(cse->cses, M_WAITOK);
674c0341432SJohn Baldwin 
675c0341432SJohn Baldwin 	error = copyin(cop->src, cod->buf, cop->len);
676c0341432SJohn Baldwin 	if (error) {
67708fca7a5SJohn-Mark Gurney 		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
678091d81d1SSam Leffler 		goto bail;
67908fca7a5SJohn-Mark Gurney 	}
680c0341432SJohn Baldwin 	crp->crp_payload_start = 0;
681c0341432SJohn Baldwin 	crp->crp_payload_length = cop->len;
682c0341432SJohn Baldwin 	if (cse->hashsize)
683c0341432SJohn Baldwin 		crp->crp_digest_start = cop->len;
684091d81d1SSam Leffler 
685b4e0a27cSJohn Baldwin 	csp = crypto_get_params(cse->cses);
686b4e0a27cSJohn Baldwin 	switch (csp->csp_mode) {
687c0341432SJohn Baldwin 	case CSP_MODE_COMPRESS:
688c0341432SJohn Baldwin 		switch (cop->op) {
689c0341432SJohn Baldwin 		case COP_ENCRYPT:
690c0341432SJohn Baldwin 			crp->crp_op = CRYPTO_OP_COMPRESS;
691c0341432SJohn Baldwin 			break;
692c0341432SJohn Baldwin 		case COP_DECRYPT:
693c0341432SJohn Baldwin 			crp->crp_op = CRYPTO_OP_DECOMPRESS;
694c0341432SJohn Baldwin 			break;
695c0341432SJohn Baldwin 		default:
696c0341432SJohn Baldwin 			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
697c0341432SJohn Baldwin 			error = EINVAL;
698c0341432SJohn Baldwin 			goto bail;
699c0341432SJohn Baldwin 		}
700c0341432SJohn Baldwin 		break;
701c0341432SJohn Baldwin 	case CSP_MODE_CIPHER:
702a0cbcbb7SJohn Baldwin 		if (cop->len == 0 ||
703a0cbcbb7SJohn Baldwin 		    (cop->iv == NULL && cop->len == cse->ivsize)) {
704a0cbcbb7SJohn Baldwin 			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
705a0cbcbb7SJohn Baldwin 			error = EINVAL;
706a0cbcbb7SJohn Baldwin 			goto bail;
707a0cbcbb7SJohn Baldwin 		}
708c0341432SJohn Baldwin 		switch (cop->op) {
709c0341432SJohn Baldwin 		case COP_ENCRYPT:
710c0341432SJohn Baldwin 			crp->crp_op = CRYPTO_OP_ENCRYPT;
711c0341432SJohn Baldwin 			break;
712c0341432SJohn Baldwin 		case COP_DECRYPT:
713c0341432SJohn Baldwin 			crp->crp_op = CRYPTO_OP_DECRYPT;
714c0341432SJohn Baldwin 			break;
715c0341432SJohn Baldwin 		default:
716c0341432SJohn Baldwin 			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
717c0341432SJohn Baldwin 			error = EINVAL;
718c0341432SJohn Baldwin 			goto bail;
719c0341432SJohn Baldwin 		}
720c0341432SJohn Baldwin 		break;
721c0341432SJohn Baldwin 	case CSP_MODE_DIGEST:
722c0341432SJohn Baldwin 		switch (cop->op) {
723c0341432SJohn Baldwin 		case 0:
724c0341432SJohn Baldwin 		case COP_ENCRYPT:
725c0341432SJohn Baldwin 		case COP_DECRYPT:
726c0341432SJohn Baldwin 			crp->crp_op = CRYPTO_OP_COMPUTE_DIGEST;
727ba63e5e7SJohn Baldwin 			if (cod->obuf != NULL)
728ba63e5e7SJohn Baldwin 				crp->crp_digest_start = 0;
729c0341432SJohn Baldwin 			break;
730c0341432SJohn Baldwin 		default:
731c0341432SJohn Baldwin 			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
732c0341432SJohn Baldwin 			error = EINVAL;
733c0341432SJohn Baldwin 			goto bail;
734c0341432SJohn Baldwin 		}
735c0341432SJohn Baldwin 		break;
73670dbebeaSJohn Baldwin 	case CSP_MODE_AEAD:
73770dbebeaSJohn Baldwin 		if (cse->ivsize != 0 && cop->iv == NULL) {
73870dbebeaSJohn Baldwin 			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
73970dbebeaSJohn Baldwin 			error = EINVAL;
74070dbebeaSJohn Baldwin 			goto bail;
74170dbebeaSJohn Baldwin 		}
74270dbebeaSJohn Baldwin 		/* FALLTHROUGH */
743c0341432SJohn Baldwin 	case CSP_MODE_ETA:
744c0341432SJohn Baldwin 		switch (cop->op) {
745c0341432SJohn Baldwin 		case COP_ENCRYPT:
746c0341432SJohn Baldwin 			crp->crp_op = CRYPTO_OP_ENCRYPT |
747c0341432SJohn Baldwin 			    CRYPTO_OP_COMPUTE_DIGEST;
748c0341432SJohn Baldwin 			break;
749c0341432SJohn Baldwin 		case COP_DECRYPT:
750c0341432SJohn Baldwin 			crp->crp_op = CRYPTO_OP_DECRYPT |
751c0341432SJohn Baldwin 			    CRYPTO_OP_VERIFY_DIGEST;
752c0341432SJohn Baldwin 			break;
753c0341432SJohn Baldwin 		default:
754c0341432SJohn Baldwin 			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
755c0341432SJohn Baldwin 			error = EINVAL;
756c0341432SJohn Baldwin 			goto bail;
757c0341432SJohn Baldwin 		}
758c0341432SJohn Baldwin 		break;
759c0341432SJohn Baldwin 	default:
760c0341432SJohn Baldwin 		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
761c0341432SJohn Baldwin 		error = EINVAL;
762c0341432SJohn Baldwin 		goto bail;
763091d81d1SSam Leffler 	}
764091d81d1SSam Leffler 
765c0341432SJohn Baldwin 	crp->crp_flags = CRYPTO_F_CBIMM | (cop->flags & COP_F_BATCH);
7669c0e3d3aSJohn Baldwin 	crypto_use_buf(crp, cod->buf, cop->len + cse->hashsize);
767ba63e5e7SJohn Baldwin 	if (cod->obuf)
768ba63e5e7SJohn Baldwin 		crypto_use_output_buf(crp, cod->obuf, cop->len + cse->hashsize);
7695425750fSJohn Baldwin 	crp->crp_callback = cryptodev_cb;
7705425750fSJohn Baldwin 	crp->crp_opaque = cod;
771091d81d1SSam Leffler 
772091d81d1SSam Leffler 	if (cop->iv) {
773c0341432SJohn Baldwin 		if (cse->ivsize == 0) {
77408fca7a5SJohn-Mark Gurney 			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
775091d81d1SSam Leffler 			error = EINVAL;
776091d81d1SSam Leffler 			goto bail;
777091d81d1SSam Leffler 		}
778c0341432SJohn Baldwin 		error = copyin(cop->iv, crp->crp_iv, cse->ivsize);
779c0341432SJohn Baldwin 		if (error) {
78008fca7a5SJohn-Mark Gurney 			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
781091d81d1SSam Leffler 			goto bail;
78208fca7a5SJohn-Mark Gurney 		}
783c0341432SJohn Baldwin 		crp->crp_flags |= CRYPTO_F_IV_SEPARATE;
784c0341432SJohn Baldwin 	} else if (cse->ivsize != 0) {
7851a04f015SMark Johnston 		if (crp->crp_payload_length < cse->ivsize) {
7861a04f015SMark Johnston 			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
7871a04f015SMark Johnston 			error = EINVAL;
7881a04f015SMark Johnston 			goto bail;
7891a04f015SMark Johnston 		}
790c0341432SJohn Baldwin 		crp->crp_iv_start = 0;
791c0341432SJohn Baldwin 		crp->crp_payload_length -= cse->ivsize;
792a0cbcbb7SJohn Baldwin 		if (crp->crp_payload_length != 0)
793a0cbcbb7SJohn Baldwin 			crp->crp_payload_start = cse->ivsize;
79484fea065SJohn Baldwin 		dst += cse->ivsize;
795091d81d1SSam Leffler 	}
796091d81d1SSam Leffler 
7977c2f227aSMark Johnston 	if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
798ba63e5e7SJohn Baldwin 		error = copyin(cop->mac, cod->buf + crp->crp_digest_start,
799ba63e5e7SJohn Baldwin 		    cse->hashsize);
800c0341432SJohn Baldwin 		if (error) {
80108fca7a5SJohn-Mark Gurney 			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
802091d81d1SSam Leffler 			goto bail;
803091d81d1SSam Leffler 		}
804c0341432SJohn Baldwin 	}
805f49861e1SPawel Jakub Dawidek again:
8063569ae7fSSam Leffler 	/*
8073569ae7fSSam Leffler 	 * Let the dispatch run unlocked, then, interlock against the
8083569ae7fSSam Leffler 	 * callback before checking if the operation completed and going
8093569ae7fSSam Leffler 	 * to sleep.  This insures drivers don't inherit our lock which
8103569ae7fSSam Leffler 	 * results in a lock order reversal between crypto_dispatch forced
8113569ae7fSSam Leffler 	 * entry and the crypto_done callback into us.
8123569ae7fSSam Leffler 	 */
8133569ae7fSSam Leffler 	error = crypto_dispatch(crp);
81408fca7a5SJohn-Mark Gurney 	if (error != 0) {
81508fca7a5SJohn-Mark Gurney 		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
81608fca7a5SJohn-Mark Gurney 		goto bail;
81708fca7a5SJohn-Mark Gurney 	}
81808fca7a5SJohn-Mark Gurney 
8195425750fSJohn Baldwin 	mtx_lock(&cse->lock);
8205425750fSJohn Baldwin 	while (!cod->done)
8215425750fSJohn Baldwin 		mtx_sleep(cod, &cse->lock, PWAIT, "crydev", 0);
8225425750fSJohn Baldwin 	mtx_unlock(&cse->lock);
8235425750fSJohn Baldwin 
82408fca7a5SJohn-Mark Gurney 	if (crp->crp_etype == EAGAIN) {
82508fca7a5SJohn-Mark Gurney 		crp->crp_etype = 0;
82608fca7a5SJohn-Mark Gurney 		crp->crp_flags &= ~CRYPTO_F_DONE;
8275425750fSJohn Baldwin 		cod->done = false;
82808fca7a5SJohn-Mark Gurney 		goto again;
82908fca7a5SJohn-Mark Gurney 	}
83008fca7a5SJohn-Mark Gurney 
83108fca7a5SJohn-Mark Gurney 	if (crp->crp_etype != 0) {
83208fca7a5SJohn-Mark Gurney 		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
83308fca7a5SJohn-Mark Gurney 		error = crp->crp_etype;
83408fca7a5SJohn-Mark Gurney 		goto bail;
83508fca7a5SJohn-Mark Gurney 	}
83608fca7a5SJohn-Mark Gurney 
837c0341432SJohn Baldwin 	if (cop->dst != NULL) {
838ba63e5e7SJohn Baldwin 		error = copyout(cod->obuf != NULL ? cod->obuf :
83984fea065SJohn Baldwin 		    cod->buf + crp->crp_payload_start, dst,
840ba63e5e7SJohn Baldwin 		    crp->crp_payload_length);
841c0341432SJohn Baldwin 		if (error) {
84208fca7a5SJohn-Mark Gurney 			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
84308fca7a5SJohn-Mark Gurney 			goto bail;
84408fca7a5SJohn-Mark Gurney 		}
845c0341432SJohn Baldwin 	}
84608fca7a5SJohn-Mark Gurney 
847ba63e5e7SJohn Baldwin 	if (cop->mac != NULL && (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) == 0) {
848ba63e5e7SJohn Baldwin 		error = copyout((cod->obuf != NULL ? cod->obuf : cod->buf) +
849ba63e5e7SJohn Baldwin 		    crp->crp_digest_start, cop->mac, cse->hashsize);
850c0341432SJohn Baldwin 		if (error) {
85108fca7a5SJohn-Mark Gurney 			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
85208fca7a5SJohn-Mark Gurney 			goto bail;
85308fca7a5SJohn-Mark Gurney 		}
854c0341432SJohn Baldwin 	}
85508fca7a5SJohn-Mark Gurney 
85608fca7a5SJohn-Mark Gurney bail:
85708fca7a5SJohn-Mark Gurney 	crypto_freereq(crp);
8585425750fSJohn Baldwin 	cod_free(cod);
85908fca7a5SJohn-Mark Gurney 
86008fca7a5SJohn-Mark Gurney 	return (error);
86108fca7a5SJohn-Mark Gurney }
86208fca7a5SJohn-Mark Gurney 
86308fca7a5SJohn-Mark Gurney static int
cryptodev_aead(struct csession * cse,struct crypt_aead * caead)864688f8b82SJohn Baldwin cryptodev_aead(struct csession *cse, struct crypt_aead *caead)
86508fca7a5SJohn-Mark Gurney {
866b4e0a27cSJohn Baldwin 	const struct crypto_session_params *csp;
8675425750fSJohn Baldwin 	struct cryptop_data *cod = NULL;
86808fca7a5SJohn-Mark Gurney 	struct cryptop *crp = NULL;
86984fea065SJohn Baldwin 	char *dst;
87008fca7a5SJohn-Mark Gurney 	int error;
87108fca7a5SJohn-Mark Gurney 
872776a2127SJohn Baldwin 	if (caead->len > 256*1024-4 || caead->aadlen > 256*1024-4) {
873776a2127SJohn Baldwin 		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
87408fca7a5SJohn-Mark Gurney 		return (E2BIG);
875776a2127SJohn Baldwin 	}
87608fca7a5SJohn-Mark Gurney 
87761ff0a1fSJohn Baldwin 	if ((caead->len % cse->blocksize) != 0) {
87861ff0a1fSJohn Baldwin 		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
87961ff0a1fSJohn Baldwin 		return (EINVAL);
88061ff0a1fSJohn Baldwin 	}
88161ff0a1fSJohn Baldwin 
88261ff0a1fSJohn Baldwin 	if (cse->hashsize == 0 || caead->tag == NULL) {
883776a2127SJohn Baldwin 		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
88408fca7a5SJohn-Mark Gurney 		return (EINVAL);
885776a2127SJohn Baldwin 	}
88608fca7a5SJohn-Mark Gurney 
887cc05c7d2SJohn Baldwin 	/*
888c0341432SJohn Baldwin 	 * The COP_F_CIPHER_FIRST flag predates explicit session
889c0341432SJohn Baldwin 	 * modes, but the only way it was used was for EtA so allow it
890c0341432SJohn Baldwin 	 * as long as it is consistent with EtA.
891cc05c7d2SJohn Baldwin 	 */
892c0341432SJohn Baldwin 	if (caead->flags & COP_F_CIPHER_FIRST) {
893c0341432SJohn Baldwin 		if (caead->op != COP_ENCRYPT) {
894c0341432SJohn Baldwin 			SDT_PROBE1(opencrypto, dev, ioctl, error,  __LINE__);
895c0341432SJohn Baldwin 			return (EINVAL);
896c0341432SJohn Baldwin 		}
897c0341432SJohn Baldwin 	}
89808fca7a5SJohn-Mark Gurney 
899688f8b82SJohn Baldwin 	cod = cod_alloc(cse, caead->aadlen, caead->len + cse->hashsize);
90084fea065SJohn Baldwin 	dst = caead->dst;
90108fca7a5SJohn-Mark Gurney 
902c0341432SJohn Baldwin 	crp = crypto_getreq(cse->cses, M_WAITOK);
90308fca7a5SJohn-Mark Gurney 
9049b774dc0SJohn Baldwin 	if (cod->aad != NULL)
9059b774dc0SJohn Baldwin 		error = copyin(caead->aad, cod->aad, caead->aadlen);
9069b774dc0SJohn Baldwin 	else
907c0341432SJohn Baldwin 		error = copyin(caead->aad, cod->buf, caead->aadlen);
908c0341432SJohn Baldwin 	if (error) {
909c0341432SJohn Baldwin 		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
910c0341432SJohn Baldwin 		goto bail;
911c0341432SJohn Baldwin 	}
9129b774dc0SJohn Baldwin 	crp->crp_aad = cod->aad;
913c0341432SJohn Baldwin 	crp->crp_aad_start = 0;
914c0341432SJohn Baldwin 	crp->crp_aad_length = caead->aadlen;
91508fca7a5SJohn-Mark Gurney 
9169b774dc0SJohn Baldwin 	if (cod->aad != NULL)
9179b774dc0SJohn Baldwin 		crp->crp_payload_start = 0;
9189b774dc0SJohn Baldwin 	else
9199b774dc0SJohn Baldwin 		crp->crp_payload_start = caead->aadlen;
9209b774dc0SJohn Baldwin 	error = copyin(caead->src, cod->buf + crp->crp_payload_start,
9219b774dc0SJohn Baldwin 	    caead->len);
922c0341432SJohn Baldwin 	if (error) {
923c0341432SJohn Baldwin 		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
924c0341432SJohn Baldwin 		goto bail;
925c0341432SJohn Baldwin 	}
926c0341432SJohn Baldwin 	crp->crp_payload_length = caead->len;
927ba63e5e7SJohn Baldwin 	if (caead->op == COP_ENCRYPT && cod->obuf != NULL)
9289b774dc0SJohn Baldwin 		crp->crp_digest_start = crp->crp_payload_output_start +
9299b774dc0SJohn Baldwin 		    caead->len;
930ba63e5e7SJohn Baldwin 	else
9319b774dc0SJohn Baldwin 		crp->crp_digest_start = crp->crp_payload_start + caead->len;
932c0341432SJohn Baldwin 
933b4e0a27cSJohn Baldwin 	csp = crypto_get_params(cse->cses);
934b4e0a27cSJohn Baldwin 	switch (csp->csp_mode) {
935c0341432SJohn Baldwin 	case CSP_MODE_AEAD:
936c0341432SJohn Baldwin 	case CSP_MODE_ETA:
937c0341432SJohn Baldwin 		switch (caead->op) {
938c0341432SJohn Baldwin 		case COP_ENCRYPT:
939c0341432SJohn Baldwin 			crp->crp_op = CRYPTO_OP_ENCRYPT |
940c0341432SJohn Baldwin 			    CRYPTO_OP_COMPUTE_DIGEST;
941c0341432SJohn Baldwin 			break;
942c0341432SJohn Baldwin 		case COP_DECRYPT:
943c0341432SJohn Baldwin 			crp->crp_op = CRYPTO_OP_DECRYPT |
944c0341432SJohn Baldwin 			    CRYPTO_OP_VERIFY_DIGEST;
945c0341432SJohn Baldwin 			break;
946c0341432SJohn Baldwin 		default:
947c0341432SJohn Baldwin 			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
948c0341432SJohn Baldwin 			error = EINVAL;
949c0341432SJohn Baldwin 			goto bail;
950c0341432SJohn Baldwin 		}
951c0341432SJohn Baldwin 		break;
952c0341432SJohn Baldwin 	default:
953c0341432SJohn Baldwin 		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
954c0341432SJohn Baldwin 		error = EINVAL;
955c0341432SJohn Baldwin 		goto bail;
956c0341432SJohn Baldwin 	}
957c0341432SJohn Baldwin 
958c0341432SJohn Baldwin 	crp->crp_flags = CRYPTO_F_CBIMM | (caead->flags & COP_F_BATCH);
9599b774dc0SJohn Baldwin 	crypto_use_buf(crp, cod->buf, crp->crp_payload_start + caead->len +
9609c0e3d3aSJohn Baldwin 	    cse->hashsize);
961ba63e5e7SJohn Baldwin 	if (cod->obuf != NULL)
962ba63e5e7SJohn Baldwin 		crypto_use_output_buf(crp, cod->obuf, caead->len +
963ba63e5e7SJohn Baldwin 		    cse->hashsize);
9645425750fSJohn Baldwin 	crp->crp_callback = cryptodev_cb;
9655425750fSJohn Baldwin 	crp->crp_opaque = cod;
96608fca7a5SJohn-Mark Gurney 
96708fca7a5SJohn-Mark Gurney 	if (caead->iv) {
968c0341432SJohn Baldwin 		/*
969c0341432SJohn Baldwin 		 * Permit a 16-byte IV for AES-XTS, but only use the
970c0341432SJohn Baldwin 		 * first 8 bytes as a block number.
971c0341432SJohn Baldwin 		 */
972b4e0a27cSJohn Baldwin 		if (csp->csp_mode == CSP_MODE_ETA &&
973b4e0a27cSJohn Baldwin 		    csp->csp_cipher_alg == CRYPTO_AES_XTS &&
974b4e0a27cSJohn Baldwin 		    caead->ivlen == AES_BLOCK_LEN)
975c0341432SJohn Baldwin 			caead->ivlen = AES_XTS_IV_LEN;
976c0341432SJohn Baldwin 
9771a04f015SMark Johnston 		if (cse->ivsize == 0) {
9781a04f015SMark Johnston 			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
9791a04f015SMark Johnston 			error = EINVAL;
9801a04f015SMark Johnston 			goto bail;
9811a04f015SMark Johnston 		}
982c0341432SJohn Baldwin 		if (caead->ivlen != cse->ivsize) {
98308fca7a5SJohn-Mark Gurney 			error = EINVAL;
984776a2127SJohn Baldwin 			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
98508fca7a5SJohn-Mark Gurney 			goto bail;
98608fca7a5SJohn-Mark Gurney 		}
98708fca7a5SJohn-Mark Gurney 
988c0341432SJohn Baldwin 		error = copyin(caead->iv, crp->crp_iv, cse->ivsize);
989c0341432SJohn Baldwin 		if (error) {
990776a2127SJohn Baldwin 			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
99108fca7a5SJohn-Mark Gurney 			goto bail;
992776a2127SJohn Baldwin 		}
993c0341432SJohn Baldwin 		crp->crp_flags |= CRYPTO_F_IV_SEPARATE;
99408fca7a5SJohn-Mark Gurney 	} else {
9951a04f015SMark Johnston 		error = EINVAL;
9961a04f015SMark Johnston 		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
9971a04f015SMark Johnston 		goto bail;
99808fca7a5SJohn-Mark Gurney 	}
99908fca7a5SJohn-Mark Gurney 
1000ba63e5e7SJohn Baldwin 	if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
1001ba63e5e7SJohn Baldwin 		error = copyin(caead->tag, cod->buf + crp->crp_digest_start,
1002c0341432SJohn Baldwin 		    cse->hashsize);
1003c0341432SJohn Baldwin 		if (error) {
1004776a2127SJohn Baldwin 			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
100508fca7a5SJohn-Mark Gurney 			goto bail;
1006776a2127SJohn Baldwin 		}
1007ba63e5e7SJohn Baldwin 	}
100808fca7a5SJohn-Mark Gurney again:
100908fca7a5SJohn-Mark Gurney 	/*
101008fca7a5SJohn-Mark Gurney 	 * Let the dispatch run unlocked, then, interlock against the
101108fca7a5SJohn-Mark Gurney 	 * callback before checking if the operation completed and going
101208fca7a5SJohn-Mark Gurney 	 * to sleep.  This insures drivers don't inherit our lock which
101308fca7a5SJohn-Mark Gurney 	 * results in a lock order reversal between crypto_dispatch forced
101408fca7a5SJohn-Mark Gurney 	 * entry and the crypto_done callback into us.
101508fca7a5SJohn-Mark Gurney 	 */
101608fca7a5SJohn-Mark Gurney 	error = crypto_dispatch(crp);
1017776a2127SJohn Baldwin 	if (error != 0) {
1018776a2127SJohn Baldwin 		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
1019091d81d1SSam Leffler 		goto bail;
1020776a2127SJohn Baldwin 	}
1021091d81d1SSam Leffler 
10225425750fSJohn Baldwin 	mtx_lock(&cse->lock);
10235425750fSJohn Baldwin 	while (!cod->done)
10245425750fSJohn Baldwin 		mtx_sleep(cod, &cse->lock, PWAIT, "crydev", 0);
10255425750fSJohn Baldwin 	mtx_unlock(&cse->lock);
10265425750fSJohn Baldwin 
1027f49861e1SPawel Jakub Dawidek 	if (crp->crp_etype == EAGAIN) {
1028f49861e1SPawel Jakub Dawidek 		crp->crp_etype = 0;
1029f49861e1SPawel Jakub Dawidek 		crp->crp_flags &= ~CRYPTO_F_DONE;
10305425750fSJohn Baldwin 		cod->done = false;
1031f49861e1SPawel Jakub Dawidek 		goto again;
1032f49861e1SPawel Jakub Dawidek 	}
1033f49861e1SPawel Jakub Dawidek 
1034091d81d1SSam Leffler 	if (crp->crp_etype != 0) {
1035091d81d1SSam Leffler 		error = crp->crp_etype;
1036776a2127SJohn Baldwin 		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
1037091d81d1SSam Leffler 		goto bail;
1038091d81d1SSam Leffler 	}
1039091d81d1SSam Leffler 
1040c0341432SJohn Baldwin 	if (caead->dst != NULL) {
1041ba63e5e7SJohn Baldwin 		error = copyout(cod->obuf != NULL ? cod->obuf :
104284fea065SJohn Baldwin 		    cod->buf + crp->crp_payload_start, dst,
1043ba63e5e7SJohn Baldwin 		    crp->crp_payload_length);
1044c0341432SJohn Baldwin 		if (error) {
1045776a2127SJohn Baldwin 			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
1046091d81d1SSam Leffler 			goto bail;
1047776a2127SJohn Baldwin 		}
1048c0341432SJohn Baldwin 	}
1049091d81d1SSam Leffler 
1050ba63e5e7SJohn Baldwin 	if ((crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) == 0) {
1051ba63e5e7SJohn Baldwin 		error = copyout((cod->obuf != NULL ? cod->obuf : cod->buf) +
1052ba63e5e7SJohn Baldwin 		    crp->crp_digest_start, caead->tag, cse->hashsize);
1053c0341432SJohn Baldwin 		if (error) {
1054776a2127SJohn Baldwin 			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
1055091d81d1SSam Leffler 			goto bail;
1056776a2127SJohn Baldwin 		}
1057ba63e5e7SJohn Baldwin 	}
1058091d81d1SSam Leffler 
1059091d81d1SSam Leffler bail:
1060091d81d1SSam Leffler 	crypto_freereq(crp);
10615425750fSJohn Baldwin 	cod_free(cod);
1062091d81d1SSam Leffler 
1063091d81d1SSam Leffler 	return (error);
1064091d81d1SSam Leffler }
1065091d81d1SSam Leffler 
10666810ad6fSSam Leffler static int
cryptodev_find(struct crypt_find_op * find)10676810ad6fSSam Leffler cryptodev_find(struct crypt_find_op *find)
10686810ad6fSSam Leffler {
10696810ad6fSSam Leffler 	device_t dev;
107008fca7a5SJohn-Mark Gurney 	size_t fnlen = sizeof find->name;
10716810ad6fSSam Leffler 
10726810ad6fSSam Leffler 	if (find->crid != -1) {
10736810ad6fSSam Leffler 		dev = crypto_find_device_byhid(find->crid);
10746810ad6fSSam Leffler 		if (dev == NULL)
10756810ad6fSSam Leffler 			return (ENOENT);
107608fca7a5SJohn-Mark Gurney 		strncpy(find->name, device_get_nameunit(dev), fnlen);
107708fca7a5SJohn-Mark Gurney 		find->name[fnlen - 1] = '\x0';
10786810ad6fSSam Leffler 	} else {
107908fca7a5SJohn-Mark Gurney 		find->name[fnlen - 1] = '\x0';
10806810ad6fSSam Leffler 		find->crid = crypto_find_driver(find->name);
10816810ad6fSSam Leffler 		if (find->crid == -1)
10826810ad6fSSam Leffler 			return (ENOENT);
10836810ad6fSSam Leffler 	}
10846810ad6fSSam Leffler 	return (0);
10856810ad6fSSam Leffler }
10866810ad6fSSam Leffler 
1087688f8b82SJohn Baldwin static void
fcrypt_dtor(void * data)1088688f8b82SJohn Baldwin fcrypt_dtor(void *data)
1089688f8b82SJohn Baldwin {
1090688f8b82SJohn Baldwin 	struct fcrypt *fcr = data;
1091688f8b82SJohn Baldwin 	struct csession *cse;
1092688f8b82SJohn Baldwin 
1093688f8b82SJohn Baldwin 	while ((cse = TAILQ_FIRST(&fcr->csessions))) {
1094688f8b82SJohn Baldwin 		TAILQ_REMOVE(&fcr->csessions, cse, next);
1095688f8b82SJohn Baldwin 		KASSERT(refcount_load(&cse->refs) == 1,
1096688f8b82SJohn Baldwin 		    ("%s: crypto session %p with %d refs", __func__, cse,
1097688f8b82SJohn Baldwin 		    refcount_load(&cse->refs)));
1098688f8b82SJohn Baldwin 		cse_free(cse);
1099688f8b82SJohn Baldwin 	}
1100688f8b82SJohn Baldwin 	mtx_destroy(&fcr->lock);
1101*8f3f3fdfSJohn Baldwin 	free(fcr, M_CRYPTODEV);
1102688f8b82SJohn Baldwin }
1103688f8b82SJohn Baldwin 
1104f5074addSJohn Baldwin static int
crypto_open(struct cdev * dev,int oflags,int devtype,struct thread * td)1105688f8b82SJohn Baldwin crypto_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
1106688f8b82SJohn Baldwin {
1107688f8b82SJohn Baldwin 	struct fcrypt *fcr;
1108688f8b82SJohn Baldwin 	int error;
1109688f8b82SJohn Baldwin 
1110*8f3f3fdfSJohn Baldwin 	fcr = malloc(sizeof(struct fcrypt), M_CRYPTODEV, M_WAITOK | M_ZERO);
1111688f8b82SJohn Baldwin 	TAILQ_INIT(&fcr->csessions);
1112688f8b82SJohn Baldwin 	mtx_init(&fcr->lock, "fcrypt", NULL, MTX_DEF);
1113688f8b82SJohn Baldwin 	error = devfs_set_cdevpriv(fcr, fcrypt_dtor);
1114688f8b82SJohn Baldwin 	if (error)
1115688f8b82SJohn Baldwin 		fcrypt_dtor(fcr);
1116688f8b82SJohn Baldwin 	return (error);
1117688f8b82SJohn Baldwin }
1118688f8b82SJohn Baldwin 
1119688f8b82SJohn Baldwin static int
crypto_ioctl(struct cdev * dev,u_long cmd,caddr_t data,int flag,struct thread * td)1120688f8b82SJohn Baldwin crypto_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag,
1121688f8b82SJohn Baldwin     struct thread *td)
1122f5074addSJohn Baldwin {
1123688f8b82SJohn Baldwin 	struct fcrypt *fcr;
1124f5074addSJohn Baldwin 	struct csession *cse;
1125f5074addSJohn Baldwin 	struct session2_op *sop;
1126f5074addSJohn Baldwin 	struct crypt_op *cop;
1127f5074addSJohn Baldwin 	struct crypt_aead *caead;
1128f5074addSJohn Baldwin 	uint32_t ses;
1129f5074addSJohn Baldwin 	int error = 0;
1130f5074addSJohn Baldwin 	union {
1131f5074addSJohn Baldwin 		struct session2_op sopc;
1132f5074addSJohn Baldwin #ifdef COMPAT_FREEBSD32
1133f5074addSJohn Baldwin 		struct crypt_op copc;
1134f5074addSJohn Baldwin 		struct crypt_aead aeadc;
1135f5074addSJohn Baldwin #endif
1136f5074addSJohn Baldwin 	} thunk;
1137f5074addSJohn Baldwin #ifdef COMPAT_FREEBSD32
1138f5074addSJohn Baldwin 	u_long cmd32;
1139f5074addSJohn Baldwin 	void *data32;
1140f5074addSJohn Baldwin 
1141f5074addSJohn Baldwin 	cmd32 = 0;
1142f5074addSJohn Baldwin 	data32 = NULL;
1143f5074addSJohn Baldwin 	switch (cmd) {
1144f5074addSJohn Baldwin 	case CIOCGSESSION32:
1145f5074addSJohn Baldwin 		cmd32 = cmd;
1146f5074addSJohn Baldwin 		data32 = data;
1147f5074addSJohn Baldwin 		cmd = CIOCGSESSION;
1148688f8b82SJohn Baldwin 		data = (void *)&thunk.sopc;
1149f5074addSJohn Baldwin 		session_op_from_32((struct session_op32 *)data32, &thunk.sopc);
1150f5074addSJohn Baldwin 		break;
1151f5074addSJohn Baldwin 	case CIOCGSESSION232:
1152f5074addSJohn Baldwin 		cmd32 = cmd;
1153f5074addSJohn Baldwin 		data32 = data;
1154f5074addSJohn Baldwin 		cmd = CIOCGSESSION2;
1155688f8b82SJohn Baldwin 		data = (void *)&thunk.sopc;
1156f5074addSJohn Baldwin 		session2_op_from_32((struct session2_op32 *)data32,
1157f5074addSJohn Baldwin 		    &thunk.sopc);
1158f5074addSJohn Baldwin 		break;
1159f5074addSJohn Baldwin 	case CIOCCRYPT32:
1160f5074addSJohn Baldwin 		cmd32 = cmd;
1161f5074addSJohn Baldwin 		data32 = data;
1162f5074addSJohn Baldwin 		cmd = CIOCCRYPT;
1163688f8b82SJohn Baldwin 		data = (void *)&thunk.copc;
1164f5074addSJohn Baldwin 		crypt_op_from_32((struct crypt_op32 *)data32, &thunk.copc);
1165f5074addSJohn Baldwin 		break;
1166f5074addSJohn Baldwin 	case CIOCCRYPTAEAD32:
1167f5074addSJohn Baldwin 		cmd32 = cmd;
1168f5074addSJohn Baldwin 		data32 = data;
1169f5074addSJohn Baldwin 		cmd = CIOCCRYPTAEAD;
1170688f8b82SJohn Baldwin 		data = (void *)&thunk.aeadc;
1171f5074addSJohn Baldwin 		crypt_aead_from_32((struct crypt_aead32 *)data32, &thunk.aeadc);
1172f5074addSJohn Baldwin 		break;
1173f5074addSJohn Baldwin 	}
1174f5074addSJohn Baldwin #endif
1175f5074addSJohn Baldwin 
1176688f8b82SJohn Baldwin 	devfs_get_cdevpriv((void **)&fcr);
1177688f8b82SJohn Baldwin 
1178f5074addSJohn Baldwin 	switch (cmd) {
1179688f8b82SJohn Baldwin #ifdef COMPAT_FREEBSD12
1180688f8b82SJohn Baldwin 	case CRIOGET:
1181688f8b82SJohn Baldwin 		/*
1182688f8b82SJohn Baldwin 		 * NB: This may fail in cases that the old
1183688f8b82SJohn Baldwin 		 * implementation did not if the current process has
1184688f8b82SJohn Baldwin 		 * restricted filesystem access (e.g. running in a
1185688f8b82SJohn Baldwin 		 * jail that does not expose /dev/crypto or in
1186688f8b82SJohn Baldwin 		 * capability mode).
1187688f8b82SJohn Baldwin 		 */
1188688f8b82SJohn Baldwin 		error = kern_openat(td, AT_FDCWD, "/dev/crypto", UIO_SYSSPACE,
1189688f8b82SJohn Baldwin 		    O_RDWR, 0);
1190688f8b82SJohn Baldwin 		if (error == 0)
1191688f8b82SJohn Baldwin 			*(uint32_t *)data = td->td_retval[0];
1192688f8b82SJohn Baldwin 		break;
1193688f8b82SJohn Baldwin #endif
1194f5074addSJohn Baldwin 	case CIOCGSESSION:
1195f5074addSJohn Baldwin 	case CIOCGSESSION2:
1196f5074addSJohn Baldwin 		if (cmd == CIOCGSESSION) {
1197688f8b82SJohn Baldwin 			session2_op_from_op((void *)data, &thunk.sopc);
1198f5074addSJohn Baldwin 			sop = &thunk.sopc;
1199f5074addSJohn Baldwin 		} else
1200f5074addSJohn Baldwin 			sop = (struct session2_op *)data;
1201f5074addSJohn Baldwin 
1202c423784dSJohn Baldwin 		error = cse_create(fcr, sop);
1203f5074addSJohn Baldwin 		if (cmd == CIOCGSESSION && error == 0)
1204688f8b82SJohn Baldwin 			session2_op_to_op(sop, (void *)data);
1205f5074addSJohn Baldwin 		break;
1206f5074addSJohn Baldwin 	case CIOCFSESSION:
1207f5074addSJohn Baldwin 		ses = *(uint32_t *)data;
1208c423784dSJohn Baldwin 		if (!cse_delete(fcr, ses)) {
1209f5074addSJohn Baldwin 			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
1210f5074addSJohn Baldwin 			return (EINVAL);
1211f5074addSJohn Baldwin 		}
1212f5074addSJohn Baldwin 		break;
1213f5074addSJohn Baldwin 	case CIOCCRYPT:
1214f5074addSJohn Baldwin 		cop = (struct crypt_op *)data;
1215c423784dSJohn Baldwin 		cse = cse_find(fcr, cop->ses);
1216f5074addSJohn Baldwin 		if (cse == NULL) {
1217f5074addSJohn Baldwin 			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
1218f5074addSJohn Baldwin 			return (EINVAL);
1219f5074addSJohn Baldwin 		}
1220688f8b82SJohn Baldwin 		error = cryptodev_op(cse, cop);
1221c423784dSJohn Baldwin 		cse_free(cse);
1222f5074addSJohn Baldwin 		break;
1223f5074addSJohn Baldwin 	case CIOCFINDDEV:
1224f5074addSJohn Baldwin 		error = cryptodev_find((struct crypt_find_op *)data);
1225f5074addSJohn Baldwin 		break;
1226f5074addSJohn Baldwin 	case CIOCCRYPTAEAD:
1227f5074addSJohn Baldwin 		caead = (struct crypt_aead *)data;
1228c423784dSJohn Baldwin 		cse = cse_find(fcr, caead->ses);
1229f5074addSJohn Baldwin 		if (cse == NULL) {
1230f5074addSJohn Baldwin 			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
1231f5074addSJohn Baldwin 			return (EINVAL);
1232f5074addSJohn Baldwin 		}
1233688f8b82SJohn Baldwin 		error = cryptodev_aead(cse, caead);
1234c423784dSJohn Baldwin 		cse_free(cse);
1235f5074addSJohn Baldwin 		break;
1236f5074addSJohn Baldwin 	default:
1237f5074addSJohn Baldwin 		error = EINVAL;
1238f5074addSJohn Baldwin 		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
1239f5074addSJohn Baldwin 		break;
1240f5074addSJohn Baldwin 	}
1241f5074addSJohn Baldwin 
1242f5074addSJohn Baldwin #ifdef COMPAT_FREEBSD32
1243f5074addSJohn Baldwin 	switch (cmd32) {
1244f5074addSJohn Baldwin 	case CIOCGSESSION32:
1245f5074addSJohn Baldwin 		if (error == 0)
1246688f8b82SJohn Baldwin 			session_op_to_32((void *)data, data32);
1247f5074addSJohn Baldwin 		break;
1248f5074addSJohn Baldwin 	case CIOCGSESSION232:
1249f5074addSJohn Baldwin 		if (error == 0)
1250688f8b82SJohn Baldwin 			session2_op_to_32((void *)data, data32);
1251f5074addSJohn Baldwin 		break;
1252f5074addSJohn Baldwin 	case CIOCCRYPT32:
1253f5074addSJohn Baldwin 		if (error == 0)
1254688f8b82SJohn Baldwin 			crypt_op_to_32((void *)data, data32);
1255f5074addSJohn Baldwin 		break;
1256f5074addSJohn Baldwin 	case CIOCCRYPTAEAD32:
1257f5074addSJohn Baldwin 		if (error == 0)
1258688f8b82SJohn Baldwin 			crypt_aead_to_32((void *)data, data32);
1259f5074addSJohn Baldwin 		break;
1260f5074addSJohn Baldwin 	}
1261f5074addSJohn Baldwin #endif
1262f5074addSJohn Baldwin 	return (error);
1263f5074addSJohn Baldwin }
1264f5074addSJohn Baldwin 
1265091d81d1SSam Leffler static struct cdevsw crypto_cdevsw = {
1266dc08ffecSPoul-Henning Kamp 	.d_version =	D_VERSION,
1267688f8b82SJohn Baldwin 	.d_open =	crypto_open,
1268688f8b82SJohn Baldwin 	.d_ioctl =	crypto_ioctl,
12697ac40f5fSPoul-Henning Kamp 	.d_name =	"crypto",
1270091d81d1SSam Leffler };
127189c9c53dSPoul-Henning Kamp static struct cdev *crypto_dev;
1272091d81d1SSam Leffler 
1273091d81d1SSam Leffler /*
1274091d81d1SSam Leffler  * Initialization code, both for static and dynamic loading.
1275091d81d1SSam Leffler  */
1276091d81d1SSam Leffler static int
cryptodev_modevent(module_t mod,int type,void * unused)1277091d81d1SSam Leffler cryptodev_modevent(module_t mod, int type, void *unused)
1278091d81d1SSam Leffler {
1279091d81d1SSam Leffler 	switch (type) {
1280091d81d1SSam Leffler 	case MOD_LOAD:
1281091d81d1SSam Leffler 		if (bootverbose)
1282091d81d1SSam Leffler 			printf("crypto: <crypto device>\n");
128395563048SSam Leffler 		crypto_dev = make_dev(&crypto_cdevsw, 0,
1284091d81d1SSam Leffler 				      UID_ROOT, GID_WHEEL, 0666,
1285091d81d1SSam Leffler 				      "crypto");
1286091d81d1SSam Leffler 		return 0;
1287091d81d1SSam Leffler 	case MOD_UNLOAD:
1288091d81d1SSam Leffler 		/*XXX disallow if active sessions */
1289091d81d1SSam Leffler 		destroy_dev(crypto_dev);
1290091d81d1SSam Leffler 		return 0;
1291091d81d1SSam Leffler 	}
1292091d81d1SSam Leffler 	return EINVAL;
1293091d81d1SSam Leffler }
1294091d81d1SSam Leffler 
1295091d81d1SSam Leffler static moduledata_t cryptodev_mod = {
1296091d81d1SSam Leffler 	"cryptodev",
1297091d81d1SSam Leffler 	cryptodev_modevent,
12989823d527SKevin Lo 	0
1299091d81d1SSam Leffler };
1300091d81d1SSam Leffler MODULE_VERSION(cryptodev, 1);
1301091d81d1SSam Leffler DECLARE_MODULE(cryptodev, cryptodev_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
1302f544a528SMark Murray MODULE_DEPEND(cryptodev, crypto, 1, 1, 1);
130351b4ccb4SWojciech A. Koszek MODULE_DEPEND(cryptodev, zlib, 1, 1, 1);
1304