xref: /freebsd/sys/opencrypto/cryptosoft.c (revision 9ebbebe4f763addd4e6269a2b4b76688f5f2fb04)
1091d81d1SSam Leffler /*	$OpenBSD: cryptosoft.c,v 1.35 2002/04/26 08:43:50 deraadt Exp $	*/
2091d81d1SSam Leffler 
360727d8bSWarner Losh /*-
4091d81d1SSam Leffler  * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
56810ad6fSSam Leffler  * Copyright (c) 2002-2006 Sam Leffler, Errno Consulting
6091d81d1SSam Leffler  *
7091d81d1SSam Leffler  * This code was written by Angelos D. Keromytis in Athens, Greece, in
8091d81d1SSam Leffler  * February 2000. Network Security Technologies Inc. (NSTI) kindly
9091d81d1SSam Leffler  * supported the development of this code.
10091d81d1SSam Leffler  *
11091d81d1SSam Leffler  * Copyright (c) 2000, 2001 Angelos D. Keromytis
1208fca7a5SJohn-Mark Gurney  * Copyright (c) 2014 The FreeBSD Foundation
1308fca7a5SJohn-Mark Gurney  * All rights reserved.
1408fca7a5SJohn-Mark Gurney  *
1508fca7a5SJohn-Mark Gurney  * Portions of this software were developed by John-Mark Gurney
1608fca7a5SJohn-Mark Gurney  * under sponsorship of the FreeBSD Foundation and
1708fca7a5SJohn-Mark Gurney  * Rubicon Communications, LLC (Netgate).
18091d81d1SSam Leffler  *
19091d81d1SSam Leffler  * Permission to use, copy, and modify this software with or without fee
20091d81d1SSam Leffler  * is hereby granted, provided that this entire notice is included in
21091d81d1SSam Leffler  * all source code copies of any software which is or includes a copy or
22091d81d1SSam Leffler  * modification of this software.
23091d81d1SSam Leffler  *
24091d81d1SSam Leffler  * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
25091d81d1SSam Leffler  * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
26091d81d1SSam Leffler  * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
27091d81d1SSam Leffler  * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
28091d81d1SSam Leffler  * PURPOSE.
29091d81d1SSam Leffler  */
30091d81d1SSam Leffler 
312c446514SDavid E. O'Brien #include <sys/cdefs.h>
322c446514SDavid E. O'Brien __FBSDID("$FreeBSD$");
332c446514SDavid E. O'Brien 
34091d81d1SSam Leffler #include <sys/param.h>
35091d81d1SSam Leffler #include <sys/systm.h>
36091d81d1SSam Leffler #include <sys/malloc.h>
37091d81d1SSam Leffler #include <sys/mbuf.h>
386810ad6fSSam Leffler #include <sys/module.h>
39091d81d1SSam Leffler #include <sys/sysctl.h>
40091d81d1SSam Leffler #include <sys/errno.h>
41091d81d1SSam Leffler #include <sys/random.h>
42091d81d1SSam Leffler #include <sys/kernel.h>
43091d81d1SSam Leffler #include <sys/uio.h>
44109919c6SBenno Rice #include <sys/lock.h>
45109919c6SBenno Rice #include <sys/rwlock.h>
4608fca7a5SJohn-Mark Gurney #include <sys/endian.h>
4708fca7a5SJohn-Mark Gurney #include <sys/limits.h>
48091d81d1SSam Leffler 
49091d81d1SSam Leffler #include <crypto/blowfish/blowfish.h>
50091d81d1SSam Leffler #include <crypto/sha1.h>
51091d81d1SSam Leffler #include <opencrypto/rmd160.h>
529f65b10bSHajimu UMEMOTO #include <opencrypto/cast.h>
53091d81d1SSam Leffler #include <opencrypto/skipjack.h>
54091d81d1SSam Leffler #include <sys/md5.h>
55091d81d1SSam Leffler 
56091d81d1SSam Leffler #include <opencrypto/cryptodev.h>
57091d81d1SSam Leffler #include <opencrypto/cryptosoft.h>
58091d81d1SSam Leffler #include <opencrypto/xform.h>
59091d81d1SSam Leffler 
606810ad6fSSam Leffler #include <sys/kobj.h>
616810ad6fSSam Leffler #include <sys/bus.h>
626810ad6fSSam Leffler #include "cryptodev_if.h"
63091d81d1SSam Leffler 
646810ad6fSSam Leffler static	int32_t swcr_id;
656810ad6fSSam Leffler 
666810ad6fSSam Leffler u_int8_t hmac_ipad_buffer[HMAC_MAX_BLOCK_LEN];
676810ad6fSSam Leffler u_int8_t hmac_opad_buffer[HMAC_MAX_BLOCK_LEN];
68091d81d1SSam Leffler 
69091d81d1SSam Leffler static	int swcr_encdec(struct cryptodesc *, struct swcr_data *, caddr_t, int);
70f34a967bSPawel Jakub Dawidek static	int swcr_authcompute(struct cryptodesc *, struct swcr_data *, caddr_t, int);
7108fca7a5SJohn-Mark Gurney static	int swcr_authenc(struct cryptop *crp);
72091d81d1SSam Leffler static	int swcr_compdec(struct cryptodesc *, struct swcr_data *, caddr_t, int);
731b0909d5SConrad Meyer static	void swcr_freesession(device_t dev, crypto_session_t cses);
74091d81d1SSam Leffler 
75091d81d1SSam Leffler /*
76091d81d1SSam Leffler  * Apply a symmetric encryption/decryption algorithm.
77091d81d1SSam Leffler  */
78091d81d1SSam Leffler static int
79091d81d1SSam Leffler swcr_encdec(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf,
80f34a967bSPawel Jakub Dawidek     int flags)
81091d81d1SSam Leffler {
825d7ae54aSConrad Meyer 	unsigned char iv[EALG_MAX_BLOCK_LEN], blk[EALG_MAX_BLOCK_LEN];
8308fca7a5SJohn-Mark Gurney 	unsigned char *ivp, *nivp, iv2[EALG_MAX_BLOCK_LEN];
84091d81d1SSam Leffler 	struct enc_xform *exf;
8508fca7a5SJohn-Mark Gurney 	int i, j, k, blks, ind, count, ivlen;
8608fca7a5SJohn-Mark Gurney 	struct uio *uio, uiolcl;
8708fca7a5SJohn-Mark Gurney 	struct iovec iovlcl[4];
8808fca7a5SJohn-Mark Gurney 	struct iovec *iov;
8908fca7a5SJohn-Mark Gurney 	int iovcnt, iovalloc;
9008fca7a5SJohn-Mark Gurney 	int error;
9108fca7a5SJohn-Mark Gurney 
9208fca7a5SJohn-Mark Gurney 	error = 0;
93091d81d1SSam Leffler 
94091d81d1SSam Leffler 	exf = sw->sw_exf;
95091d81d1SSam Leffler 	blks = exf->blocksize;
9608fca7a5SJohn-Mark Gurney 	ivlen = exf->ivsize;
97091d81d1SSam Leffler 
98091d81d1SSam Leffler 	/* Check for non-padded data */
99091d81d1SSam Leffler 	if (crd->crd_len % blks)
100091d81d1SSam Leffler 		return EINVAL;
101091d81d1SSam Leffler 
10208fca7a5SJohn-Mark Gurney 	if (crd->crd_alg == CRYPTO_AES_ICM &&
10308fca7a5SJohn-Mark Gurney 	    (crd->crd_flags & CRD_F_IV_EXPLICIT) == 0)
10408fca7a5SJohn-Mark Gurney 		return (EINVAL);
10508fca7a5SJohn-Mark Gurney 
106091d81d1SSam Leffler 	/* Initialize the IV */
107091d81d1SSam Leffler 	if (crd->crd_flags & CRD_F_ENCRYPT) {
108091d81d1SSam Leffler 		/* IV explicitly provided ? */
109091d81d1SSam Leffler 		if (crd->crd_flags & CRD_F_IV_EXPLICIT)
11008fca7a5SJohn-Mark Gurney 			bcopy(crd->crd_iv, iv, ivlen);
11148b0f2e1SPawel Jakub Dawidek 		else
11208fca7a5SJohn-Mark Gurney 			arc4rand(iv, ivlen, 0);
113091d81d1SSam Leffler 
114091d81d1SSam Leffler 		/* Do we need to write the IV */
115f34a967bSPawel Jakub Dawidek 		if (!(crd->crd_flags & CRD_F_IV_PRESENT))
11608fca7a5SJohn-Mark Gurney 			crypto_copyback(flags, buf, crd->crd_inject, ivlen, iv);
117091d81d1SSam Leffler 
118091d81d1SSam Leffler 	} else {	/* Decryption */
119091d81d1SSam Leffler 		/* IV explicitly provided ? */
120091d81d1SSam Leffler 		if (crd->crd_flags & CRD_F_IV_EXPLICIT)
12108fca7a5SJohn-Mark Gurney 			bcopy(crd->crd_iv, iv, ivlen);
122091d81d1SSam Leffler 		else {
123091d81d1SSam Leffler 			/* Get IV off buf */
12408fca7a5SJohn-Mark Gurney 			crypto_copydata(flags, buf, crd->crd_inject, ivlen, iv);
125091d81d1SSam Leffler 		}
126091d81d1SSam Leffler 	}
127091d81d1SSam Leffler 
128c740ae4bSPoul-Henning Kamp 	if (crd->crd_flags & CRD_F_KEY_EXPLICIT) {
129c740ae4bSPoul-Henning Kamp 		int error;
130c740ae4bSPoul-Henning Kamp 
131c740ae4bSPoul-Henning Kamp 		if (sw->sw_kschedule)
132c740ae4bSPoul-Henning Kamp 			exf->zerokey(&(sw->sw_kschedule));
13308fca7a5SJohn-Mark Gurney 
134c740ae4bSPoul-Henning Kamp 		error = exf->setkey(&sw->sw_kschedule,
135c740ae4bSPoul-Henning Kamp 				crd->crd_key, crd->crd_klen / 8);
136c740ae4bSPoul-Henning Kamp 		if (error)
137c740ae4bSPoul-Henning Kamp 			return (error);
138c740ae4bSPoul-Henning Kamp 	}
139d295bdeeSPawel Jakub Dawidek 
14008fca7a5SJohn-Mark Gurney 	iov = iovlcl;
14108fca7a5SJohn-Mark Gurney 	iovcnt = nitems(iovlcl);
14208fca7a5SJohn-Mark Gurney 	iovalloc = 0;
14308fca7a5SJohn-Mark Gurney 	uio = &uiolcl;
14408fca7a5SJohn-Mark Gurney 	if ((flags & CRYPTO_F_IMBUF) != 0) {
145748a12e2SJohn-Mark Gurney 		error = crypto_mbuftoiov((struct mbuf *)buf, &iov, &iovcnt,
14608fca7a5SJohn-Mark Gurney 		    &iovalloc);
147748a12e2SJohn-Mark Gurney 		if (error)
148748a12e2SJohn-Mark Gurney 			return (error);
14908fca7a5SJohn-Mark Gurney 		uio->uio_iov = iov;
15008fca7a5SJohn-Mark Gurney 		uio->uio_iovcnt = iovcnt;
15108fca7a5SJohn-Mark Gurney 	} else if ((flags & CRYPTO_F_IOV) != 0)
15208fca7a5SJohn-Mark Gurney 		uio = (struct uio *)buf;
15308fca7a5SJohn-Mark Gurney 	else {
15408fca7a5SJohn-Mark Gurney 		iov[0].iov_base = buf;
15508fca7a5SJohn-Mark Gurney 		iov[0].iov_len = crd->crd_skip + crd->crd_len;
15608fca7a5SJohn-Mark Gurney 		uio->uio_iov = iov;
15708fca7a5SJohn-Mark Gurney 		uio->uio_iovcnt = 1;
15808fca7a5SJohn-Mark Gurney 	}
15908fca7a5SJohn-Mark Gurney 
160091d81d1SSam Leffler 	ivp = iv;
161091d81d1SSam Leffler 
16208fca7a5SJohn-Mark Gurney 	if (exf->reinit) {
163d295bdeeSPawel Jakub Dawidek 		/*
164d295bdeeSPawel Jakub Dawidek 		 * xforms that provide a reinit method perform all IV
165d295bdeeSPawel Jakub Dawidek 		 * handling themselves.
166d295bdeeSPawel Jakub Dawidek 		 */
167d295bdeeSPawel Jakub Dawidek 		exf->reinit(sw->sw_kschedule, iv);
168091d81d1SSam Leffler 	}
169091d81d1SSam Leffler 
17008fca7a5SJohn-Mark Gurney 	count = crd->crd_skip;
17108fca7a5SJohn-Mark Gurney 	ind = cuio_getptr(uio, count, &k);
17208fca7a5SJohn-Mark Gurney 	if (ind == -1) {
17308fca7a5SJohn-Mark Gurney 		error = EINVAL;
17408fca7a5SJohn-Mark Gurney 		goto out;
175091d81d1SSam Leffler 	}
176091d81d1SSam Leffler 
177091d81d1SSam Leffler 	i = crd->crd_len;
178091d81d1SSam Leffler 
179091d81d1SSam Leffler 	while (i > 0) {
180091d81d1SSam Leffler 		/*
181091d81d1SSam Leffler 		 * If there's insufficient data at the end of
182091d81d1SSam Leffler 		 * an iovec, we have to do some copying.
183091d81d1SSam Leffler 		 */
18408fca7a5SJohn-Mark Gurney 		if (uio->uio_iov[ind].iov_len < k + blks &&
18508fca7a5SJohn-Mark Gurney 		    uio->uio_iov[ind].iov_len != k) {
18608fca7a5SJohn-Mark Gurney 			cuio_copydata(uio, count, blks, blk);
187091d81d1SSam Leffler 
188091d81d1SSam Leffler 			/* Actual encryption/decryption */
189d295bdeeSPawel Jakub Dawidek 			if (exf->reinit) {
190091d81d1SSam Leffler 				if (crd->crd_flags & CRD_F_ENCRYPT) {
191d295bdeeSPawel Jakub Dawidek 					exf->encrypt(sw->sw_kschedule,
192d295bdeeSPawel Jakub Dawidek 					    blk);
193d295bdeeSPawel Jakub Dawidek 				} else {
194d295bdeeSPawel Jakub Dawidek 					exf->decrypt(sw->sw_kschedule,
195d295bdeeSPawel Jakub Dawidek 					    blk);
196d295bdeeSPawel Jakub Dawidek 				}
197d295bdeeSPawel Jakub Dawidek 			} else if (crd->crd_flags & CRD_F_ENCRYPT) {
198091d81d1SSam Leffler 				/* XOR with previous block */
199091d81d1SSam Leffler 				for (j = 0; j < blks; j++)
200091d81d1SSam Leffler 					blk[j] ^= ivp[j];
201091d81d1SSam Leffler 
202091d81d1SSam Leffler 				exf->encrypt(sw->sw_kschedule, blk);
203091d81d1SSam Leffler 
204091d81d1SSam Leffler 				/*
205091d81d1SSam Leffler 				 * Keep encrypted block for XOR'ing
206091d81d1SSam Leffler 				 * with next block
207091d81d1SSam Leffler 				 */
208091d81d1SSam Leffler 				bcopy(blk, iv, blks);
209091d81d1SSam Leffler 				ivp = iv;
210091d81d1SSam Leffler 			} else {	/* decrypt */
211091d81d1SSam Leffler 				/*
212091d81d1SSam Leffler 				 * Keep encrypted block for XOR'ing
213091d81d1SSam Leffler 				 * with next block
214091d81d1SSam Leffler 				 */
21508fca7a5SJohn-Mark Gurney 				nivp = (ivp == iv) ? iv2 : iv;
21608fca7a5SJohn-Mark Gurney 				bcopy(blk, nivp, blks);
217091d81d1SSam Leffler 
218091d81d1SSam Leffler 				exf->decrypt(sw->sw_kschedule, blk);
219091d81d1SSam Leffler 
220091d81d1SSam Leffler 				/* XOR with previous block */
221091d81d1SSam Leffler 				for (j = 0; j < blks; j++)
222091d81d1SSam Leffler 					blk[j] ^= ivp[j];
223091d81d1SSam Leffler 
22408fca7a5SJohn-Mark Gurney 				ivp = nivp;
225091d81d1SSam Leffler 			}
226091d81d1SSam Leffler 
227091d81d1SSam Leffler 			/* Copy back decrypted block */
22808fca7a5SJohn-Mark Gurney 			cuio_copyback(uio, count, blks, blk);
22908fca7a5SJohn-Mark Gurney 
23008fca7a5SJohn-Mark Gurney 			count += blks;
231091d81d1SSam Leffler 
232091d81d1SSam Leffler 			/* Advance pointer */
23308fca7a5SJohn-Mark Gurney 			ind = cuio_getptr(uio, count, &k);
23408fca7a5SJohn-Mark Gurney 			if (ind == -1) {
23508fca7a5SJohn-Mark Gurney 				error = EINVAL;
23608fca7a5SJohn-Mark Gurney 				goto out;
23708fca7a5SJohn-Mark Gurney 			}
238091d81d1SSam Leffler 
239091d81d1SSam Leffler 			i -= blks;
240091d81d1SSam Leffler 
241091d81d1SSam Leffler 			/* Could be done... */
242091d81d1SSam Leffler 			if (i == 0)
243091d81d1SSam Leffler 				break;
244091d81d1SSam Leffler 		}
245091d81d1SSam Leffler 
2462f1f9cceSConrad Meyer 		while (uio->uio_iov[ind].iov_len >= k + blks && i > 0) {
2475d7ae54aSConrad Meyer 			uint8_t *idat;
2482f1f9cceSConrad Meyer 			size_t nb, rem;
2492f1f9cceSConrad Meyer 
2502f1f9cceSConrad Meyer 			nb = blks;
251179b21e8SConrad Meyer 			rem = MIN((size_t)i,
252179b21e8SConrad Meyer 			    uio->uio_iov[ind].iov_len - (size_t)k);
2535d7ae54aSConrad Meyer 			idat = (uint8_t *)uio->uio_iov[ind].iov_base + k;
254091d81d1SSam Leffler 
255d295bdeeSPawel Jakub Dawidek 			if (exf->reinit) {
2562f1f9cceSConrad Meyer 				if ((crd->crd_flags & CRD_F_ENCRYPT) != 0 &&
2572f1f9cceSConrad Meyer 				    exf->encrypt_multi == NULL)
258d295bdeeSPawel Jakub Dawidek 					exf->encrypt(sw->sw_kschedule,
259d295bdeeSPawel Jakub Dawidek 					    idat);
2602f1f9cceSConrad Meyer 				else if ((crd->crd_flags & CRD_F_ENCRYPT) != 0) {
2612f1f9cceSConrad Meyer 					nb = rounddown(rem, blks);
2622f1f9cceSConrad Meyer 					exf->encrypt_multi(sw->sw_kschedule,
2632f1f9cceSConrad Meyer 					    idat, nb);
2642f1f9cceSConrad Meyer 				} else if (exf->decrypt_multi == NULL)
265d295bdeeSPawel Jakub Dawidek 					exf->decrypt(sw->sw_kschedule,
266d295bdeeSPawel Jakub Dawidek 					    idat);
2672f1f9cceSConrad Meyer 				else {
2682f1f9cceSConrad Meyer 					nb = rounddown(rem, blks);
2692f1f9cceSConrad Meyer 					exf->decrypt_multi(sw->sw_kschedule,
2702f1f9cceSConrad Meyer 					    idat, nb);
271d295bdeeSPawel Jakub Dawidek 				}
272d295bdeeSPawel Jakub Dawidek 			} else if (crd->crd_flags & CRD_F_ENCRYPT) {
273091d81d1SSam Leffler 				/* XOR with previous block/IV */
274091d81d1SSam Leffler 				for (j = 0; j < blks; j++)
275091d81d1SSam Leffler 					idat[j] ^= ivp[j];
276091d81d1SSam Leffler 
277091d81d1SSam Leffler 				exf->encrypt(sw->sw_kschedule, idat);
278091d81d1SSam Leffler 				ivp = idat;
279091d81d1SSam Leffler 			} else {	/* decrypt */
280091d81d1SSam Leffler 				/*
281091d81d1SSam Leffler 				 * Keep encrypted block to be used
282091d81d1SSam Leffler 				 * in next block's processing.
283091d81d1SSam Leffler 				 */
28408fca7a5SJohn-Mark Gurney 				nivp = (ivp == iv) ? iv2 : iv;
28508fca7a5SJohn-Mark Gurney 				bcopy(idat, nivp, blks);
286091d81d1SSam Leffler 
287091d81d1SSam Leffler 				exf->decrypt(sw->sw_kschedule, idat);
288091d81d1SSam Leffler 
289091d81d1SSam Leffler 				/* XOR with previous block/IV */
290091d81d1SSam Leffler 				for (j = 0; j < blks; j++)
291091d81d1SSam Leffler 					idat[j] ^= ivp[j];
292091d81d1SSam Leffler 
29308fca7a5SJohn-Mark Gurney 				ivp = nivp;
294091d81d1SSam Leffler 			}
295091d81d1SSam Leffler 
2962f1f9cceSConrad Meyer 			count += nb;
2972f1f9cceSConrad Meyer 			k += nb;
2982f1f9cceSConrad Meyer 			i -= nb;
299091d81d1SSam Leffler 		}
300091d81d1SSam Leffler 
301f34a967bSPawel Jakub Dawidek 		/*
30208fca7a5SJohn-Mark Gurney 		 * Advance to the next iov if the end of the current iov
30308fca7a5SJohn-Mark Gurney 		 * is aligned with the end of a cipher block.
30408fca7a5SJohn-Mark Gurney 		 * Note that the code is equivalent to calling:
30508fca7a5SJohn-Mark Gurney 		 *      ind = cuio_getptr(uio, count, &k);
306f34a967bSPawel Jakub Dawidek 		 */
30708fca7a5SJohn-Mark Gurney 		if (i > 0 && k == uio->uio_iov[ind].iov_len) {
30808fca7a5SJohn-Mark Gurney 			k = 0;
30908fca7a5SJohn-Mark Gurney 			ind++;
31008fca7a5SJohn-Mark Gurney 			if (ind >= uio->uio_iovcnt) {
31108fca7a5SJohn-Mark Gurney 				error = EINVAL;
31208fca7a5SJohn-Mark Gurney 				goto out;
31308fca7a5SJohn-Mark Gurney 			}
314f34a967bSPawel Jakub Dawidek 		}
315f34a967bSPawel Jakub Dawidek 	}
316f34a967bSPawel Jakub Dawidek 
31708fca7a5SJohn-Mark Gurney out:
31808fca7a5SJohn-Mark Gurney 	if (iovalloc)
31908fca7a5SJohn-Mark Gurney 		free(iov, M_CRYPTO_DATA);
320091d81d1SSam Leffler 
32108fca7a5SJohn-Mark Gurney 	return (error);
322091d81d1SSam Leffler }
323091d81d1SSam Leffler 
32425b7033bSConrad Meyer static int __result_use_check
325f6c4bc3bSPawel Jakub Dawidek swcr_authprepare(struct auth_hash *axf, struct swcr_data *sw, u_char *key,
326f6c4bc3bSPawel Jakub Dawidek     int klen)
327f6c4bc3bSPawel Jakub Dawidek {
328f6c4bc3bSPawel Jakub Dawidek 	int k;
329f6c4bc3bSPawel Jakub Dawidek 
330f6c4bc3bSPawel Jakub Dawidek 	klen /= 8;
331f6c4bc3bSPawel Jakub Dawidek 
332f6c4bc3bSPawel Jakub Dawidek 	switch (axf->type) {
333f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_MD5_HMAC:
334f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA1_HMAC:
335c97f39ceSConrad Meyer 	case CRYPTO_SHA2_224_HMAC:
336f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_256_HMAC:
337f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_384_HMAC:
338f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_512_HMAC:
339f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_NULL_HMAC:
340f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_RIPEMD160_HMAC:
341f6c4bc3bSPawel Jakub Dawidek 		for (k = 0; k < klen; k++)
342f6c4bc3bSPawel Jakub Dawidek 			key[k] ^= HMAC_IPAD_VAL;
343f6c4bc3bSPawel Jakub Dawidek 
344f6c4bc3bSPawel Jakub Dawidek 		axf->Init(sw->sw_ictx);
345f6c4bc3bSPawel Jakub Dawidek 		axf->Update(sw->sw_ictx, key, klen);
346f6c4bc3bSPawel Jakub Dawidek 		axf->Update(sw->sw_ictx, hmac_ipad_buffer, axf->blocksize - klen);
347f6c4bc3bSPawel Jakub Dawidek 
348f6c4bc3bSPawel Jakub Dawidek 		for (k = 0; k < klen; k++)
349f6c4bc3bSPawel Jakub Dawidek 			key[k] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL);
350f6c4bc3bSPawel Jakub Dawidek 
351f6c4bc3bSPawel Jakub Dawidek 		axf->Init(sw->sw_octx);
352f6c4bc3bSPawel Jakub Dawidek 		axf->Update(sw->sw_octx, key, klen);
353f6c4bc3bSPawel Jakub Dawidek 		axf->Update(sw->sw_octx, hmac_opad_buffer, axf->blocksize - klen);
354f6c4bc3bSPawel Jakub Dawidek 
355f6c4bc3bSPawel Jakub Dawidek 		for (k = 0; k < klen; k++)
356f6c4bc3bSPawel Jakub Dawidek 			key[k] ^= HMAC_OPAD_VAL;
357f6c4bc3bSPawel Jakub Dawidek 		break;
358f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_MD5_KPDK:
359f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA1_KPDK:
3601f4990a6SBjoern A. Zeeb 	{
36177680d96SBjoern A. Zeeb 		/*
36277680d96SBjoern A. Zeeb 		 * We need a buffer that can hold an md5 and a sha1 result
36377680d96SBjoern A. Zeeb 		 * just to throw it away.
36477680d96SBjoern A. Zeeb 		 * What we do here is the initial part of:
36577680d96SBjoern A. Zeeb 		 *   ALGO( key, keyfill, .. )
36677680d96SBjoern A. Zeeb 		 * adding the key to sw_ictx and abusing Final() to get the
36777680d96SBjoern A. Zeeb 		 * "keyfill" padding.
36877680d96SBjoern A. Zeeb 		 * In addition we abuse the sw_octx to save the key to have
36977680d96SBjoern A. Zeeb 		 * it to be able to append it at the end in swcr_authcompute().
37077680d96SBjoern A. Zeeb 		 */
3711f4990a6SBjoern A. Zeeb 		u_char buf[SHA1_RESULTLEN];
3721f4990a6SBjoern A. Zeeb 
373f6c4bc3bSPawel Jakub Dawidek 		sw->sw_klen = klen;
374f6c4bc3bSPawel Jakub Dawidek 		bcopy(key, sw->sw_octx, klen);
375f6c4bc3bSPawel Jakub Dawidek 		axf->Init(sw->sw_ictx);
376f6c4bc3bSPawel Jakub Dawidek 		axf->Update(sw->sw_ictx, key, klen);
3771f4990a6SBjoern A. Zeeb 		axf->Final(buf, sw->sw_ictx);
378f6c4bc3bSPawel Jakub Dawidek 		break;
3791f4990a6SBjoern A. Zeeb 	}
38025b7033bSConrad Meyer 	case CRYPTO_POLY1305:
38125b7033bSConrad Meyer 		if (klen != POLY1305_KEY_LEN) {
38225b7033bSConrad Meyer 			CRYPTDEB("bad poly1305 key size %d", klen);
38325b7033bSConrad Meyer 			return EINVAL;
38425b7033bSConrad Meyer 		}
38525b7033bSConrad Meyer 		/* FALLTHROUGH */
3860e33efe4SConrad Meyer 	case CRYPTO_BLAKE2B:
3870e33efe4SConrad Meyer 	case CRYPTO_BLAKE2S:
3880e33efe4SConrad Meyer 		axf->Setkey(sw->sw_ictx, key, klen);
3890e33efe4SConrad Meyer 		axf->Init(sw->sw_ictx);
3900e33efe4SConrad Meyer 		break;
391f6c4bc3bSPawel Jakub Dawidek 	default:
392f6c4bc3bSPawel Jakub Dawidek 		printf("%s: CRD_F_KEY_EXPLICIT flag given, but algorithm %d "
393f6c4bc3bSPawel Jakub Dawidek 		    "doesn't use keys.\n", __func__, axf->type);
39425b7033bSConrad Meyer 		return EINVAL;
395f6c4bc3bSPawel Jakub Dawidek 	}
39625b7033bSConrad Meyer 	return 0;
397f6c4bc3bSPawel Jakub Dawidek }
398f6c4bc3bSPawel Jakub Dawidek 
399091d81d1SSam Leffler /*
400091d81d1SSam Leffler  * Compute keyed-hash authenticator.
401091d81d1SSam Leffler  */
402091d81d1SSam Leffler static int
40338d2f8d6SPawel Jakub Dawidek swcr_authcompute(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf,
404f34a967bSPawel Jakub Dawidek     int flags)
405091d81d1SSam Leffler {
4060bbc4bf9SPawel Jakub Dawidek 	unsigned char aalg[HASH_MAX_LEN];
407091d81d1SSam Leffler 	struct auth_hash *axf;
408091d81d1SSam Leffler 	union authctx ctx;
409091d81d1SSam Leffler 	int err;
410091d81d1SSam Leffler 
411091d81d1SSam Leffler 	if (sw->sw_ictx == 0)
412091d81d1SSam Leffler 		return EINVAL;
413091d81d1SSam Leffler 
414091d81d1SSam Leffler 	axf = sw->sw_axf;
415091d81d1SSam Leffler 
41625b7033bSConrad Meyer 	if (crd->crd_flags & CRD_F_KEY_EXPLICIT) {
41725b7033bSConrad Meyer 		err = swcr_authprepare(axf, sw, crd->crd_key, crd->crd_klen);
41825b7033bSConrad Meyer 		if (err != 0)
41925b7033bSConrad Meyer 			return err;
42025b7033bSConrad Meyer 	}
421f6c4bc3bSPawel Jakub Dawidek 
422091d81d1SSam Leffler 	bcopy(sw->sw_ictx, &ctx, axf->ctxsize);
423091d81d1SSam Leffler 
424f34a967bSPawel Jakub Dawidek 	err = crypto_apply(flags, buf, crd->crd_skip, crd->crd_len,
425f34a967bSPawel Jakub Dawidek 	    (int (*)(void *, void *, unsigned int))axf->Update, (caddr_t)&ctx);
426091d81d1SSam Leffler 	if (err)
427091d81d1SSam Leffler 		return err;
428091d81d1SSam Leffler 
429091d81d1SSam Leffler 	switch (sw->sw_alg) {
430c4729f6eSConrad Meyer 	case CRYPTO_SHA1:
431c4729f6eSConrad Meyer 	case CRYPTO_SHA2_224:
432c4729f6eSConrad Meyer 	case CRYPTO_SHA2_256:
433c4729f6eSConrad Meyer 	case CRYPTO_SHA2_384:
434c4729f6eSConrad Meyer 	case CRYPTO_SHA2_512:
435c4729f6eSConrad Meyer 		axf->Final(aalg, &ctx);
436c4729f6eSConrad Meyer 		break;
437c4729f6eSConrad Meyer 
438091d81d1SSam Leffler 	case CRYPTO_MD5_HMAC:
439091d81d1SSam Leffler 	case CRYPTO_SHA1_HMAC:
440c97f39ceSConrad Meyer 	case CRYPTO_SHA2_224_HMAC:
441f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_256_HMAC:
442f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_384_HMAC:
443f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_512_HMAC:
444091d81d1SSam Leffler 	case CRYPTO_RIPEMD160_HMAC:
445091d81d1SSam Leffler 		if (sw->sw_octx == NULL)
446091d81d1SSam Leffler 			return EINVAL;
447091d81d1SSam Leffler 
448091d81d1SSam Leffler 		axf->Final(aalg, &ctx);
449091d81d1SSam Leffler 		bcopy(sw->sw_octx, &ctx, axf->ctxsize);
450091d81d1SSam Leffler 		axf->Update(&ctx, aalg, axf->hashsize);
451091d81d1SSam Leffler 		axf->Final(aalg, &ctx);
452091d81d1SSam Leffler 		break;
453091d81d1SSam Leffler 
454091d81d1SSam Leffler 	case CRYPTO_MD5_KPDK:
455091d81d1SSam Leffler 	case CRYPTO_SHA1_KPDK:
45677680d96SBjoern A. Zeeb 		/* If we have no key saved, return error. */
457091d81d1SSam Leffler 		if (sw->sw_octx == NULL)
458091d81d1SSam Leffler 			return EINVAL;
459091d81d1SSam Leffler 
46077680d96SBjoern A. Zeeb 		/*
46177680d96SBjoern A. Zeeb 		 * Add the trailing copy of the key (see comment in
46277680d96SBjoern A. Zeeb 		 * swcr_authprepare()) after the data:
46377680d96SBjoern A. Zeeb 		 *   ALGO( .., key, algofill )
46477680d96SBjoern A. Zeeb 		 * and let Final() do the proper, natural "algofill"
46577680d96SBjoern A. Zeeb 		 * padding.
46677680d96SBjoern A. Zeeb 		 */
467091d81d1SSam Leffler 		axf->Update(&ctx, sw->sw_octx, sw->sw_klen);
468091d81d1SSam Leffler 		axf->Final(aalg, &ctx);
469091d81d1SSam Leffler 		break;
470091d81d1SSam Leffler 
4710e33efe4SConrad Meyer 	case CRYPTO_BLAKE2B:
4720e33efe4SConrad Meyer 	case CRYPTO_BLAKE2S:
473091d81d1SSam Leffler 	case CRYPTO_NULL_HMAC:
47425b7033bSConrad Meyer 	case CRYPTO_POLY1305:
475091d81d1SSam Leffler 		axf->Final(aalg, &ctx);
476091d81d1SSam Leffler 		break;
477091d81d1SSam Leffler 	}
478091d81d1SSam Leffler 
479091d81d1SSam Leffler 	/* Inject the authentication data */
480f34a967bSPawel Jakub Dawidek 	crypto_copyback(flags, buf, crd->crd_inject,
481f6c4bc3bSPawel Jakub Dawidek 	    sw->sw_mlen == 0 ? axf->hashsize : sw->sw_mlen, aalg);
482091d81d1SSam Leffler 	return 0;
483091d81d1SSam Leffler }
484091d81d1SSam Leffler 
48508fca7a5SJohn-Mark Gurney CTASSERT(INT_MAX <= (1ll<<39) - 256);	/* GCM: plain text < 2^39-256 */
48608fca7a5SJohn-Mark Gurney CTASSERT(INT_MAX <= (uint64_t)-1);	/* GCM: associated data <= 2^64-1 */
48708fca7a5SJohn-Mark Gurney 
48808fca7a5SJohn-Mark Gurney /*
48908fca7a5SJohn-Mark Gurney  * Apply a combined encryption-authentication transformation
49008fca7a5SJohn-Mark Gurney  */
49108fca7a5SJohn-Mark Gurney static int
49208fca7a5SJohn-Mark Gurney swcr_authenc(struct cryptop *crp)
49308fca7a5SJohn-Mark Gurney {
49408fca7a5SJohn-Mark Gurney 	uint32_t blkbuf[howmany(EALG_MAX_BLOCK_LEN, sizeof(uint32_t))];
49508fca7a5SJohn-Mark Gurney 	u_char *blk = (u_char *)blkbuf;
49608fca7a5SJohn-Mark Gurney 	u_char aalg[AALG_MAX_RESULT_LEN];
49708fca7a5SJohn-Mark Gurney 	u_char uaalg[AALG_MAX_RESULT_LEN];
49808fca7a5SJohn-Mark Gurney 	u_char iv[EALG_MAX_BLOCK_LEN];
49908fca7a5SJohn-Mark Gurney 	union authctx ctx;
500*9ebbebe4SConrad Meyer 	struct swcr_session *ses;
50108fca7a5SJohn-Mark Gurney 	struct cryptodesc *crd, *crda = NULL, *crde = NULL;
50208fca7a5SJohn-Mark Gurney 	struct swcr_data *sw, *swa, *swe = NULL;
50308fca7a5SJohn-Mark Gurney 	struct auth_hash *axf = NULL;
50408fca7a5SJohn-Mark Gurney 	struct enc_xform *exf = NULL;
50508fca7a5SJohn-Mark Gurney 	caddr_t buf = (caddr_t)crp->crp_buf;
50608fca7a5SJohn-Mark Gurney 	uint32_t *blkp;
50708fca7a5SJohn-Mark Gurney 	int aadlen, blksz, i, ivlen, len, iskip, oskip, r;
50808fca7a5SJohn-Mark Gurney 
50908fca7a5SJohn-Mark Gurney 	ivlen = blksz = iskip = oskip = 0;
51008fca7a5SJohn-Mark Gurney 
511*9ebbebe4SConrad Meyer 	ses = crypto_get_driver_session(crp->crp_session);
512*9ebbebe4SConrad Meyer 
51308fca7a5SJohn-Mark Gurney 	for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
514*9ebbebe4SConrad Meyer 		for (i = 0; i < nitems(ses->swcr_algorithms) &&
515*9ebbebe4SConrad Meyer 		    ses->swcr_algorithms[i].sw_alg != crd->crd_alg; i++)
51608fca7a5SJohn-Mark Gurney 			;
517*9ebbebe4SConrad Meyer 		if (i == nitems(ses->swcr_algorithms))
51808fca7a5SJohn-Mark Gurney 			return (EINVAL);
51908fca7a5SJohn-Mark Gurney 
520*9ebbebe4SConrad Meyer 		sw = &ses->swcr_algorithms[i];
52108fca7a5SJohn-Mark Gurney 		switch (sw->sw_alg) {
52208fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_NIST_GCM_16:
52308fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_NIST_GMAC:
52408fca7a5SJohn-Mark Gurney 			swe = sw;
52508fca7a5SJohn-Mark Gurney 			crde = crd;
52608fca7a5SJohn-Mark Gurney 			exf = swe->sw_exf;
52708fca7a5SJohn-Mark Gurney 			ivlen = 12;
52808fca7a5SJohn-Mark Gurney 			break;
52908fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_128_NIST_GMAC:
53008fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_192_NIST_GMAC:
53108fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_256_NIST_GMAC:
53208fca7a5SJohn-Mark Gurney 			swa = sw;
53308fca7a5SJohn-Mark Gurney 			crda = crd;
53408fca7a5SJohn-Mark Gurney 			axf = swa->sw_axf;
53508fca7a5SJohn-Mark Gurney 			if (swa->sw_ictx == 0)
53608fca7a5SJohn-Mark Gurney 				return (EINVAL);
53708fca7a5SJohn-Mark Gurney 			bcopy(swa->sw_ictx, &ctx, axf->ctxsize);
53808fca7a5SJohn-Mark Gurney 			blksz = axf->blocksize;
53908fca7a5SJohn-Mark Gurney 			break;
54008fca7a5SJohn-Mark Gurney 		default:
54108fca7a5SJohn-Mark Gurney 			return (EINVAL);
54208fca7a5SJohn-Mark Gurney 		}
54308fca7a5SJohn-Mark Gurney 	}
54408fca7a5SJohn-Mark Gurney 	if (crde == NULL || crda == NULL)
54508fca7a5SJohn-Mark Gurney 		return (EINVAL);
54608fca7a5SJohn-Mark Gurney 
54708fca7a5SJohn-Mark Gurney 	if (crde->crd_alg == CRYPTO_AES_NIST_GCM_16 &&
54808fca7a5SJohn-Mark Gurney 	    (crde->crd_flags & CRD_F_IV_EXPLICIT) == 0)
54908fca7a5SJohn-Mark Gurney 		return (EINVAL);
55008fca7a5SJohn-Mark Gurney 
55108fca7a5SJohn-Mark Gurney 	if (crde->crd_klen != crda->crd_klen)
55208fca7a5SJohn-Mark Gurney 		return (EINVAL);
55308fca7a5SJohn-Mark Gurney 
55408fca7a5SJohn-Mark Gurney 	/* Initialize the IV */
55508fca7a5SJohn-Mark Gurney 	if (crde->crd_flags & CRD_F_ENCRYPT) {
55608fca7a5SJohn-Mark Gurney 		/* IV explicitly provided ? */
55708fca7a5SJohn-Mark Gurney 		if (crde->crd_flags & CRD_F_IV_EXPLICIT)
55808fca7a5SJohn-Mark Gurney 			bcopy(crde->crd_iv, iv, ivlen);
55908fca7a5SJohn-Mark Gurney 		else
56008fca7a5SJohn-Mark Gurney 			arc4rand(iv, ivlen, 0);
56108fca7a5SJohn-Mark Gurney 
56208fca7a5SJohn-Mark Gurney 		/* Do we need to write the IV */
56308fca7a5SJohn-Mark Gurney 		if (!(crde->crd_flags & CRD_F_IV_PRESENT))
56408fca7a5SJohn-Mark Gurney 			crypto_copyback(crp->crp_flags, buf, crde->crd_inject,
56508fca7a5SJohn-Mark Gurney 			    ivlen, iv);
56608fca7a5SJohn-Mark Gurney 
56708fca7a5SJohn-Mark Gurney 	} else {	/* Decryption */
56808fca7a5SJohn-Mark Gurney 			/* IV explicitly provided ? */
56908fca7a5SJohn-Mark Gurney 		if (crde->crd_flags & CRD_F_IV_EXPLICIT)
57008fca7a5SJohn-Mark Gurney 			bcopy(crde->crd_iv, iv, ivlen);
57108fca7a5SJohn-Mark Gurney 		else {
57208fca7a5SJohn-Mark Gurney 			/* Get IV off buf */
57308fca7a5SJohn-Mark Gurney 			crypto_copydata(crp->crp_flags, buf, crde->crd_inject,
57408fca7a5SJohn-Mark Gurney 			    ivlen, iv);
57508fca7a5SJohn-Mark Gurney 		}
57608fca7a5SJohn-Mark Gurney 	}
57708fca7a5SJohn-Mark Gurney 
57808fca7a5SJohn-Mark Gurney 	/* Supply MAC with IV */
57908fca7a5SJohn-Mark Gurney 	if (axf->Reinit)
58008fca7a5SJohn-Mark Gurney 		axf->Reinit(&ctx, iv, ivlen);
58108fca7a5SJohn-Mark Gurney 
58208fca7a5SJohn-Mark Gurney 	/* Supply MAC with AAD */
58308fca7a5SJohn-Mark Gurney 	aadlen = crda->crd_len;
58408fca7a5SJohn-Mark Gurney 
58508fca7a5SJohn-Mark Gurney 	for (i = iskip; i < crda->crd_len; i += blksz) {
58608fca7a5SJohn-Mark Gurney 		len = MIN(crda->crd_len - i, blksz - oskip);
58708fca7a5SJohn-Mark Gurney 		crypto_copydata(crp->crp_flags, buf, crda->crd_skip + i, len,
58808fca7a5SJohn-Mark Gurney 		    blk + oskip);
58908fca7a5SJohn-Mark Gurney 		bzero(blk + len + oskip, blksz - len - oskip);
59008fca7a5SJohn-Mark Gurney 		axf->Update(&ctx, blk, blksz);
59108fca7a5SJohn-Mark Gurney 		oskip = 0; /* reset initial output offset */
59208fca7a5SJohn-Mark Gurney 	}
59308fca7a5SJohn-Mark Gurney 
59408fca7a5SJohn-Mark Gurney 	if (exf->reinit)
59508fca7a5SJohn-Mark Gurney 		exf->reinit(swe->sw_kschedule, iv);
59608fca7a5SJohn-Mark Gurney 
59708fca7a5SJohn-Mark Gurney 	/* Do encryption/decryption with MAC */
5982f1f9cceSConrad Meyer 	for (i = 0; i < crde->crd_len; i += len) {
5992f1f9cceSConrad Meyer 		if (exf->encrypt_multi != NULL) {
6002f1f9cceSConrad Meyer 			len = rounddown(crde->crd_len - i, blksz);
6012f1f9cceSConrad Meyer 			if (len == 0)
6022f1f9cceSConrad Meyer 				len = blksz;
6032f1f9cceSConrad Meyer 			else
6042f1f9cceSConrad Meyer 				len = MIN(len, sizeof(blkbuf));
6052f1f9cceSConrad Meyer 		} else
6062f1f9cceSConrad Meyer 			len = blksz;
6072f1f9cceSConrad Meyer 		len = MIN(crde->crd_len - i, len);
60808fca7a5SJohn-Mark Gurney 		if (len < blksz)
60908fca7a5SJohn-Mark Gurney 			bzero(blk, blksz);
61008fca7a5SJohn-Mark Gurney 		crypto_copydata(crp->crp_flags, buf, crde->crd_skip + i, len,
61108fca7a5SJohn-Mark Gurney 		    blk);
61208fca7a5SJohn-Mark Gurney 		if (crde->crd_flags & CRD_F_ENCRYPT) {
6132f1f9cceSConrad Meyer 			if (exf->encrypt_multi != NULL)
6142f1f9cceSConrad Meyer 				exf->encrypt_multi(swe->sw_kschedule, blk,
6152f1f9cceSConrad Meyer 				    len);
6162f1f9cceSConrad Meyer 			else
61708fca7a5SJohn-Mark Gurney 				exf->encrypt(swe->sw_kschedule, blk);
61808fca7a5SJohn-Mark Gurney 			axf->Update(&ctx, blk, len);
61908fca7a5SJohn-Mark Gurney 			crypto_copyback(crp->crp_flags, buf,
62008fca7a5SJohn-Mark Gurney 			    crde->crd_skip + i, len, blk);
62108fca7a5SJohn-Mark Gurney 		} else {
62208fca7a5SJohn-Mark Gurney 			axf->Update(&ctx, blk, len);
62308fca7a5SJohn-Mark Gurney 		}
62408fca7a5SJohn-Mark Gurney 	}
62508fca7a5SJohn-Mark Gurney 
62608fca7a5SJohn-Mark Gurney 	/* Do any required special finalization */
62708fca7a5SJohn-Mark Gurney 	switch (crda->crd_alg) {
62808fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_128_NIST_GMAC:
62908fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_192_NIST_GMAC:
63008fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_256_NIST_GMAC:
63108fca7a5SJohn-Mark Gurney 			/* length block */
63208fca7a5SJohn-Mark Gurney 			bzero(blk, blksz);
63308fca7a5SJohn-Mark Gurney 			blkp = (uint32_t *)blk + 1;
63408fca7a5SJohn-Mark Gurney 			*blkp = htobe32(aadlen * 8);
63508fca7a5SJohn-Mark Gurney 			blkp = (uint32_t *)blk + 3;
63608fca7a5SJohn-Mark Gurney 			*blkp = htobe32(crde->crd_len * 8);
63708fca7a5SJohn-Mark Gurney 			axf->Update(&ctx, blk, blksz);
63808fca7a5SJohn-Mark Gurney 			break;
63908fca7a5SJohn-Mark Gurney 	}
64008fca7a5SJohn-Mark Gurney 
64108fca7a5SJohn-Mark Gurney 	/* Finalize MAC */
64208fca7a5SJohn-Mark Gurney 	axf->Final(aalg, &ctx);
64308fca7a5SJohn-Mark Gurney 
64408fca7a5SJohn-Mark Gurney 	/* Validate tag */
64508fca7a5SJohn-Mark Gurney 	if (!(crde->crd_flags & CRD_F_ENCRYPT)) {
64608fca7a5SJohn-Mark Gurney 		crypto_copydata(crp->crp_flags, buf, crda->crd_inject,
64708fca7a5SJohn-Mark Gurney 		    axf->hashsize, uaalg);
64808fca7a5SJohn-Mark Gurney 
64908fca7a5SJohn-Mark Gurney 		r = timingsafe_bcmp(aalg, uaalg, axf->hashsize);
65008fca7a5SJohn-Mark Gurney 		if (r == 0) {
65108fca7a5SJohn-Mark Gurney 			/* tag matches, decrypt data */
65208fca7a5SJohn-Mark Gurney 			for (i = 0; i < crde->crd_len; i += blksz) {
65308fca7a5SJohn-Mark Gurney 				len = MIN(crde->crd_len - i, blksz);
65408fca7a5SJohn-Mark Gurney 				if (len < blksz)
65508fca7a5SJohn-Mark Gurney 					bzero(blk, blksz);
65608fca7a5SJohn-Mark Gurney 				crypto_copydata(crp->crp_flags, buf,
65708fca7a5SJohn-Mark Gurney 				    crde->crd_skip + i, len, blk);
65808fca7a5SJohn-Mark Gurney 				exf->decrypt(swe->sw_kschedule, blk);
65908fca7a5SJohn-Mark Gurney 				crypto_copyback(crp->crp_flags, buf,
66008fca7a5SJohn-Mark Gurney 				    crde->crd_skip + i, len, blk);
66108fca7a5SJohn-Mark Gurney 			}
66208fca7a5SJohn-Mark Gurney 		} else
66308fca7a5SJohn-Mark Gurney 			return (EBADMSG);
66408fca7a5SJohn-Mark Gurney 	} else {
66508fca7a5SJohn-Mark Gurney 		/* Inject the authentication data */
66608fca7a5SJohn-Mark Gurney 		crypto_copyback(crp->crp_flags, buf, crda->crd_inject,
66708fca7a5SJohn-Mark Gurney 		    axf->hashsize, aalg);
66808fca7a5SJohn-Mark Gurney 	}
66908fca7a5SJohn-Mark Gurney 
67008fca7a5SJohn-Mark Gurney 	return (0);
67108fca7a5SJohn-Mark Gurney }
67208fca7a5SJohn-Mark Gurney 
673091d81d1SSam Leffler /*
674091d81d1SSam Leffler  * Apply a compression/decompression algorithm
675091d81d1SSam Leffler  */
676091d81d1SSam Leffler static int
677091d81d1SSam Leffler swcr_compdec(struct cryptodesc *crd, struct swcr_data *sw,
678f34a967bSPawel Jakub Dawidek     caddr_t buf, int flags)
679091d81d1SSam Leffler {
680091d81d1SSam Leffler 	u_int8_t *data, *out;
681091d81d1SSam Leffler 	struct comp_algo *cxf;
682091d81d1SSam Leffler 	int adj;
683091d81d1SSam Leffler 	u_int32_t result;
684091d81d1SSam Leffler 
685091d81d1SSam Leffler 	cxf = sw->sw_cxf;
686091d81d1SSam Leffler 
687091d81d1SSam Leffler 	/* We must handle the whole buffer of data in one time
688091d81d1SSam Leffler 	 * then if there is not all the data in the mbuf, we must
689091d81d1SSam Leffler 	 * copy in a buffer.
690091d81d1SSam Leffler 	 */
691091d81d1SSam Leffler 
6921ede983cSDag-Erling Smørgrav 	data = malloc(crd->crd_len, M_CRYPTO_DATA,  M_NOWAIT);
693091d81d1SSam Leffler 	if (data == NULL)
694091d81d1SSam Leffler 		return (EINVAL);
695f34a967bSPawel Jakub Dawidek 	crypto_copydata(flags, buf, crd->crd_skip, crd->crd_len, data);
696091d81d1SSam Leffler 
697091d81d1SSam Leffler 	if (crd->crd_flags & CRD_F_COMP)
698091d81d1SSam Leffler 		result = cxf->compress(data, crd->crd_len, &out);
699091d81d1SSam Leffler 	else
700091d81d1SSam Leffler 		result = cxf->decompress(data, crd->crd_len, &out);
701091d81d1SSam Leffler 
7021ede983cSDag-Erling Smørgrav 	free(data, M_CRYPTO_DATA);
703091d81d1SSam Leffler 	if (result == 0)
704091d81d1SSam Leffler 		return EINVAL;
705091d81d1SSam Leffler 
706091d81d1SSam Leffler 	/* Copy back the (de)compressed data. m_copyback is
707091d81d1SSam Leffler 	 * extending the mbuf as necessary.
708091d81d1SSam Leffler 	 */
709091d81d1SSam Leffler 	sw->sw_size = result;
710091d81d1SSam Leffler 	/* Check the compressed size when doing compression */
711091d81d1SSam Leffler 	if (crd->crd_flags & CRD_F_COMP) {
712df4dece1SBjoern A. Zeeb 		if (result >= crd->crd_len) {
713091d81d1SSam Leffler 			/* Compression was useless, we lost time */
7141ede983cSDag-Erling Smørgrav 			free(out, M_CRYPTO_DATA);
715091d81d1SSam Leffler 			return 0;
716091d81d1SSam Leffler 		}
717091d81d1SSam Leffler 	}
718091d81d1SSam Leffler 
719f34a967bSPawel Jakub Dawidek 	crypto_copyback(flags, buf, crd->crd_skip, result, out);
720091d81d1SSam Leffler 	if (result < crd->crd_len) {
721091d81d1SSam Leffler 		adj = result - crd->crd_len;
722f34a967bSPawel Jakub Dawidek 		if (flags & CRYPTO_F_IMBUF) {
723091d81d1SSam Leffler 			adj = result - crd->crd_len;
724091d81d1SSam Leffler 			m_adj((struct mbuf *)buf, adj);
725f34a967bSPawel Jakub Dawidek 		} else if (flags & CRYPTO_F_IOV) {
726091d81d1SSam Leffler 			struct uio *uio = (struct uio *)buf;
727091d81d1SSam Leffler 			int ind;
728091d81d1SSam Leffler 
729091d81d1SSam Leffler 			adj = crd->crd_len - result;
730091d81d1SSam Leffler 			ind = uio->uio_iovcnt - 1;
731091d81d1SSam Leffler 
732091d81d1SSam Leffler 			while (adj > 0 && ind >= 0) {
733091d81d1SSam Leffler 				if (adj < uio->uio_iov[ind].iov_len) {
734091d81d1SSam Leffler 					uio->uio_iov[ind].iov_len -= adj;
735091d81d1SSam Leffler 					break;
736091d81d1SSam Leffler 				}
737091d81d1SSam Leffler 
738091d81d1SSam Leffler 				adj -= uio->uio_iov[ind].iov_len;
739091d81d1SSam Leffler 				uio->uio_iov[ind].iov_len = 0;
740091d81d1SSam Leffler 				ind--;
741091d81d1SSam Leffler 				uio->uio_iovcnt--;
742091d81d1SSam Leffler 			}
743091d81d1SSam Leffler 		}
744091d81d1SSam Leffler 	}
7451ede983cSDag-Erling Smørgrav 	free(out, M_CRYPTO_DATA);
746091d81d1SSam Leffler 	return 0;
747091d81d1SSam Leffler }
748091d81d1SSam Leffler 
749091d81d1SSam Leffler /*
750091d81d1SSam Leffler  * Generate a new software session.
751091d81d1SSam Leffler  */
752091d81d1SSam Leffler static int
7531b0909d5SConrad Meyer swcr_newsession(device_t dev, crypto_session_t cses, struct cryptoini *cri)
754091d81d1SSam Leffler {
755*9ebbebe4SConrad Meyer 	struct swcr_session *ses;
756*9ebbebe4SConrad Meyer 	struct swcr_data *swd;
757091d81d1SSam Leffler 	struct auth_hash *axf;
758091d81d1SSam Leffler 	struct enc_xform *txf;
759091d81d1SSam Leffler 	struct comp_algo *cxf;
760*9ebbebe4SConrad Meyer 	size_t i;
761a2bc81bfSJohn-Mark Gurney 	int len;
762f6c4bc3bSPawel Jakub Dawidek 	int error;
763091d81d1SSam Leffler 
7641b0909d5SConrad Meyer 	if (cses == NULL || cri == NULL)
765091d81d1SSam Leffler 		return EINVAL;
766091d81d1SSam Leffler 
7671b0909d5SConrad Meyer 	ses = crypto_get_driver_session(cses);
768091d81d1SSam Leffler 
769*9ebbebe4SConrad Meyer 	for (i = 0; cri != NULL && i < nitems(ses->swcr_algorithms); i++) {
770*9ebbebe4SConrad Meyer 		swd = &ses->swcr_algorithms[i];
771091d81d1SSam Leffler 
772091d81d1SSam Leffler 		switch (cri->cri_alg) {
773091d81d1SSam Leffler 		case CRYPTO_DES_CBC:
774091d81d1SSam Leffler 			txf = &enc_xform_des;
775091d81d1SSam Leffler 			goto enccommon;
776091d81d1SSam Leffler 		case CRYPTO_3DES_CBC:
777091d81d1SSam Leffler 			txf = &enc_xform_3des;
778091d81d1SSam Leffler 			goto enccommon;
779091d81d1SSam Leffler 		case CRYPTO_BLF_CBC:
780091d81d1SSam Leffler 			txf = &enc_xform_blf;
781091d81d1SSam Leffler 			goto enccommon;
782091d81d1SSam Leffler 		case CRYPTO_CAST_CBC:
783091d81d1SSam Leffler 			txf = &enc_xform_cast5;
784091d81d1SSam Leffler 			goto enccommon;
785091d81d1SSam Leffler 		case CRYPTO_SKIPJACK_CBC:
786091d81d1SSam Leffler 			txf = &enc_xform_skipjack;
787091d81d1SSam Leffler 			goto enccommon;
788091d81d1SSam Leffler 		case CRYPTO_RIJNDAEL128_CBC:
789091d81d1SSam Leffler 			txf = &enc_xform_rijndael128;
790091d81d1SSam Leffler 			goto enccommon;
791d295bdeeSPawel Jakub Dawidek 		case CRYPTO_AES_XTS:
792d295bdeeSPawel Jakub Dawidek 			txf = &enc_xform_aes_xts;
793d295bdeeSPawel Jakub Dawidek 			goto enccommon;
79408fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_ICM:
79508fca7a5SJohn-Mark Gurney 			txf = &enc_xform_aes_icm;
79608fca7a5SJohn-Mark Gurney 			goto enccommon;
79708fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_NIST_GCM_16:
79808fca7a5SJohn-Mark Gurney 			txf = &enc_xform_aes_nist_gcm;
79908fca7a5SJohn-Mark Gurney 			goto enccommon;
80008fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_NIST_GMAC:
80108fca7a5SJohn-Mark Gurney 			txf = &enc_xform_aes_nist_gmac;
802*9ebbebe4SConrad Meyer 			swd->sw_exf = txf;
80308fca7a5SJohn-Mark Gurney 			break;
804559d3390SGeorge V. Neville-Neil 		case CRYPTO_CAMELLIA_CBC:
805559d3390SGeorge V. Neville-Neil 			txf = &enc_xform_camellia;
806559d3390SGeorge V. Neville-Neil 			goto enccommon;
807091d81d1SSam Leffler 		case CRYPTO_NULL_CBC:
808091d81d1SSam Leffler 			txf = &enc_xform_null;
809091d81d1SSam Leffler 			goto enccommon;
81061590291SConrad Meyer 		case CRYPTO_CHACHA20:
81161590291SConrad Meyer 			txf = &enc_xform_chacha20;
81261590291SConrad Meyer 			goto enccommon;
813091d81d1SSam Leffler 		enccommon:
814f6c4bc3bSPawel Jakub Dawidek 			if (cri->cri_key != NULL) {
815*9ebbebe4SConrad Meyer 				error = txf->setkey(&swd->sw_kschedule,
816091d81d1SSam Leffler 				    cri->cri_key, cri->cri_klen / 8);
817091d81d1SSam Leffler 				if (error) {
8181b0909d5SConrad Meyer 					swcr_freesession(dev, cses);
819091d81d1SSam Leffler 					return error;
820091d81d1SSam Leffler 				}
821f6c4bc3bSPawel Jakub Dawidek 			}
822*9ebbebe4SConrad Meyer 			swd->sw_exf = txf;
823091d81d1SSam Leffler 			break;
824091d81d1SSam Leffler 
825091d81d1SSam Leffler 		case CRYPTO_MD5_HMAC:
826f6c4bc3bSPawel Jakub Dawidek 			axf = &auth_hash_hmac_md5;
827091d81d1SSam Leffler 			goto authcommon;
828091d81d1SSam Leffler 		case CRYPTO_SHA1_HMAC:
829f6c4bc3bSPawel Jakub Dawidek 			axf = &auth_hash_hmac_sha1;
830091d81d1SSam Leffler 			goto authcommon;
831c97f39ceSConrad Meyer 		case CRYPTO_SHA2_224_HMAC:
832c97f39ceSConrad Meyer 			axf = &auth_hash_hmac_sha2_224;
833c97f39ceSConrad Meyer 			goto authcommon;
834f6c4bc3bSPawel Jakub Dawidek 		case CRYPTO_SHA2_256_HMAC:
835091d81d1SSam Leffler 			axf = &auth_hash_hmac_sha2_256;
836f6c4bc3bSPawel Jakub Dawidek 			goto authcommon;
837f6c4bc3bSPawel Jakub Dawidek 		case CRYPTO_SHA2_384_HMAC:
838091d81d1SSam Leffler 			axf = &auth_hash_hmac_sha2_384;
839f6c4bc3bSPawel Jakub Dawidek 			goto authcommon;
840f6c4bc3bSPawel Jakub Dawidek 		case CRYPTO_SHA2_512_HMAC:
841091d81d1SSam Leffler 			axf = &auth_hash_hmac_sha2_512;
842091d81d1SSam Leffler 			goto authcommon;
843091d81d1SSam Leffler 		case CRYPTO_NULL_HMAC:
844091d81d1SSam Leffler 			axf = &auth_hash_null;
845091d81d1SSam Leffler 			goto authcommon;
846091d81d1SSam Leffler 		case CRYPTO_RIPEMD160_HMAC:
847f6c4bc3bSPawel Jakub Dawidek 			axf = &auth_hash_hmac_ripemd_160;
848091d81d1SSam Leffler 		authcommon:
849*9ebbebe4SConrad Meyer 			swd->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
850091d81d1SSam Leffler 			    M_NOWAIT);
851*9ebbebe4SConrad Meyer 			if (swd->sw_ictx == NULL) {
8521b0909d5SConrad Meyer 				swcr_freesession(dev, cses);
853091d81d1SSam Leffler 				return ENOBUFS;
854091d81d1SSam Leffler 			}
855091d81d1SSam Leffler 
856*9ebbebe4SConrad Meyer 			swd->sw_octx = malloc(axf->ctxsize, M_CRYPTO_DATA,
857091d81d1SSam Leffler 			    M_NOWAIT);
858*9ebbebe4SConrad Meyer 			if (swd->sw_octx == NULL) {
8591b0909d5SConrad Meyer 				swcr_freesession(dev, cses);
860091d81d1SSam Leffler 				return ENOBUFS;
861091d81d1SSam Leffler 			}
862091d81d1SSam Leffler 
863f6c4bc3bSPawel Jakub Dawidek 			if (cri->cri_key != NULL) {
864*9ebbebe4SConrad Meyer 				error = swcr_authprepare(axf, swd,
86525b7033bSConrad Meyer 				    cri->cri_key, cri->cri_klen);
86625b7033bSConrad Meyer 				if (error != 0) {
86725b7033bSConrad Meyer 					swcr_freesession(dev, cses);
86825b7033bSConrad Meyer 					return error;
86925b7033bSConrad Meyer 				}
870f6c4bc3bSPawel Jakub Dawidek 			}
871091d81d1SSam Leffler 
872*9ebbebe4SConrad Meyer 			swd->sw_mlen = cri->cri_mlen;
873*9ebbebe4SConrad Meyer 			swd->sw_axf = axf;
874091d81d1SSam Leffler 			break;
875091d81d1SSam Leffler 
876091d81d1SSam Leffler 		case CRYPTO_MD5_KPDK:
877091d81d1SSam Leffler 			axf = &auth_hash_key_md5;
878091d81d1SSam Leffler 			goto auth2common;
879091d81d1SSam Leffler 
880091d81d1SSam Leffler 		case CRYPTO_SHA1_KPDK:
881091d81d1SSam Leffler 			axf = &auth_hash_key_sha1;
882091d81d1SSam Leffler 		auth2common:
883*9ebbebe4SConrad Meyer 			swd->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
884091d81d1SSam Leffler 			    M_NOWAIT);
885*9ebbebe4SConrad Meyer 			if (swd->sw_ictx == NULL) {
8861b0909d5SConrad Meyer 				swcr_freesession(dev, cses);
887091d81d1SSam Leffler 				return ENOBUFS;
888091d81d1SSam Leffler 			}
889091d81d1SSam Leffler 
890*9ebbebe4SConrad Meyer 			swd->sw_octx = malloc(cri->cri_klen / 8,
891f6c4bc3bSPawel Jakub Dawidek 			    M_CRYPTO_DATA, M_NOWAIT);
892*9ebbebe4SConrad Meyer 			if (swd->sw_octx == NULL) {
8931b0909d5SConrad Meyer 				swcr_freesession(dev, cses);
894091d81d1SSam Leffler 				return ENOBUFS;
895091d81d1SSam Leffler 			}
896091d81d1SSam Leffler 
897f6c4bc3bSPawel Jakub Dawidek 			/* Store the key so we can "append" it to the payload */
898f6c4bc3bSPawel Jakub Dawidek 			if (cri->cri_key != NULL) {
899*9ebbebe4SConrad Meyer 				error = swcr_authprepare(axf, swd,
90025b7033bSConrad Meyer 				    cri->cri_key, cri->cri_klen);
90125b7033bSConrad Meyer 				if (error != 0) {
90225b7033bSConrad Meyer 					swcr_freesession(dev, cses);
90325b7033bSConrad Meyer 					return error;
90425b7033bSConrad Meyer 				}
905f6c4bc3bSPawel Jakub Dawidek 			}
906f6c4bc3bSPawel Jakub Dawidek 
907*9ebbebe4SConrad Meyer 			swd->sw_mlen = cri->cri_mlen;
908*9ebbebe4SConrad Meyer 			swd->sw_axf = axf;
909091d81d1SSam Leffler 			break;
910091d81d1SSam Leffler #ifdef notdef
911091d81d1SSam Leffler 		case CRYPTO_MD5:
912091d81d1SSam Leffler 			axf = &auth_hash_md5;
913091d81d1SSam Leffler 			goto auth3common;
914c4729f6eSConrad Meyer #endif
915091d81d1SSam Leffler 
916091d81d1SSam Leffler 		case CRYPTO_SHA1:
917091d81d1SSam Leffler 			axf = &auth_hash_sha1;
918c4729f6eSConrad Meyer 			goto auth3common;
919c4729f6eSConrad Meyer 		case CRYPTO_SHA2_224:
920c4729f6eSConrad Meyer 			axf = &auth_hash_sha2_224;
921c4729f6eSConrad Meyer 			goto auth3common;
922c4729f6eSConrad Meyer 		case CRYPTO_SHA2_256:
923c4729f6eSConrad Meyer 			axf = &auth_hash_sha2_256;
924c4729f6eSConrad Meyer 			goto auth3common;
925c4729f6eSConrad Meyer 		case CRYPTO_SHA2_384:
926c4729f6eSConrad Meyer 			axf = &auth_hash_sha2_384;
927c4729f6eSConrad Meyer 			goto auth3common;
928c4729f6eSConrad Meyer 		case CRYPTO_SHA2_512:
929c4729f6eSConrad Meyer 			axf = &auth_hash_sha2_512;
930c4729f6eSConrad Meyer 
931091d81d1SSam Leffler 		auth3common:
932*9ebbebe4SConrad Meyer 			swd->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
933091d81d1SSam Leffler 			    M_NOWAIT);
934*9ebbebe4SConrad Meyer 			if (swd->sw_ictx == NULL) {
9351b0909d5SConrad Meyer 				swcr_freesession(dev, cses);
936091d81d1SSam Leffler 				return ENOBUFS;
937091d81d1SSam Leffler 			}
938091d81d1SSam Leffler 
939*9ebbebe4SConrad Meyer 			axf->Init(swd->sw_ictx);
940*9ebbebe4SConrad Meyer 			swd->sw_mlen = cri->cri_mlen;
941*9ebbebe4SConrad Meyer 			swd->sw_axf = axf;
942091d81d1SSam Leffler 			break;
94308fca7a5SJohn-Mark Gurney 
94408fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_128_NIST_GMAC:
94508fca7a5SJohn-Mark Gurney 			axf = &auth_hash_nist_gmac_aes_128;
94608fca7a5SJohn-Mark Gurney 			goto auth4common;
94708fca7a5SJohn-Mark Gurney 
94808fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_192_NIST_GMAC:
94908fca7a5SJohn-Mark Gurney 			axf = &auth_hash_nist_gmac_aes_192;
95008fca7a5SJohn-Mark Gurney 			goto auth4common;
95108fca7a5SJohn-Mark Gurney 
95208fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_256_NIST_GMAC:
95308fca7a5SJohn-Mark Gurney 			axf = &auth_hash_nist_gmac_aes_256;
95408fca7a5SJohn-Mark Gurney 		auth4common:
955a2bc81bfSJohn-Mark Gurney 			len = cri->cri_klen / 8;
9562e2e26d1SJohn Baldwin 			if (len != 16 && len != 24 && len != 32) {
9571b0909d5SConrad Meyer 				swcr_freesession(dev, cses);
958a2bc81bfSJohn-Mark Gurney 				return EINVAL;
9592e2e26d1SJohn Baldwin 			}
960a2bc81bfSJohn-Mark Gurney 
961*9ebbebe4SConrad Meyer 			swd->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
96208fca7a5SJohn-Mark Gurney 			    M_NOWAIT);
963*9ebbebe4SConrad Meyer 			if (swd->sw_ictx == NULL) {
9641b0909d5SConrad Meyer 				swcr_freesession(dev, cses);
96508fca7a5SJohn-Mark Gurney 				return ENOBUFS;
96608fca7a5SJohn-Mark Gurney 			}
967*9ebbebe4SConrad Meyer 			axf->Init(swd->sw_ictx);
968*9ebbebe4SConrad Meyer 			axf->Setkey(swd->sw_ictx, cri->cri_key, len);
969*9ebbebe4SConrad Meyer 			swd->sw_axf = axf;
97008fca7a5SJohn-Mark Gurney 			break;
97108fca7a5SJohn-Mark Gurney 
9720e33efe4SConrad Meyer 		case CRYPTO_BLAKE2B:
9730e33efe4SConrad Meyer 			axf = &auth_hash_blake2b;
9740e33efe4SConrad Meyer 			goto auth5common;
9750e33efe4SConrad Meyer 		case CRYPTO_BLAKE2S:
9760e33efe4SConrad Meyer 			axf = &auth_hash_blake2s;
97725b7033bSConrad Meyer 			goto auth5common;
97825b7033bSConrad Meyer 		case CRYPTO_POLY1305:
97925b7033bSConrad Meyer 			axf = &auth_hash_poly1305;
9800e33efe4SConrad Meyer 		auth5common:
981*9ebbebe4SConrad Meyer 			swd->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
9820e33efe4SConrad Meyer 			    M_NOWAIT);
983*9ebbebe4SConrad Meyer 			if (swd->sw_ictx == NULL) {
9841b0909d5SConrad Meyer 				swcr_freesession(dev, cses);
9850e33efe4SConrad Meyer 				return ENOBUFS;
9860e33efe4SConrad Meyer 			}
987*9ebbebe4SConrad Meyer 			axf->Setkey(swd->sw_ictx, cri->cri_key,
9880e33efe4SConrad Meyer 			    cri->cri_klen / 8);
989*9ebbebe4SConrad Meyer 			axf->Init(swd->sw_ictx);
990*9ebbebe4SConrad Meyer 			swd->sw_axf = axf;
9910e33efe4SConrad Meyer 			break;
9920e33efe4SConrad Meyer 
993091d81d1SSam Leffler 		case CRYPTO_DEFLATE_COMP:
994091d81d1SSam Leffler 			cxf = &comp_algo_deflate;
995*9ebbebe4SConrad Meyer 			swd->sw_cxf = cxf;
996091d81d1SSam Leffler 			break;
997091d81d1SSam Leffler 		default:
9981b0909d5SConrad Meyer 			swcr_freesession(dev, cses);
999091d81d1SSam Leffler 			return EINVAL;
1000091d81d1SSam Leffler 		}
1001091d81d1SSam Leffler 
1002*9ebbebe4SConrad Meyer 		swd->sw_alg = cri->cri_alg;
1003091d81d1SSam Leffler 		cri = cri->cri_next;
1004*9ebbebe4SConrad Meyer 		ses->swcr_nalgs++;
1005*9ebbebe4SConrad Meyer 	}
1006*9ebbebe4SConrad Meyer 
1007*9ebbebe4SConrad Meyer 	if (cri != NULL) {
1008*9ebbebe4SConrad Meyer 		CRYPTDEB("Bogus session request for three or more algorithms");
1009*9ebbebe4SConrad Meyer 		return EINVAL;
1010091d81d1SSam Leffler 	}
1011091d81d1SSam Leffler 	return 0;
1012091d81d1SSam Leffler }
1013091d81d1SSam Leffler 
10141b0909d5SConrad Meyer static void
10151b0909d5SConrad Meyer swcr_freesession(device_t dev, crypto_session_t cses)
1016109919c6SBenno Rice {
1017*9ebbebe4SConrad Meyer 	struct swcr_session *ses;
1018*9ebbebe4SConrad Meyer 	struct swcr_data *swd;
1019091d81d1SSam Leffler 	struct enc_xform *txf;
1020091d81d1SSam Leffler 	struct auth_hash *axf;
1021*9ebbebe4SConrad Meyer 	size_t i;
1022091d81d1SSam Leffler 
10231b0909d5SConrad Meyer 	ses = crypto_get_driver_session(cses);
1024091d81d1SSam Leffler 
1025*9ebbebe4SConrad Meyer 	for (i = 0; i < nitems(ses->swcr_algorithms); i++) {
1026*9ebbebe4SConrad Meyer 		swd = &ses->swcr_algorithms[i];
1027091d81d1SSam Leffler 
1028091d81d1SSam Leffler 		switch (swd->sw_alg) {
1029091d81d1SSam Leffler 		case CRYPTO_DES_CBC:
1030091d81d1SSam Leffler 		case CRYPTO_3DES_CBC:
1031091d81d1SSam Leffler 		case CRYPTO_BLF_CBC:
1032091d81d1SSam Leffler 		case CRYPTO_CAST_CBC:
1033091d81d1SSam Leffler 		case CRYPTO_SKIPJACK_CBC:
1034091d81d1SSam Leffler 		case CRYPTO_RIJNDAEL128_CBC:
1035d295bdeeSPawel Jakub Dawidek 		case CRYPTO_AES_XTS:
103608fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_ICM:
103708fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_NIST_GCM_16:
103808fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_NIST_GMAC:
1039559d3390SGeorge V. Neville-Neil 		case CRYPTO_CAMELLIA_CBC:
1040091d81d1SSam Leffler 		case CRYPTO_NULL_CBC:
104161590291SConrad Meyer 		case CRYPTO_CHACHA20:
1042091d81d1SSam Leffler 			txf = swd->sw_exf;
1043091d81d1SSam Leffler 
1044091d81d1SSam Leffler 			if (swd->sw_kschedule)
1045091d81d1SSam Leffler 				txf->zerokey(&(swd->sw_kschedule));
1046091d81d1SSam Leffler 			break;
1047091d81d1SSam Leffler 
1048091d81d1SSam Leffler 		case CRYPTO_MD5_HMAC:
1049091d81d1SSam Leffler 		case CRYPTO_SHA1_HMAC:
1050c97f39ceSConrad Meyer 		case CRYPTO_SHA2_224_HMAC:
1051f6c4bc3bSPawel Jakub Dawidek 		case CRYPTO_SHA2_256_HMAC:
1052f6c4bc3bSPawel Jakub Dawidek 		case CRYPTO_SHA2_384_HMAC:
1053f6c4bc3bSPawel Jakub Dawidek 		case CRYPTO_SHA2_512_HMAC:
1054091d81d1SSam Leffler 		case CRYPTO_RIPEMD160_HMAC:
1055091d81d1SSam Leffler 		case CRYPTO_NULL_HMAC:
1056091d81d1SSam Leffler 			axf = swd->sw_axf;
1057091d81d1SSam Leffler 
1058091d81d1SSam Leffler 			if (swd->sw_ictx) {
1059091d81d1SSam Leffler 				bzero(swd->sw_ictx, axf->ctxsize);
1060091d81d1SSam Leffler 				free(swd->sw_ictx, M_CRYPTO_DATA);
1061091d81d1SSam Leffler 			}
1062091d81d1SSam Leffler 			if (swd->sw_octx) {
1063091d81d1SSam Leffler 				bzero(swd->sw_octx, axf->ctxsize);
1064091d81d1SSam Leffler 				free(swd->sw_octx, M_CRYPTO_DATA);
1065091d81d1SSam Leffler 			}
1066091d81d1SSam Leffler 			break;
1067091d81d1SSam Leffler 
1068091d81d1SSam Leffler 		case CRYPTO_MD5_KPDK:
1069091d81d1SSam Leffler 		case CRYPTO_SHA1_KPDK:
1070091d81d1SSam Leffler 			axf = swd->sw_axf;
1071091d81d1SSam Leffler 
1072091d81d1SSam Leffler 			if (swd->sw_ictx) {
1073091d81d1SSam Leffler 				bzero(swd->sw_ictx, axf->ctxsize);
1074091d81d1SSam Leffler 				free(swd->sw_ictx, M_CRYPTO_DATA);
1075091d81d1SSam Leffler 			}
1076091d81d1SSam Leffler 			if (swd->sw_octx) {
1077091d81d1SSam Leffler 				bzero(swd->sw_octx, swd->sw_klen);
1078091d81d1SSam Leffler 				free(swd->sw_octx, M_CRYPTO_DATA);
1079091d81d1SSam Leffler 			}
1080091d81d1SSam Leffler 			break;
1081091d81d1SSam Leffler 
10820e33efe4SConrad Meyer 		case CRYPTO_BLAKE2B:
10830e33efe4SConrad Meyer 		case CRYPTO_BLAKE2S:
1084091d81d1SSam Leffler 		case CRYPTO_MD5:
108525b7033bSConrad Meyer 		case CRYPTO_POLY1305:
1086091d81d1SSam Leffler 		case CRYPTO_SHA1:
1087c4729f6eSConrad Meyer 		case CRYPTO_SHA2_224:
1088c4729f6eSConrad Meyer 		case CRYPTO_SHA2_256:
1089c4729f6eSConrad Meyer 		case CRYPTO_SHA2_384:
1090c4729f6eSConrad Meyer 		case CRYPTO_SHA2_512:
1091091d81d1SSam Leffler 			axf = swd->sw_axf;
1092091d81d1SSam Leffler 
10935fbc5b5aSConrad Meyer 			if (swd->sw_ictx) {
10945fbc5b5aSConrad Meyer 				explicit_bzero(swd->sw_ictx, axf->ctxsize);
1095091d81d1SSam Leffler 				free(swd->sw_ictx, M_CRYPTO_DATA);
10965fbc5b5aSConrad Meyer 			}
1097091d81d1SSam Leffler 			break;
1098091d81d1SSam Leffler 
1099091d81d1SSam Leffler 		case CRYPTO_DEFLATE_COMP:
1100151ba793SAlexander Kabaev 			/* Nothing to do */
1101091d81d1SSam Leffler 			break;
1102091d81d1SSam Leffler 		}
1103091d81d1SSam Leffler 	}
1104091d81d1SSam Leffler }
1105091d81d1SSam Leffler 
1106091d81d1SSam Leffler /*
1107091d81d1SSam Leffler  * Process a software request.
1108091d81d1SSam Leffler  */
1109091d81d1SSam Leffler static int
11106810ad6fSSam Leffler swcr_process(device_t dev, struct cryptop *crp, int hint)
1111091d81d1SSam Leffler {
1112*9ebbebe4SConrad Meyer 	struct swcr_session *ses;
1113091d81d1SSam Leffler 	struct cryptodesc *crd;
1114*9ebbebe4SConrad Meyer 	struct swcr_data *sw;
1115*9ebbebe4SConrad Meyer 	size_t i;
1116091d81d1SSam Leffler 
1117091d81d1SSam Leffler 	/* Sanity check */
1118091d81d1SSam Leffler 	if (crp == NULL)
1119091d81d1SSam Leffler 		return EINVAL;
1120091d81d1SSam Leffler 
1121091d81d1SSam Leffler 	if (crp->crp_desc == NULL || crp->crp_buf == NULL) {
1122091d81d1SSam Leffler 		crp->crp_etype = EINVAL;
1123091d81d1SSam Leffler 		goto done;
1124091d81d1SSam Leffler 	}
1125091d81d1SSam Leffler 
11261b0909d5SConrad Meyer 	ses = crypto_get_driver_session(crp->crp_session);
1127091d81d1SSam Leffler 
1128091d81d1SSam Leffler 	/* Go through crypto descriptors, processing as we go */
1129091d81d1SSam Leffler 	for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
1130091d81d1SSam Leffler 		/*
1131091d81d1SSam Leffler 		 * Find the crypto context.
1132091d81d1SSam Leffler 		 *
1133091d81d1SSam Leffler 		 * XXX Note that the logic here prevents us from having
1134091d81d1SSam Leffler 		 * XXX the same algorithm multiple times in a session
1135091d81d1SSam Leffler 		 * XXX (or rather, we can but it won't give us the right
1136091d81d1SSam Leffler 		 * XXX results). To do that, we'd need some way of differentiating
1137091d81d1SSam Leffler 		 * XXX between the various instances of an algorithm (so we can
1138091d81d1SSam Leffler 		 * XXX locate the correct crypto context).
1139091d81d1SSam Leffler 		 */
1140*9ebbebe4SConrad Meyer 		for (i = 0; i < nitems(ses->swcr_algorithms) &&
1141*9ebbebe4SConrad Meyer 		    ses->swcr_algorithms[i].sw_alg != crd->crd_alg; i++)
1142091d81d1SSam Leffler 			;
1143091d81d1SSam Leffler 
1144091d81d1SSam Leffler 		/* No such context ? */
1145*9ebbebe4SConrad Meyer 		if (i == nitems(ses->swcr_algorithms)) {
1146091d81d1SSam Leffler 			crp->crp_etype = EINVAL;
1147091d81d1SSam Leffler 			goto done;
1148091d81d1SSam Leffler 		}
1149*9ebbebe4SConrad Meyer 		sw = &ses->swcr_algorithms[i];
1150091d81d1SSam Leffler 		switch (sw->sw_alg) {
1151091d81d1SSam Leffler 		case CRYPTO_DES_CBC:
1152091d81d1SSam Leffler 		case CRYPTO_3DES_CBC:
1153091d81d1SSam Leffler 		case CRYPTO_BLF_CBC:
1154091d81d1SSam Leffler 		case CRYPTO_CAST_CBC:
1155091d81d1SSam Leffler 		case CRYPTO_SKIPJACK_CBC:
1156091d81d1SSam Leffler 		case CRYPTO_RIJNDAEL128_CBC:
1157d295bdeeSPawel Jakub Dawidek 		case CRYPTO_AES_XTS:
115808fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_ICM:
1159559d3390SGeorge V. Neville-Neil 		case CRYPTO_CAMELLIA_CBC:
116061590291SConrad Meyer 		case CRYPTO_CHACHA20:
1161091d81d1SSam Leffler 			if ((crp->crp_etype = swcr_encdec(crd, sw,
1162f34a967bSPawel Jakub Dawidek 			    crp->crp_buf, crp->crp_flags)) != 0)
1163091d81d1SSam Leffler 				goto done;
1164091d81d1SSam Leffler 			break;
1165091d81d1SSam Leffler 		case CRYPTO_NULL_CBC:
1166091d81d1SSam Leffler 			crp->crp_etype = 0;
1167091d81d1SSam Leffler 			break;
1168091d81d1SSam Leffler 		case CRYPTO_MD5_HMAC:
1169091d81d1SSam Leffler 		case CRYPTO_SHA1_HMAC:
1170c97f39ceSConrad Meyer 		case CRYPTO_SHA2_224_HMAC:
1171f6c4bc3bSPawel Jakub Dawidek 		case CRYPTO_SHA2_256_HMAC:
1172f6c4bc3bSPawel Jakub Dawidek 		case CRYPTO_SHA2_384_HMAC:
1173f6c4bc3bSPawel Jakub Dawidek 		case CRYPTO_SHA2_512_HMAC:
1174091d81d1SSam Leffler 		case CRYPTO_RIPEMD160_HMAC:
1175091d81d1SSam Leffler 		case CRYPTO_NULL_HMAC:
1176091d81d1SSam Leffler 		case CRYPTO_MD5_KPDK:
1177091d81d1SSam Leffler 		case CRYPTO_SHA1_KPDK:
1178091d81d1SSam Leffler 		case CRYPTO_MD5:
1179091d81d1SSam Leffler 		case CRYPTO_SHA1:
1180c4729f6eSConrad Meyer 		case CRYPTO_SHA2_224:
1181c4729f6eSConrad Meyer 		case CRYPTO_SHA2_256:
1182c4729f6eSConrad Meyer 		case CRYPTO_SHA2_384:
1183c4729f6eSConrad Meyer 		case CRYPTO_SHA2_512:
11840e33efe4SConrad Meyer 		case CRYPTO_BLAKE2B:
11850e33efe4SConrad Meyer 		case CRYPTO_BLAKE2S:
118625b7033bSConrad Meyer 		case CRYPTO_POLY1305:
118738d2f8d6SPawel Jakub Dawidek 			if ((crp->crp_etype = swcr_authcompute(crd, sw,
1188f34a967bSPawel Jakub Dawidek 			    crp->crp_buf, crp->crp_flags)) != 0)
1189091d81d1SSam Leffler 				goto done;
1190091d81d1SSam Leffler 			break;
1191091d81d1SSam Leffler 
119208fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_NIST_GCM_16:
119308fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_NIST_GMAC:
119408fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_128_NIST_GMAC:
119508fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_192_NIST_GMAC:
119608fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_256_NIST_GMAC:
119708fca7a5SJohn-Mark Gurney 			crp->crp_etype = swcr_authenc(crp);
119808fca7a5SJohn-Mark Gurney 			goto done;
119908fca7a5SJohn-Mark Gurney 
1200091d81d1SSam Leffler 		case CRYPTO_DEFLATE_COMP:
1201091d81d1SSam Leffler 			if ((crp->crp_etype = swcr_compdec(crd, sw,
1202f34a967bSPawel Jakub Dawidek 			    crp->crp_buf, crp->crp_flags)) != 0)
1203091d81d1SSam Leffler 				goto done;
1204091d81d1SSam Leffler 			else
1205091d81d1SSam Leffler 				crp->crp_olen = (int)sw->sw_size;
1206091d81d1SSam Leffler 			break;
1207091d81d1SSam Leffler 
1208091d81d1SSam Leffler 		default:
1209091d81d1SSam Leffler 			/* Unknown/unsupported algorithm */
1210091d81d1SSam Leffler 			crp->crp_etype = EINVAL;
1211091d81d1SSam Leffler 			goto done;
1212091d81d1SSam Leffler 		}
1213091d81d1SSam Leffler 	}
1214091d81d1SSam Leffler 
1215091d81d1SSam Leffler done:
1216091d81d1SSam Leffler 	crypto_done(crp);
1217091d81d1SSam Leffler 	return 0;
1218091d81d1SSam Leffler }
1219091d81d1SSam Leffler 
1220091d81d1SSam Leffler static void
12213f147ab2SWarner Losh swcr_identify(driver_t *drv, device_t parent)
1222091d81d1SSam Leffler {
12236810ad6fSSam Leffler 	/* NB: order 10 is so we get attached after h/w devices */
12246810ad6fSSam Leffler 	if (device_find_child(parent, "cryptosoft", -1) == NULL &&
122586c585d9SMarius Strobl 	    BUS_ADD_CHILD(parent, 10, "cryptosoft", 0) == 0)
12266810ad6fSSam Leffler 		panic("cryptosoft: could not attach");
12276810ad6fSSam Leffler }
1228f6c4bc3bSPawel Jakub Dawidek 
12296810ad6fSSam Leffler static int
12306810ad6fSSam Leffler swcr_probe(device_t dev)
12316810ad6fSSam Leffler {
12326810ad6fSSam Leffler 	device_set_desc(dev, "software crypto");
123386c585d9SMarius Strobl 	return (BUS_PROBE_NOWILDCARD);
12346810ad6fSSam Leffler }
1235f6c4bc3bSPawel Jakub Dawidek 
12366810ad6fSSam Leffler static int
12376810ad6fSSam Leffler swcr_attach(device_t dev)
12386810ad6fSSam Leffler {
12396810ad6fSSam Leffler 	memset(hmac_ipad_buffer, HMAC_IPAD_VAL, HMAC_MAX_BLOCK_LEN);
12406810ad6fSSam Leffler 	memset(hmac_opad_buffer, HMAC_OPAD_VAL, HMAC_MAX_BLOCK_LEN);
12416810ad6fSSam Leffler 
1242*9ebbebe4SConrad Meyer 	swcr_id = crypto_get_driverid(dev, sizeof(struct swcr_session),
12436810ad6fSSam Leffler 			CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC);
12446810ad6fSSam Leffler 	if (swcr_id < 0) {
12456810ad6fSSam Leffler 		device_printf(dev, "cannot initialize!");
12466810ad6fSSam Leffler 		return ENOMEM;
12476810ad6fSSam Leffler 	}
1248091d81d1SSam Leffler #define	REGISTER(alg) \
12496810ad6fSSam Leffler 	crypto_register(swcr_id, alg, 0,0)
12506810ad6fSSam Leffler 	REGISTER(CRYPTO_DES_CBC);
1251091d81d1SSam Leffler 	REGISTER(CRYPTO_3DES_CBC);
1252091d81d1SSam Leffler 	REGISTER(CRYPTO_BLF_CBC);
1253091d81d1SSam Leffler 	REGISTER(CRYPTO_CAST_CBC);
1254091d81d1SSam Leffler 	REGISTER(CRYPTO_SKIPJACK_CBC);
1255091d81d1SSam Leffler 	REGISTER(CRYPTO_NULL_CBC);
1256091d81d1SSam Leffler 	REGISTER(CRYPTO_MD5_HMAC);
1257091d81d1SSam Leffler 	REGISTER(CRYPTO_SHA1_HMAC);
1258c97f39ceSConrad Meyer 	REGISTER(CRYPTO_SHA2_224_HMAC);
1259f6c4bc3bSPawel Jakub Dawidek 	REGISTER(CRYPTO_SHA2_256_HMAC);
1260f6c4bc3bSPawel Jakub Dawidek 	REGISTER(CRYPTO_SHA2_384_HMAC);
1261f6c4bc3bSPawel Jakub Dawidek 	REGISTER(CRYPTO_SHA2_512_HMAC);
1262091d81d1SSam Leffler 	REGISTER(CRYPTO_RIPEMD160_HMAC);
1263091d81d1SSam Leffler 	REGISTER(CRYPTO_NULL_HMAC);
1264091d81d1SSam Leffler 	REGISTER(CRYPTO_MD5_KPDK);
1265091d81d1SSam Leffler 	REGISTER(CRYPTO_SHA1_KPDK);
1266091d81d1SSam Leffler 	REGISTER(CRYPTO_MD5);
1267091d81d1SSam Leffler 	REGISTER(CRYPTO_SHA1);
1268c4729f6eSConrad Meyer 	REGISTER(CRYPTO_SHA2_224);
1269c4729f6eSConrad Meyer 	REGISTER(CRYPTO_SHA2_256);
1270c4729f6eSConrad Meyer 	REGISTER(CRYPTO_SHA2_384);
1271c4729f6eSConrad Meyer 	REGISTER(CRYPTO_SHA2_512);
1272091d81d1SSam Leffler 	REGISTER(CRYPTO_RIJNDAEL128_CBC);
1273d295bdeeSPawel Jakub Dawidek 	REGISTER(CRYPTO_AES_XTS);
127408fca7a5SJohn-Mark Gurney 	REGISTER(CRYPTO_AES_ICM);
127508fca7a5SJohn-Mark Gurney 	REGISTER(CRYPTO_AES_NIST_GCM_16);
127608fca7a5SJohn-Mark Gurney 	REGISTER(CRYPTO_AES_NIST_GMAC);
127708fca7a5SJohn-Mark Gurney 	REGISTER(CRYPTO_AES_128_NIST_GMAC);
127808fca7a5SJohn-Mark Gurney 	REGISTER(CRYPTO_AES_192_NIST_GMAC);
127908fca7a5SJohn-Mark Gurney 	REGISTER(CRYPTO_AES_256_NIST_GMAC);
1280559d3390SGeorge V. Neville-Neil  	REGISTER(CRYPTO_CAMELLIA_CBC);
1281091d81d1SSam Leffler 	REGISTER(CRYPTO_DEFLATE_COMP);
12820e33efe4SConrad Meyer 	REGISTER(CRYPTO_BLAKE2B);
12830e33efe4SConrad Meyer 	REGISTER(CRYPTO_BLAKE2S);
128461590291SConrad Meyer 	REGISTER(CRYPTO_CHACHA20);
128525b7033bSConrad Meyer 	REGISTER(CRYPTO_POLY1305);
1286091d81d1SSam Leffler #undef REGISTER
12876810ad6fSSam Leffler 
12886810ad6fSSam Leffler 	return 0;
1289091d81d1SSam Leffler }
12904b465da2SPawel Jakub Dawidek 
12913f147ab2SWarner Losh static int
12926810ad6fSSam Leffler swcr_detach(device_t dev)
12934b465da2SPawel Jakub Dawidek {
12946810ad6fSSam Leffler 	crypto_unregister_all(swcr_id);
12953f147ab2SWarner Losh 	return 0;
12964b465da2SPawel Jakub Dawidek }
12976810ad6fSSam Leffler 
12986810ad6fSSam Leffler static device_method_t swcr_methods[] = {
12996810ad6fSSam Leffler 	DEVMETHOD(device_identify,	swcr_identify),
13006810ad6fSSam Leffler 	DEVMETHOD(device_probe,		swcr_probe),
13016810ad6fSSam Leffler 	DEVMETHOD(device_attach,	swcr_attach),
13026810ad6fSSam Leffler 	DEVMETHOD(device_detach,	swcr_detach),
13036810ad6fSSam Leffler 
13046810ad6fSSam Leffler 	DEVMETHOD(cryptodev_newsession,	swcr_newsession),
13056810ad6fSSam Leffler 	DEVMETHOD(cryptodev_freesession,swcr_freesession),
13066810ad6fSSam Leffler 	DEVMETHOD(cryptodev_process,	swcr_process),
13076810ad6fSSam Leffler 
13086810ad6fSSam Leffler 	{0, 0},
13096810ad6fSSam Leffler };
13106810ad6fSSam Leffler 
13116810ad6fSSam Leffler static driver_t swcr_driver = {
13126810ad6fSSam Leffler 	"cryptosoft",
13136810ad6fSSam Leffler 	swcr_methods,
13146810ad6fSSam Leffler 	0,		/* NB: no softc */
13156810ad6fSSam Leffler };
13166810ad6fSSam Leffler static devclass_t swcr_devclass;
13176810ad6fSSam Leffler 
13186810ad6fSSam Leffler /*
13196810ad6fSSam Leffler  * NB: We explicitly reference the crypto module so we
13206810ad6fSSam Leffler  * get the necessary ordering when built as a loadable
13216810ad6fSSam Leffler  * module.  This is required because we bundle the crypto
13226810ad6fSSam Leffler  * module code together with the cryptosoft driver (otherwise
13236810ad6fSSam Leffler  * normal module dependencies would handle things).
13246810ad6fSSam Leffler  */
13256810ad6fSSam Leffler extern int crypto_modevent(struct module *, int, void *);
13266810ad6fSSam Leffler /* XXX where to attach */
13276810ad6fSSam Leffler DRIVER_MODULE(cryptosoft, nexus, swcr_driver, swcr_devclass, crypto_modevent,0);
13286810ad6fSSam Leffler MODULE_VERSION(cryptosoft, 1);
13296810ad6fSSam Leffler MODULE_DEPEND(cryptosoft, crypto, 1, 1, 1);
1330