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