xref: /freebsd/sys/opencrypto/cryptosoft.c (revision 25b7033b)
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;
50008fca7a5SJohn-Mark Gurney 	struct cryptodesc *crd, *crda = NULL, *crde = NULL;
50108fca7a5SJohn-Mark Gurney 	struct swcr_data *sw, *swa, *swe = NULL;
50208fca7a5SJohn-Mark Gurney 	struct auth_hash *axf = NULL;
50308fca7a5SJohn-Mark Gurney 	struct enc_xform *exf = NULL;
50408fca7a5SJohn-Mark Gurney 	caddr_t buf = (caddr_t)crp->crp_buf;
50508fca7a5SJohn-Mark Gurney 	uint32_t *blkp;
50608fca7a5SJohn-Mark Gurney 	int aadlen, blksz, i, ivlen, len, iskip, oskip, r;
50708fca7a5SJohn-Mark Gurney 
50808fca7a5SJohn-Mark Gurney 	ivlen = blksz = iskip = oskip = 0;
50908fca7a5SJohn-Mark Gurney 
51008fca7a5SJohn-Mark Gurney 	for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
5111b0909d5SConrad Meyer 		for (sw = crypto_get_driver_session(crp->crp_session);
51208fca7a5SJohn-Mark Gurney 		     sw && sw->sw_alg != crd->crd_alg;
51308fca7a5SJohn-Mark Gurney 		     sw = sw->sw_next)
51408fca7a5SJohn-Mark Gurney 			;
51508fca7a5SJohn-Mark Gurney 		if (sw == NULL)
51608fca7a5SJohn-Mark Gurney 			return (EINVAL);
51708fca7a5SJohn-Mark Gurney 
51808fca7a5SJohn-Mark Gurney 		switch (sw->sw_alg) {
51908fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_NIST_GCM_16:
52008fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_NIST_GMAC:
52108fca7a5SJohn-Mark Gurney 			swe = sw;
52208fca7a5SJohn-Mark Gurney 			crde = crd;
52308fca7a5SJohn-Mark Gurney 			exf = swe->sw_exf;
52408fca7a5SJohn-Mark Gurney 			ivlen = 12;
52508fca7a5SJohn-Mark Gurney 			break;
52608fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_128_NIST_GMAC:
52708fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_192_NIST_GMAC:
52808fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_256_NIST_GMAC:
52908fca7a5SJohn-Mark Gurney 			swa = sw;
53008fca7a5SJohn-Mark Gurney 			crda = crd;
53108fca7a5SJohn-Mark Gurney 			axf = swa->sw_axf;
53208fca7a5SJohn-Mark Gurney 			if (swa->sw_ictx == 0)
53308fca7a5SJohn-Mark Gurney 				return (EINVAL);
53408fca7a5SJohn-Mark Gurney 			bcopy(swa->sw_ictx, &ctx, axf->ctxsize);
53508fca7a5SJohn-Mark Gurney 			blksz = axf->blocksize;
53608fca7a5SJohn-Mark Gurney 			break;
53708fca7a5SJohn-Mark Gurney 		default:
53808fca7a5SJohn-Mark Gurney 			return (EINVAL);
53908fca7a5SJohn-Mark Gurney 		}
54008fca7a5SJohn-Mark Gurney 	}
54108fca7a5SJohn-Mark Gurney 	if (crde == NULL || crda == NULL)
54208fca7a5SJohn-Mark Gurney 		return (EINVAL);
54308fca7a5SJohn-Mark Gurney 
54408fca7a5SJohn-Mark Gurney 	if (crde->crd_alg == CRYPTO_AES_NIST_GCM_16 &&
54508fca7a5SJohn-Mark Gurney 	    (crde->crd_flags & CRD_F_IV_EXPLICIT) == 0)
54608fca7a5SJohn-Mark Gurney 		return (EINVAL);
54708fca7a5SJohn-Mark Gurney 
54808fca7a5SJohn-Mark Gurney 	if (crde->crd_klen != crda->crd_klen)
54908fca7a5SJohn-Mark Gurney 		return (EINVAL);
55008fca7a5SJohn-Mark Gurney 
55108fca7a5SJohn-Mark Gurney 	/* Initialize the IV */
55208fca7a5SJohn-Mark Gurney 	if (crde->crd_flags & CRD_F_ENCRYPT) {
55308fca7a5SJohn-Mark Gurney 		/* IV explicitly provided ? */
55408fca7a5SJohn-Mark Gurney 		if (crde->crd_flags & CRD_F_IV_EXPLICIT)
55508fca7a5SJohn-Mark Gurney 			bcopy(crde->crd_iv, iv, ivlen);
55608fca7a5SJohn-Mark Gurney 		else
55708fca7a5SJohn-Mark Gurney 			arc4rand(iv, ivlen, 0);
55808fca7a5SJohn-Mark Gurney 
55908fca7a5SJohn-Mark Gurney 		/* Do we need to write the IV */
56008fca7a5SJohn-Mark Gurney 		if (!(crde->crd_flags & CRD_F_IV_PRESENT))
56108fca7a5SJohn-Mark Gurney 			crypto_copyback(crp->crp_flags, buf, crde->crd_inject,
56208fca7a5SJohn-Mark Gurney 			    ivlen, iv);
56308fca7a5SJohn-Mark Gurney 
56408fca7a5SJohn-Mark Gurney 	} else {	/* Decryption */
56508fca7a5SJohn-Mark Gurney 			/* IV explicitly provided ? */
56608fca7a5SJohn-Mark Gurney 		if (crde->crd_flags & CRD_F_IV_EXPLICIT)
56708fca7a5SJohn-Mark Gurney 			bcopy(crde->crd_iv, iv, ivlen);
56808fca7a5SJohn-Mark Gurney 		else {
56908fca7a5SJohn-Mark Gurney 			/* Get IV off buf */
57008fca7a5SJohn-Mark Gurney 			crypto_copydata(crp->crp_flags, buf, crde->crd_inject,
57108fca7a5SJohn-Mark Gurney 			    ivlen, iv);
57208fca7a5SJohn-Mark Gurney 		}
57308fca7a5SJohn-Mark Gurney 	}
57408fca7a5SJohn-Mark Gurney 
57508fca7a5SJohn-Mark Gurney 	/* Supply MAC with IV */
57608fca7a5SJohn-Mark Gurney 	if (axf->Reinit)
57708fca7a5SJohn-Mark Gurney 		axf->Reinit(&ctx, iv, ivlen);
57808fca7a5SJohn-Mark Gurney 
57908fca7a5SJohn-Mark Gurney 	/* Supply MAC with AAD */
58008fca7a5SJohn-Mark Gurney 	aadlen = crda->crd_len;
58108fca7a5SJohn-Mark Gurney 
58208fca7a5SJohn-Mark Gurney 	for (i = iskip; i < crda->crd_len; i += blksz) {
58308fca7a5SJohn-Mark Gurney 		len = MIN(crda->crd_len - i, blksz - oskip);
58408fca7a5SJohn-Mark Gurney 		crypto_copydata(crp->crp_flags, buf, crda->crd_skip + i, len,
58508fca7a5SJohn-Mark Gurney 		    blk + oskip);
58608fca7a5SJohn-Mark Gurney 		bzero(blk + len + oskip, blksz - len - oskip);
58708fca7a5SJohn-Mark Gurney 		axf->Update(&ctx, blk, blksz);
58808fca7a5SJohn-Mark Gurney 		oskip = 0; /* reset initial output offset */
58908fca7a5SJohn-Mark Gurney 	}
59008fca7a5SJohn-Mark Gurney 
59108fca7a5SJohn-Mark Gurney 	if (exf->reinit)
59208fca7a5SJohn-Mark Gurney 		exf->reinit(swe->sw_kschedule, iv);
59308fca7a5SJohn-Mark Gurney 
59408fca7a5SJohn-Mark Gurney 	/* Do encryption/decryption with MAC */
5952f1f9cceSConrad Meyer 	for (i = 0; i < crde->crd_len; i += len) {
5962f1f9cceSConrad Meyer 		if (exf->encrypt_multi != NULL) {
5972f1f9cceSConrad Meyer 			len = rounddown(crde->crd_len - i, blksz);
5982f1f9cceSConrad Meyer 			if (len == 0)
5992f1f9cceSConrad Meyer 				len = blksz;
6002f1f9cceSConrad Meyer 			else
6012f1f9cceSConrad Meyer 				len = MIN(len, sizeof(blkbuf));
6022f1f9cceSConrad Meyer 		} else
6032f1f9cceSConrad Meyer 			len = blksz;
6042f1f9cceSConrad Meyer 		len = MIN(crde->crd_len - i, len);
60508fca7a5SJohn-Mark Gurney 		if (len < blksz)
60608fca7a5SJohn-Mark Gurney 			bzero(blk, blksz);
60708fca7a5SJohn-Mark Gurney 		crypto_copydata(crp->crp_flags, buf, crde->crd_skip + i, len,
60808fca7a5SJohn-Mark Gurney 		    blk);
60908fca7a5SJohn-Mark Gurney 		if (crde->crd_flags & CRD_F_ENCRYPT) {
6102f1f9cceSConrad Meyer 			if (exf->encrypt_multi != NULL)
6112f1f9cceSConrad Meyer 				exf->encrypt_multi(swe->sw_kschedule, blk,
6122f1f9cceSConrad Meyer 				    len);
6132f1f9cceSConrad Meyer 			else
61408fca7a5SJohn-Mark Gurney 				exf->encrypt(swe->sw_kschedule, blk);
61508fca7a5SJohn-Mark Gurney 			axf->Update(&ctx, blk, len);
61608fca7a5SJohn-Mark Gurney 			crypto_copyback(crp->crp_flags, buf,
61708fca7a5SJohn-Mark Gurney 			    crde->crd_skip + i, len, blk);
61808fca7a5SJohn-Mark Gurney 		} else {
61908fca7a5SJohn-Mark Gurney 			axf->Update(&ctx, blk, len);
62008fca7a5SJohn-Mark Gurney 		}
62108fca7a5SJohn-Mark Gurney 	}
62208fca7a5SJohn-Mark Gurney 
62308fca7a5SJohn-Mark Gurney 	/* Do any required special finalization */
62408fca7a5SJohn-Mark Gurney 	switch (crda->crd_alg) {
62508fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_128_NIST_GMAC:
62608fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_192_NIST_GMAC:
62708fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_256_NIST_GMAC:
62808fca7a5SJohn-Mark Gurney 			/* length block */
62908fca7a5SJohn-Mark Gurney 			bzero(blk, blksz);
63008fca7a5SJohn-Mark Gurney 			blkp = (uint32_t *)blk + 1;
63108fca7a5SJohn-Mark Gurney 			*blkp = htobe32(aadlen * 8);
63208fca7a5SJohn-Mark Gurney 			blkp = (uint32_t *)blk + 3;
63308fca7a5SJohn-Mark Gurney 			*blkp = htobe32(crde->crd_len * 8);
63408fca7a5SJohn-Mark Gurney 			axf->Update(&ctx, blk, blksz);
63508fca7a5SJohn-Mark Gurney 			break;
63608fca7a5SJohn-Mark Gurney 	}
63708fca7a5SJohn-Mark Gurney 
63808fca7a5SJohn-Mark Gurney 	/* Finalize MAC */
63908fca7a5SJohn-Mark Gurney 	axf->Final(aalg, &ctx);
64008fca7a5SJohn-Mark Gurney 
64108fca7a5SJohn-Mark Gurney 	/* Validate tag */
64208fca7a5SJohn-Mark Gurney 	if (!(crde->crd_flags & CRD_F_ENCRYPT)) {
64308fca7a5SJohn-Mark Gurney 		crypto_copydata(crp->crp_flags, buf, crda->crd_inject,
64408fca7a5SJohn-Mark Gurney 		    axf->hashsize, uaalg);
64508fca7a5SJohn-Mark Gurney 
64608fca7a5SJohn-Mark Gurney 		r = timingsafe_bcmp(aalg, uaalg, axf->hashsize);
64708fca7a5SJohn-Mark Gurney 		if (r == 0) {
64808fca7a5SJohn-Mark Gurney 			/* tag matches, decrypt data */
64908fca7a5SJohn-Mark Gurney 			for (i = 0; i < crde->crd_len; i += blksz) {
65008fca7a5SJohn-Mark Gurney 				len = MIN(crde->crd_len - i, blksz);
65108fca7a5SJohn-Mark Gurney 				if (len < blksz)
65208fca7a5SJohn-Mark Gurney 					bzero(blk, blksz);
65308fca7a5SJohn-Mark Gurney 				crypto_copydata(crp->crp_flags, buf,
65408fca7a5SJohn-Mark Gurney 				    crde->crd_skip + i, len, blk);
65508fca7a5SJohn-Mark Gurney 				exf->decrypt(swe->sw_kschedule, blk);
65608fca7a5SJohn-Mark Gurney 				crypto_copyback(crp->crp_flags, buf,
65708fca7a5SJohn-Mark Gurney 				    crde->crd_skip + i, len, blk);
65808fca7a5SJohn-Mark Gurney 			}
65908fca7a5SJohn-Mark Gurney 		} else
66008fca7a5SJohn-Mark Gurney 			return (EBADMSG);
66108fca7a5SJohn-Mark Gurney 	} else {
66208fca7a5SJohn-Mark Gurney 		/* Inject the authentication data */
66308fca7a5SJohn-Mark Gurney 		crypto_copyback(crp->crp_flags, buf, crda->crd_inject,
66408fca7a5SJohn-Mark Gurney 		    axf->hashsize, aalg);
66508fca7a5SJohn-Mark Gurney 	}
66608fca7a5SJohn-Mark Gurney 
66708fca7a5SJohn-Mark Gurney 	return (0);
66808fca7a5SJohn-Mark Gurney }
66908fca7a5SJohn-Mark Gurney 
670091d81d1SSam Leffler /*
671091d81d1SSam Leffler  * Apply a compression/decompression algorithm
672091d81d1SSam Leffler  */
673091d81d1SSam Leffler static int
674091d81d1SSam Leffler swcr_compdec(struct cryptodesc *crd, struct swcr_data *sw,
675f34a967bSPawel Jakub Dawidek     caddr_t buf, int flags)
676091d81d1SSam Leffler {
677091d81d1SSam Leffler 	u_int8_t *data, *out;
678091d81d1SSam Leffler 	struct comp_algo *cxf;
679091d81d1SSam Leffler 	int adj;
680091d81d1SSam Leffler 	u_int32_t result;
681091d81d1SSam Leffler 
682091d81d1SSam Leffler 	cxf = sw->sw_cxf;
683091d81d1SSam Leffler 
684091d81d1SSam Leffler 	/* We must handle the whole buffer of data in one time
685091d81d1SSam Leffler 	 * then if there is not all the data in the mbuf, we must
686091d81d1SSam Leffler 	 * copy in a buffer.
687091d81d1SSam Leffler 	 */
688091d81d1SSam Leffler 
6891ede983cSDag-Erling Smørgrav 	data = malloc(crd->crd_len, M_CRYPTO_DATA,  M_NOWAIT);
690091d81d1SSam Leffler 	if (data == NULL)
691091d81d1SSam Leffler 		return (EINVAL);
692f34a967bSPawel Jakub Dawidek 	crypto_copydata(flags, buf, crd->crd_skip, crd->crd_len, data);
693091d81d1SSam Leffler 
694091d81d1SSam Leffler 	if (crd->crd_flags & CRD_F_COMP)
695091d81d1SSam Leffler 		result = cxf->compress(data, crd->crd_len, &out);
696091d81d1SSam Leffler 	else
697091d81d1SSam Leffler 		result = cxf->decompress(data, crd->crd_len, &out);
698091d81d1SSam Leffler 
6991ede983cSDag-Erling Smørgrav 	free(data, M_CRYPTO_DATA);
700091d81d1SSam Leffler 	if (result == 0)
701091d81d1SSam Leffler 		return EINVAL;
702091d81d1SSam Leffler 
703091d81d1SSam Leffler 	/* Copy back the (de)compressed data. m_copyback is
704091d81d1SSam Leffler 	 * extending the mbuf as necessary.
705091d81d1SSam Leffler 	 */
706091d81d1SSam Leffler 	sw->sw_size = result;
707091d81d1SSam Leffler 	/* Check the compressed size when doing compression */
708091d81d1SSam Leffler 	if (crd->crd_flags & CRD_F_COMP) {
709df4dece1SBjoern A. Zeeb 		if (result >= crd->crd_len) {
710091d81d1SSam Leffler 			/* Compression was useless, we lost time */
7111ede983cSDag-Erling Smørgrav 			free(out, M_CRYPTO_DATA);
712091d81d1SSam Leffler 			return 0;
713091d81d1SSam Leffler 		}
714091d81d1SSam Leffler 	}
715091d81d1SSam Leffler 
716f34a967bSPawel Jakub Dawidek 	crypto_copyback(flags, buf, crd->crd_skip, result, out);
717091d81d1SSam Leffler 	if (result < crd->crd_len) {
718091d81d1SSam Leffler 		adj = result - crd->crd_len;
719f34a967bSPawel Jakub Dawidek 		if (flags & CRYPTO_F_IMBUF) {
720091d81d1SSam Leffler 			adj = result - crd->crd_len;
721091d81d1SSam Leffler 			m_adj((struct mbuf *)buf, adj);
722f34a967bSPawel Jakub Dawidek 		} else if (flags & CRYPTO_F_IOV) {
723091d81d1SSam Leffler 			struct uio *uio = (struct uio *)buf;
724091d81d1SSam Leffler 			int ind;
725091d81d1SSam Leffler 
726091d81d1SSam Leffler 			adj = crd->crd_len - result;
727091d81d1SSam Leffler 			ind = uio->uio_iovcnt - 1;
728091d81d1SSam Leffler 
729091d81d1SSam Leffler 			while (adj > 0 && ind >= 0) {
730091d81d1SSam Leffler 				if (adj < uio->uio_iov[ind].iov_len) {
731091d81d1SSam Leffler 					uio->uio_iov[ind].iov_len -= adj;
732091d81d1SSam Leffler 					break;
733091d81d1SSam Leffler 				}
734091d81d1SSam Leffler 
735091d81d1SSam Leffler 				adj -= uio->uio_iov[ind].iov_len;
736091d81d1SSam Leffler 				uio->uio_iov[ind].iov_len = 0;
737091d81d1SSam Leffler 				ind--;
738091d81d1SSam Leffler 				uio->uio_iovcnt--;
739091d81d1SSam Leffler 			}
740091d81d1SSam Leffler 		}
741091d81d1SSam Leffler 	}
7421ede983cSDag-Erling Smørgrav 	free(out, M_CRYPTO_DATA);
743091d81d1SSam Leffler 	return 0;
744091d81d1SSam Leffler }
745091d81d1SSam Leffler 
746091d81d1SSam Leffler /*
747091d81d1SSam Leffler  * Generate a new software session.
748091d81d1SSam Leffler  */
749091d81d1SSam Leffler static int
7501b0909d5SConrad Meyer swcr_newsession(device_t dev, crypto_session_t cses, struct cryptoini *cri)
751091d81d1SSam Leffler {
7521b0909d5SConrad Meyer 	struct swcr_data **swd, *ses;
753091d81d1SSam Leffler 	struct auth_hash *axf;
754091d81d1SSam Leffler 	struct enc_xform *txf;
755091d81d1SSam Leffler 	struct comp_algo *cxf;
756a2bc81bfSJohn-Mark Gurney 	int len;
757f6c4bc3bSPawel Jakub Dawidek 	int error;
758091d81d1SSam Leffler 
7591b0909d5SConrad Meyer 	if (cses == NULL || cri == NULL)
760091d81d1SSam Leffler 		return EINVAL;
761091d81d1SSam Leffler 
7621b0909d5SConrad Meyer 	ses = crypto_get_driver_session(cses);
7631b0909d5SConrad Meyer 	swd = &ses;
764091d81d1SSam Leffler 
765091d81d1SSam Leffler 	while (cri) {
7661b0909d5SConrad Meyer 		if (*swd == NULL)
7671ede983cSDag-Erling Smørgrav 			*swd = malloc(sizeof(struct swcr_data),
7681b0909d5SConrad Meyer 			    M_CRYPTO_DATA, M_WAITOK | M_ZERO);
769091d81d1SSam Leffler 		if (*swd == NULL) {
7701b0909d5SConrad Meyer 			swcr_freesession(dev, cses);
771091d81d1SSam Leffler 			return ENOBUFS;
772091d81d1SSam Leffler 		}
773091d81d1SSam Leffler 
774091d81d1SSam Leffler 		switch (cri->cri_alg) {
775091d81d1SSam Leffler 		case CRYPTO_DES_CBC:
776091d81d1SSam Leffler 			txf = &enc_xform_des;
777091d81d1SSam Leffler 			goto enccommon;
778091d81d1SSam Leffler 		case CRYPTO_3DES_CBC:
779091d81d1SSam Leffler 			txf = &enc_xform_3des;
780091d81d1SSam Leffler 			goto enccommon;
781091d81d1SSam Leffler 		case CRYPTO_BLF_CBC:
782091d81d1SSam Leffler 			txf = &enc_xform_blf;
783091d81d1SSam Leffler 			goto enccommon;
784091d81d1SSam Leffler 		case CRYPTO_CAST_CBC:
785091d81d1SSam Leffler 			txf = &enc_xform_cast5;
786091d81d1SSam Leffler 			goto enccommon;
787091d81d1SSam Leffler 		case CRYPTO_SKIPJACK_CBC:
788091d81d1SSam Leffler 			txf = &enc_xform_skipjack;
789091d81d1SSam Leffler 			goto enccommon;
790091d81d1SSam Leffler 		case CRYPTO_RIJNDAEL128_CBC:
791091d81d1SSam Leffler 			txf = &enc_xform_rijndael128;
792091d81d1SSam Leffler 			goto enccommon;
793d295bdeeSPawel Jakub Dawidek 		case CRYPTO_AES_XTS:
794d295bdeeSPawel Jakub Dawidek 			txf = &enc_xform_aes_xts;
795d295bdeeSPawel Jakub Dawidek 			goto enccommon;
79608fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_ICM:
79708fca7a5SJohn-Mark Gurney 			txf = &enc_xform_aes_icm;
79808fca7a5SJohn-Mark Gurney 			goto enccommon;
79908fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_NIST_GCM_16:
80008fca7a5SJohn-Mark Gurney 			txf = &enc_xform_aes_nist_gcm;
80108fca7a5SJohn-Mark Gurney 			goto enccommon;
80208fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_NIST_GMAC:
80308fca7a5SJohn-Mark Gurney 			txf = &enc_xform_aes_nist_gmac;
80408fca7a5SJohn-Mark Gurney 			(*swd)->sw_exf = txf;
80508fca7a5SJohn-Mark Gurney 			break;
806559d3390SGeorge V. Neville-Neil 		case CRYPTO_CAMELLIA_CBC:
807559d3390SGeorge V. Neville-Neil 			txf = &enc_xform_camellia;
808559d3390SGeorge V. Neville-Neil 			goto enccommon;
809091d81d1SSam Leffler 		case CRYPTO_NULL_CBC:
810091d81d1SSam Leffler 			txf = &enc_xform_null;
811091d81d1SSam Leffler 			goto enccommon;
81261590291SConrad Meyer 		case CRYPTO_CHACHA20:
81361590291SConrad Meyer 			txf = &enc_xform_chacha20;
81461590291SConrad Meyer 			goto enccommon;
815091d81d1SSam Leffler 		enccommon:
816f6c4bc3bSPawel Jakub Dawidek 			if (cri->cri_key != NULL) {
817091d81d1SSam Leffler 				error = txf->setkey(&((*swd)->sw_kschedule),
818091d81d1SSam Leffler 				    cri->cri_key, cri->cri_klen / 8);
819091d81d1SSam Leffler 				if (error) {
8201b0909d5SConrad Meyer 					swcr_freesession(dev, cses);
821091d81d1SSam Leffler 					return error;
822091d81d1SSam Leffler 				}
823f6c4bc3bSPawel Jakub Dawidek 			}
824091d81d1SSam Leffler 			(*swd)->sw_exf = txf;
825091d81d1SSam Leffler 			break;
826091d81d1SSam Leffler 
827091d81d1SSam Leffler 		case CRYPTO_MD5_HMAC:
828f6c4bc3bSPawel Jakub Dawidek 			axf = &auth_hash_hmac_md5;
829091d81d1SSam Leffler 			goto authcommon;
830091d81d1SSam Leffler 		case CRYPTO_SHA1_HMAC:
831f6c4bc3bSPawel Jakub Dawidek 			axf = &auth_hash_hmac_sha1;
832091d81d1SSam Leffler 			goto authcommon;
833c97f39ceSConrad Meyer 		case CRYPTO_SHA2_224_HMAC:
834c97f39ceSConrad Meyer 			axf = &auth_hash_hmac_sha2_224;
835c97f39ceSConrad Meyer 			goto authcommon;
836f6c4bc3bSPawel Jakub Dawidek 		case CRYPTO_SHA2_256_HMAC:
837091d81d1SSam Leffler 			axf = &auth_hash_hmac_sha2_256;
838f6c4bc3bSPawel Jakub Dawidek 			goto authcommon;
839f6c4bc3bSPawel Jakub Dawidek 		case CRYPTO_SHA2_384_HMAC:
840091d81d1SSam Leffler 			axf = &auth_hash_hmac_sha2_384;
841f6c4bc3bSPawel Jakub Dawidek 			goto authcommon;
842f6c4bc3bSPawel Jakub Dawidek 		case CRYPTO_SHA2_512_HMAC:
843091d81d1SSam Leffler 			axf = &auth_hash_hmac_sha2_512;
844091d81d1SSam Leffler 			goto authcommon;
845091d81d1SSam Leffler 		case CRYPTO_NULL_HMAC:
846091d81d1SSam Leffler 			axf = &auth_hash_null;
847091d81d1SSam Leffler 			goto authcommon;
848091d81d1SSam Leffler 		case CRYPTO_RIPEMD160_HMAC:
849f6c4bc3bSPawel Jakub Dawidek 			axf = &auth_hash_hmac_ripemd_160;
850091d81d1SSam Leffler 		authcommon:
851091d81d1SSam Leffler 			(*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
852091d81d1SSam Leffler 			    M_NOWAIT);
853091d81d1SSam Leffler 			if ((*swd)->sw_ictx == NULL) {
8541b0909d5SConrad Meyer 				swcr_freesession(dev, cses);
855091d81d1SSam Leffler 				return ENOBUFS;
856091d81d1SSam Leffler 			}
857091d81d1SSam Leffler 
858091d81d1SSam Leffler 			(*swd)->sw_octx = malloc(axf->ctxsize, M_CRYPTO_DATA,
859091d81d1SSam Leffler 			    M_NOWAIT);
860091d81d1SSam Leffler 			if ((*swd)->sw_octx == NULL) {
8611b0909d5SConrad Meyer 				swcr_freesession(dev, cses);
862091d81d1SSam Leffler 				return ENOBUFS;
863091d81d1SSam Leffler 			}
864091d81d1SSam Leffler 
865f6c4bc3bSPawel Jakub Dawidek 			if (cri->cri_key != NULL) {
86625b7033bSConrad Meyer 				error = swcr_authprepare(axf, *swd,
86725b7033bSConrad Meyer 				    cri->cri_key, cri->cri_klen);
86825b7033bSConrad Meyer 				if (error != 0) {
86925b7033bSConrad Meyer 					swcr_freesession(dev, cses);
87025b7033bSConrad Meyer 					return error;
87125b7033bSConrad Meyer 				}
872f6c4bc3bSPawel Jakub Dawidek 			}
873091d81d1SSam Leffler 
874f6c4bc3bSPawel Jakub Dawidek 			(*swd)->sw_mlen = cri->cri_mlen;
875091d81d1SSam Leffler 			(*swd)->sw_axf = axf;
876091d81d1SSam Leffler 			break;
877091d81d1SSam Leffler 
878091d81d1SSam Leffler 		case CRYPTO_MD5_KPDK:
879091d81d1SSam Leffler 			axf = &auth_hash_key_md5;
880091d81d1SSam Leffler 			goto auth2common;
881091d81d1SSam Leffler 
882091d81d1SSam Leffler 		case CRYPTO_SHA1_KPDK:
883091d81d1SSam Leffler 			axf = &auth_hash_key_sha1;
884091d81d1SSam Leffler 		auth2common:
885091d81d1SSam Leffler 			(*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
886091d81d1SSam Leffler 			    M_NOWAIT);
887091d81d1SSam Leffler 			if ((*swd)->sw_ictx == NULL) {
8881b0909d5SConrad Meyer 				swcr_freesession(dev, cses);
889091d81d1SSam Leffler 				return ENOBUFS;
890091d81d1SSam Leffler 			}
891091d81d1SSam Leffler 
892f6c4bc3bSPawel Jakub Dawidek 			(*swd)->sw_octx = malloc(cri->cri_klen / 8,
893f6c4bc3bSPawel Jakub Dawidek 			    M_CRYPTO_DATA, M_NOWAIT);
894091d81d1SSam Leffler 			if ((*swd)->sw_octx == NULL) {
8951b0909d5SConrad Meyer 				swcr_freesession(dev, cses);
896091d81d1SSam Leffler 				return ENOBUFS;
897091d81d1SSam Leffler 			}
898091d81d1SSam Leffler 
899f6c4bc3bSPawel Jakub Dawidek 			/* Store the key so we can "append" it to the payload */
900f6c4bc3bSPawel Jakub Dawidek 			if (cri->cri_key != NULL) {
90125b7033bSConrad Meyer 				error = swcr_authprepare(axf, *swd,
90225b7033bSConrad Meyer 				    cri->cri_key, cri->cri_klen);
90325b7033bSConrad Meyer 				if (error != 0) {
90425b7033bSConrad Meyer 					swcr_freesession(dev, cses);
90525b7033bSConrad Meyer 					return error;
90625b7033bSConrad Meyer 				}
907f6c4bc3bSPawel Jakub Dawidek 			}
908f6c4bc3bSPawel Jakub Dawidek 
909f6c4bc3bSPawel Jakub Dawidek 			(*swd)->sw_mlen = cri->cri_mlen;
910091d81d1SSam Leffler 			(*swd)->sw_axf = axf;
911091d81d1SSam Leffler 			break;
912091d81d1SSam Leffler #ifdef notdef
913091d81d1SSam Leffler 		case CRYPTO_MD5:
914091d81d1SSam Leffler 			axf = &auth_hash_md5;
915091d81d1SSam Leffler 			goto auth3common;
916c4729f6eSConrad Meyer #endif
917091d81d1SSam Leffler 
918091d81d1SSam Leffler 		case CRYPTO_SHA1:
919091d81d1SSam Leffler 			axf = &auth_hash_sha1;
920c4729f6eSConrad Meyer 			goto auth3common;
921c4729f6eSConrad Meyer 		case CRYPTO_SHA2_224:
922c4729f6eSConrad Meyer 			axf = &auth_hash_sha2_224;
923c4729f6eSConrad Meyer 			goto auth3common;
924c4729f6eSConrad Meyer 		case CRYPTO_SHA2_256:
925c4729f6eSConrad Meyer 			axf = &auth_hash_sha2_256;
926c4729f6eSConrad Meyer 			goto auth3common;
927c4729f6eSConrad Meyer 		case CRYPTO_SHA2_384:
928c4729f6eSConrad Meyer 			axf = &auth_hash_sha2_384;
929c4729f6eSConrad Meyer 			goto auth3common;
930c4729f6eSConrad Meyer 		case CRYPTO_SHA2_512:
931c4729f6eSConrad Meyer 			axf = &auth_hash_sha2_512;
932c4729f6eSConrad Meyer 
933091d81d1SSam Leffler 		auth3common:
934091d81d1SSam Leffler 			(*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
935091d81d1SSam Leffler 			    M_NOWAIT);
936091d81d1SSam Leffler 			if ((*swd)->sw_ictx == NULL) {
9371b0909d5SConrad Meyer 				swcr_freesession(dev, cses);
938091d81d1SSam Leffler 				return ENOBUFS;
939091d81d1SSam Leffler 			}
940091d81d1SSam Leffler 
941091d81d1SSam Leffler 			axf->Init((*swd)->sw_ictx);
942f6c4bc3bSPawel Jakub Dawidek 			(*swd)->sw_mlen = cri->cri_mlen;
943091d81d1SSam Leffler 			(*swd)->sw_axf = axf;
944091d81d1SSam Leffler 			break;
94508fca7a5SJohn-Mark Gurney 
94608fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_128_NIST_GMAC:
94708fca7a5SJohn-Mark Gurney 			axf = &auth_hash_nist_gmac_aes_128;
94808fca7a5SJohn-Mark Gurney 			goto auth4common;
94908fca7a5SJohn-Mark Gurney 
95008fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_192_NIST_GMAC:
95108fca7a5SJohn-Mark Gurney 			axf = &auth_hash_nist_gmac_aes_192;
95208fca7a5SJohn-Mark Gurney 			goto auth4common;
95308fca7a5SJohn-Mark Gurney 
95408fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_256_NIST_GMAC:
95508fca7a5SJohn-Mark Gurney 			axf = &auth_hash_nist_gmac_aes_256;
95608fca7a5SJohn-Mark Gurney 		auth4common:
957a2bc81bfSJohn-Mark Gurney 			len = cri->cri_klen / 8;
9582e2e26d1SJohn Baldwin 			if (len != 16 && len != 24 && len != 32) {
9591b0909d5SConrad Meyer 				swcr_freesession(dev, cses);
960a2bc81bfSJohn-Mark Gurney 				return EINVAL;
9612e2e26d1SJohn Baldwin 			}
962a2bc81bfSJohn-Mark Gurney 
96308fca7a5SJohn-Mark Gurney 			(*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
96408fca7a5SJohn-Mark Gurney 			    M_NOWAIT);
96508fca7a5SJohn-Mark Gurney 			if ((*swd)->sw_ictx == NULL) {
9661b0909d5SConrad Meyer 				swcr_freesession(dev, cses);
96708fca7a5SJohn-Mark Gurney 				return ENOBUFS;
96808fca7a5SJohn-Mark Gurney 			}
96908fca7a5SJohn-Mark Gurney 			axf->Init((*swd)->sw_ictx);
970a2bc81bfSJohn-Mark Gurney 			axf->Setkey((*swd)->sw_ictx, cri->cri_key, len);
97108fca7a5SJohn-Mark Gurney 			(*swd)->sw_axf = axf;
97208fca7a5SJohn-Mark Gurney 			break;
97308fca7a5SJohn-Mark Gurney 
9740e33efe4SConrad Meyer 		case CRYPTO_BLAKE2B:
9750e33efe4SConrad Meyer 			axf = &auth_hash_blake2b;
9760e33efe4SConrad Meyer 			goto auth5common;
9770e33efe4SConrad Meyer 		case CRYPTO_BLAKE2S:
9780e33efe4SConrad Meyer 			axf = &auth_hash_blake2s;
97925b7033bSConrad Meyer 			goto auth5common;
98025b7033bSConrad Meyer 		case CRYPTO_POLY1305:
98125b7033bSConrad Meyer 			axf = &auth_hash_poly1305;
9820e33efe4SConrad Meyer 		auth5common:
9830e33efe4SConrad Meyer 			(*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
9840e33efe4SConrad Meyer 			    M_NOWAIT);
9850e33efe4SConrad Meyer 			if ((*swd)->sw_ictx == NULL) {
9861b0909d5SConrad Meyer 				swcr_freesession(dev, cses);
9870e33efe4SConrad Meyer 				return ENOBUFS;
9880e33efe4SConrad Meyer 			}
9890e33efe4SConrad Meyer 			axf->Setkey((*swd)->sw_ictx, cri->cri_key,
9900e33efe4SConrad Meyer 			    cri->cri_klen / 8);
9910e33efe4SConrad Meyer 			axf->Init((*swd)->sw_ictx);
9920e33efe4SConrad Meyer 			(*swd)->sw_axf = axf;
9930e33efe4SConrad Meyer 			break;
9940e33efe4SConrad Meyer 
995091d81d1SSam Leffler 		case CRYPTO_DEFLATE_COMP:
996091d81d1SSam Leffler 			cxf = &comp_algo_deflate;
997091d81d1SSam Leffler 			(*swd)->sw_cxf = cxf;
998091d81d1SSam Leffler 			break;
999091d81d1SSam Leffler 		default:
10001b0909d5SConrad Meyer 			swcr_freesession(dev, cses);
1001091d81d1SSam Leffler 			return EINVAL;
1002091d81d1SSam Leffler 		}
1003091d81d1SSam Leffler 
1004091d81d1SSam Leffler 		(*swd)->sw_alg = cri->cri_alg;
1005091d81d1SSam Leffler 		cri = cri->cri_next;
1006091d81d1SSam Leffler 		swd = &((*swd)->sw_next);
1007091d81d1SSam Leffler 	}
1008091d81d1SSam Leffler 	return 0;
1009091d81d1SSam Leffler }
1010091d81d1SSam Leffler 
10111b0909d5SConrad Meyer static void
10121b0909d5SConrad Meyer swcr_freesession(device_t dev, crypto_session_t cses)
1013109919c6SBenno Rice {
10141b0909d5SConrad Meyer 	struct swcr_data *ses, *swd, *next;
1015091d81d1SSam Leffler 	struct enc_xform *txf;
1016091d81d1SSam Leffler 	struct auth_hash *axf;
1017091d81d1SSam Leffler 
10181b0909d5SConrad Meyer 	ses = crypto_get_driver_session(cses);
1019091d81d1SSam Leffler 
10201b0909d5SConrad Meyer 	for (swd = ses; swd != NULL; swd = next) {
10211b0909d5SConrad Meyer 		next = swd->sw_next;
1022091d81d1SSam Leffler 
1023091d81d1SSam Leffler 		switch (swd->sw_alg) {
1024091d81d1SSam Leffler 		case CRYPTO_DES_CBC:
1025091d81d1SSam Leffler 		case CRYPTO_3DES_CBC:
1026091d81d1SSam Leffler 		case CRYPTO_BLF_CBC:
1027091d81d1SSam Leffler 		case CRYPTO_CAST_CBC:
1028091d81d1SSam Leffler 		case CRYPTO_SKIPJACK_CBC:
1029091d81d1SSam Leffler 		case CRYPTO_RIJNDAEL128_CBC:
1030d295bdeeSPawel Jakub Dawidek 		case CRYPTO_AES_XTS:
103108fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_ICM:
103208fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_NIST_GCM_16:
103308fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_NIST_GMAC:
1034559d3390SGeorge V. Neville-Neil 		case CRYPTO_CAMELLIA_CBC:
1035091d81d1SSam Leffler 		case CRYPTO_NULL_CBC:
103661590291SConrad Meyer 		case CRYPTO_CHACHA20:
1037091d81d1SSam Leffler 			txf = swd->sw_exf;
1038091d81d1SSam Leffler 
1039091d81d1SSam Leffler 			if (swd->sw_kschedule)
1040091d81d1SSam Leffler 				txf->zerokey(&(swd->sw_kschedule));
1041091d81d1SSam Leffler 			break;
1042091d81d1SSam Leffler 
1043091d81d1SSam Leffler 		case CRYPTO_MD5_HMAC:
1044091d81d1SSam Leffler 		case CRYPTO_SHA1_HMAC:
1045c97f39ceSConrad Meyer 		case CRYPTO_SHA2_224_HMAC:
1046f6c4bc3bSPawel Jakub Dawidek 		case CRYPTO_SHA2_256_HMAC:
1047f6c4bc3bSPawel Jakub Dawidek 		case CRYPTO_SHA2_384_HMAC:
1048f6c4bc3bSPawel Jakub Dawidek 		case CRYPTO_SHA2_512_HMAC:
1049091d81d1SSam Leffler 		case CRYPTO_RIPEMD160_HMAC:
1050091d81d1SSam Leffler 		case CRYPTO_NULL_HMAC:
1051091d81d1SSam Leffler 			axf = swd->sw_axf;
1052091d81d1SSam Leffler 
1053091d81d1SSam Leffler 			if (swd->sw_ictx) {
1054091d81d1SSam Leffler 				bzero(swd->sw_ictx, axf->ctxsize);
1055091d81d1SSam Leffler 				free(swd->sw_ictx, M_CRYPTO_DATA);
1056091d81d1SSam Leffler 			}
1057091d81d1SSam Leffler 			if (swd->sw_octx) {
1058091d81d1SSam Leffler 				bzero(swd->sw_octx, axf->ctxsize);
1059091d81d1SSam Leffler 				free(swd->sw_octx, M_CRYPTO_DATA);
1060091d81d1SSam Leffler 			}
1061091d81d1SSam Leffler 			break;
1062091d81d1SSam Leffler 
1063091d81d1SSam Leffler 		case CRYPTO_MD5_KPDK:
1064091d81d1SSam Leffler 		case CRYPTO_SHA1_KPDK:
1065091d81d1SSam Leffler 			axf = swd->sw_axf;
1066091d81d1SSam Leffler 
1067091d81d1SSam Leffler 			if (swd->sw_ictx) {
1068091d81d1SSam Leffler 				bzero(swd->sw_ictx, axf->ctxsize);
1069091d81d1SSam Leffler 				free(swd->sw_ictx, M_CRYPTO_DATA);
1070091d81d1SSam Leffler 			}
1071091d81d1SSam Leffler 			if (swd->sw_octx) {
1072091d81d1SSam Leffler 				bzero(swd->sw_octx, swd->sw_klen);
1073091d81d1SSam Leffler 				free(swd->sw_octx, M_CRYPTO_DATA);
1074091d81d1SSam Leffler 			}
1075091d81d1SSam Leffler 			break;
1076091d81d1SSam Leffler 
10770e33efe4SConrad Meyer 		case CRYPTO_BLAKE2B:
10780e33efe4SConrad Meyer 		case CRYPTO_BLAKE2S:
1079091d81d1SSam Leffler 		case CRYPTO_MD5:
108025b7033bSConrad Meyer 		case CRYPTO_POLY1305:
1081091d81d1SSam Leffler 		case CRYPTO_SHA1:
1082c4729f6eSConrad Meyer 		case CRYPTO_SHA2_224:
1083c4729f6eSConrad Meyer 		case CRYPTO_SHA2_256:
1084c4729f6eSConrad Meyer 		case CRYPTO_SHA2_384:
1085c4729f6eSConrad Meyer 		case CRYPTO_SHA2_512:
1086091d81d1SSam Leffler 			axf = swd->sw_axf;
1087091d81d1SSam Leffler 
10885fbc5b5aSConrad Meyer 			if (swd->sw_ictx) {
10895fbc5b5aSConrad Meyer 				explicit_bzero(swd->sw_ictx, axf->ctxsize);
1090091d81d1SSam Leffler 				free(swd->sw_ictx, M_CRYPTO_DATA);
10915fbc5b5aSConrad Meyer 			}
1092091d81d1SSam Leffler 			break;
1093091d81d1SSam Leffler 
1094091d81d1SSam Leffler 		case CRYPTO_DEFLATE_COMP:
1095151ba793SAlexander Kabaev 			/* Nothing to do */
1096091d81d1SSam Leffler 			break;
1097091d81d1SSam Leffler 		}
1098091d81d1SSam Leffler 
10991b0909d5SConrad Meyer 		/* OCF owns and frees the primary session object */
11001b0909d5SConrad Meyer 		if (swd != ses)
11011ede983cSDag-Erling Smørgrav 			free(swd, M_CRYPTO_DATA);
1102091d81d1SSam Leffler 	}
1103091d81d1SSam Leffler }
1104091d81d1SSam Leffler 
1105091d81d1SSam Leffler /*
1106091d81d1SSam Leffler  * Process a software request.
1107091d81d1SSam Leffler  */
1108091d81d1SSam Leffler static int
11096810ad6fSSam Leffler swcr_process(device_t dev, struct cryptop *crp, int hint)
1110091d81d1SSam Leffler {
1111091d81d1SSam Leffler 	struct cryptodesc *crd;
11121b0909d5SConrad Meyer 	struct swcr_data *sw, *ses;
1113091d81d1SSam Leffler 
1114091d81d1SSam Leffler 	/* Sanity check */
1115091d81d1SSam Leffler 	if (crp == NULL)
1116091d81d1SSam Leffler 		return EINVAL;
1117091d81d1SSam Leffler 
1118091d81d1SSam Leffler 	if (crp->crp_desc == NULL || crp->crp_buf == NULL) {
1119091d81d1SSam Leffler 		crp->crp_etype = EINVAL;
1120091d81d1SSam Leffler 		goto done;
1121091d81d1SSam Leffler 	}
1122091d81d1SSam Leffler 
11231b0909d5SConrad Meyer 	ses = crypto_get_driver_session(crp->crp_session);
1124091d81d1SSam Leffler 
1125091d81d1SSam Leffler 	/* Go through crypto descriptors, processing as we go */
1126091d81d1SSam Leffler 	for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
1127091d81d1SSam Leffler 		/*
1128091d81d1SSam Leffler 		 * Find the crypto context.
1129091d81d1SSam Leffler 		 *
1130091d81d1SSam Leffler 		 * XXX Note that the logic here prevents us from having
1131091d81d1SSam Leffler 		 * XXX the same algorithm multiple times in a session
1132091d81d1SSam Leffler 		 * XXX (or rather, we can but it won't give us the right
1133091d81d1SSam Leffler 		 * XXX results). To do that, we'd need some way of differentiating
1134091d81d1SSam Leffler 		 * XXX between the various instances of an algorithm (so we can
1135091d81d1SSam Leffler 		 * XXX locate the correct crypto context).
1136091d81d1SSam Leffler 		 */
11371b0909d5SConrad Meyer 		for (sw = ses; sw && sw->sw_alg != crd->crd_alg;
1138091d81d1SSam Leffler 		    sw = sw->sw_next)
1139091d81d1SSam Leffler 			;
1140091d81d1SSam Leffler 
1141091d81d1SSam Leffler 		/* No such context ? */
1142091d81d1SSam Leffler 		if (sw == NULL) {
1143091d81d1SSam Leffler 			crp->crp_etype = EINVAL;
1144091d81d1SSam Leffler 			goto done;
1145091d81d1SSam Leffler 		}
1146091d81d1SSam Leffler 		switch (sw->sw_alg) {
1147091d81d1SSam Leffler 		case CRYPTO_DES_CBC:
1148091d81d1SSam Leffler 		case CRYPTO_3DES_CBC:
1149091d81d1SSam Leffler 		case CRYPTO_BLF_CBC:
1150091d81d1SSam Leffler 		case CRYPTO_CAST_CBC:
1151091d81d1SSam Leffler 		case CRYPTO_SKIPJACK_CBC:
1152091d81d1SSam Leffler 		case CRYPTO_RIJNDAEL128_CBC:
1153d295bdeeSPawel Jakub Dawidek 		case CRYPTO_AES_XTS:
115408fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_ICM:
1155559d3390SGeorge V. Neville-Neil 		case CRYPTO_CAMELLIA_CBC:
115661590291SConrad Meyer 		case CRYPTO_CHACHA20:
1157091d81d1SSam Leffler 			if ((crp->crp_etype = swcr_encdec(crd, sw,
1158f34a967bSPawel Jakub Dawidek 			    crp->crp_buf, crp->crp_flags)) != 0)
1159091d81d1SSam Leffler 				goto done;
1160091d81d1SSam Leffler 			break;
1161091d81d1SSam Leffler 		case CRYPTO_NULL_CBC:
1162091d81d1SSam Leffler 			crp->crp_etype = 0;
1163091d81d1SSam Leffler 			break;
1164091d81d1SSam Leffler 		case CRYPTO_MD5_HMAC:
1165091d81d1SSam Leffler 		case CRYPTO_SHA1_HMAC:
1166c97f39ceSConrad Meyer 		case CRYPTO_SHA2_224_HMAC:
1167f6c4bc3bSPawel Jakub Dawidek 		case CRYPTO_SHA2_256_HMAC:
1168f6c4bc3bSPawel Jakub Dawidek 		case CRYPTO_SHA2_384_HMAC:
1169f6c4bc3bSPawel Jakub Dawidek 		case CRYPTO_SHA2_512_HMAC:
1170091d81d1SSam Leffler 		case CRYPTO_RIPEMD160_HMAC:
1171091d81d1SSam Leffler 		case CRYPTO_NULL_HMAC:
1172091d81d1SSam Leffler 		case CRYPTO_MD5_KPDK:
1173091d81d1SSam Leffler 		case CRYPTO_SHA1_KPDK:
1174091d81d1SSam Leffler 		case CRYPTO_MD5:
1175091d81d1SSam Leffler 		case CRYPTO_SHA1:
1176c4729f6eSConrad Meyer 		case CRYPTO_SHA2_224:
1177c4729f6eSConrad Meyer 		case CRYPTO_SHA2_256:
1178c4729f6eSConrad Meyer 		case CRYPTO_SHA2_384:
1179c4729f6eSConrad Meyer 		case CRYPTO_SHA2_512:
11800e33efe4SConrad Meyer 		case CRYPTO_BLAKE2B:
11810e33efe4SConrad Meyer 		case CRYPTO_BLAKE2S:
118225b7033bSConrad Meyer 		case CRYPTO_POLY1305:
118338d2f8d6SPawel Jakub Dawidek 			if ((crp->crp_etype = swcr_authcompute(crd, sw,
1184f34a967bSPawel Jakub Dawidek 			    crp->crp_buf, crp->crp_flags)) != 0)
1185091d81d1SSam Leffler 				goto done;
1186091d81d1SSam Leffler 			break;
1187091d81d1SSam Leffler 
118808fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_NIST_GCM_16:
118908fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_NIST_GMAC:
119008fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_128_NIST_GMAC:
119108fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_192_NIST_GMAC:
119208fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_256_NIST_GMAC:
119308fca7a5SJohn-Mark Gurney 			crp->crp_etype = swcr_authenc(crp);
119408fca7a5SJohn-Mark Gurney 			goto done;
119508fca7a5SJohn-Mark Gurney 
1196091d81d1SSam Leffler 		case CRYPTO_DEFLATE_COMP:
1197091d81d1SSam Leffler 			if ((crp->crp_etype = swcr_compdec(crd, sw,
1198f34a967bSPawel Jakub Dawidek 			    crp->crp_buf, crp->crp_flags)) != 0)
1199091d81d1SSam Leffler 				goto done;
1200091d81d1SSam Leffler 			else
1201091d81d1SSam Leffler 				crp->crp_olen = (int)sw->sw_size;
1202091d81d1SSam Leffler 			break;
1203091d81d1SSam Leffler 
1204091d81d1SSam Leffler 		default:
1205091d81d1SSam Leffler 			/* Unknown/unsupported algorithm */
1206091d81d1SSam Leffler 			crp->crp_etype = EINVAL;
1207091d81d1SSam Leffler 			goto done;
1208091d81d1SSam Leffler 		}
1209091d81d1SSam Leffler 	}
1210091d81d1SSam Leffler 
1211091d81d1SSam Leffler done:
1212091d81d1SSam Leffler 	crypto_done(crp);
1213091d81d1SSam Leffler 	return 0;
1214091d81d1SSam Leffler }
1215091d81d1SSam Leffler 
1216091d81d1SSam Leffler static void
12173f147ab2SWarner Losh swcr_identify(driver_t *drv, device_t parent)
1218091d81d1SSam Leffler {
12196810ad6fSSam Leffler 	/* NB: order 10 is so we get attached after h/w devices */
12206810ad6fSSam Leffler 	if (device_find_child(parent, "cryptosoft", -1) == NULL &&
122186c585d9SMarius Strobl 	    BUS_ADD_CHILD(parent, 10, "cryptosoft", 0) == 0)
12226810ad6fSSam Leffler 		panic("cryptosoft: could not attach");
12236810ad6fSSam Leffler }
1224f6c4bc3bSPawel Jakub Dawidek 
12256810ad6fSSam Leffler static int
12266810ad6fSSam Leffler swcr_probe(device_t dev)
12276810ad6fSSam Leffler {
12286810ad6fSSam Leffler 	device_set_desc(dev, "software crypto");
122986c585d9SMarius Strobl 	return (BUS_PROBE_NOWILDCARD);
12306810ad6fSSam Leffler }
1231f6c4bc3bSPawel Jakub Dawidek 
12326810ad6fSSam Leffler static int
12336810ad6fSSam Leffler swcr_attach(device_t dev)
12346810ad6fSSam Leffler {
12356810ad6fSSam Leffler 	memset(hmac_ipad_buffer, HMAC_IPAD_VAL, HMAC_MAX_BLOCK_LEN);
12366810ad6fSSam Leffler 	memset(hmac_opad_buffer, HMAC_OPAD_VAL, HMAC_MAX_BLOCK_LEN);
12376810ad6fSSam Leffler 
12381b0909d5SConrad Meyer 	swcr_id = crypto_get_driverid(dev, sizeof(struct swcr_data),
12396810ad6fSSam Leffler 			CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC);
12406810ad6fSSam Leffler 	if (swcr_id < 0) {
12416810ad6fSSam Leffler 		device_printf(dev, "cannot initialize!");
12426810ad6fSSam Leffler 		return ENOMEM;
12436810ad6fSSam Leffler 	}
1244091d81d1SSam Leffler #define	REGISTER(alg) \
12456810ad6fSSam Leffler 	crypto_register(swcr_id, alg, 0,0)
12466810ad6fSSam Leffler 	REGISTER(CRYPTO_DES_CBC);
1247091d81d1SSam Leffler 	REGISTER(CRYPTO_3DES_CBC);
1248091d81d1SSam Leffler 	REGISTER(CRYPTO_BLF_CBC);
1249091d81d1SSam Leffler 	REGISTER(CRYPTO_CAST_CBC);
1250091d81d1SSam Leffler 	REGISTER(CRYPTO_SKIPJACK_CBC);
1251091d81d1SSam Leffler 	REGISTER(CRYPTO_NULL_CBC);
1252091d81d1SSam Leffler 	REGISTER(CRYPTO_MD5_HMAC);
1253091d81d1SSam Leffler 	REGISTER(CRYPTO_SHA1_HMAC);
1254c97f39ceSConrad Meyer 	REGISTER(CRYPTO_SHA2_224_HMAC);
1255f6c4bc3bSPawel Jakub Dawidek 	REGISTER(CRYPTO_SHA2_256_HMAC);
1256f6c4bc3bSPawel Jakub Dawidek 	REGISTER(CRYPTO_SHA2_384_HMAC);
1257f6c4bc3bSPawel Jakub Dawidek 	REGISTER(CRYPTO_SHA2_512_HMAC);
1258091d81d1SSam Leffler 	REGISTER(CRYPTO_RIPEMD160_HMAC);
1259091d81d1SSam Leffler 	REGISTER(CRYPTO_NULL_HMAC);
1260091d81d1SSam Leffler 	REGISTER(CRYPTO_MD5_KPDK);
1261091d81d1SSam Leffler 	REGISTER(CRYPTO_SHA1_KPDK);
1262091d81d1SSam Leffler 	REGISTER(CRYPTO_MD5);
1263091d81d1SSam Leffler 	REGISTER(CRYPTO_SHA1);
1264c4729f6eSConrad Meyer 	REGISTER(CRYPTO_SHA2_224);
1265c4729f6eSConrad Meyer 	REGISTER(CRYPTO_SHA2_256);
1266c4729f6eSConrad Meyer 	REGISTER(CRYPTO_SHA2_384);
1267c4729f6eSConrad Meyer 	REGISTER(CRYPTO_SHA2_512);
1268091d81d1SSam Leffler 	REGISTER(CRYPTO_RIJNDAEL128_CBC);
1269d295bdeeSPawel Jakub Dawidek 	REGISTER(CRYPTO_AES_XTS);
127008fca7a5SJohn-Mark Gurney 	REGISTER(CRYPTO_AES_ICM);
127108fca7a5SJohn-Mark Gurney 	REGISTER(CRYPTO_AES_NIST_GCM_16);
127208fca7a5SJohn-Mark Gurney 	REGISTER(CRYPTO_AES_NIST_GMAC);
127308fca7a5SJohn-Mark Gurney 	REGISTER(CRYPTO_AES_128_NIST_GMAC);
127408fca7a5SJohn-Mark Gurney 	REGISTER(CRYPTO_AES_192_NIST_GMAC);
127508fca7a5SJohn-Mark Gurney 	REGISTER(CRYPTO_AES_256_NIST_GMAC);
1276559d3390SGeorge V. Neville-Neil  	REGISTER(CRYPTO_CAMELLIA_CBC);
1277091d81d1SSam Leffler 	REGISTER(CRYPTO_DEFLATE_COMP);
12780e33efe4SConrad Meyer 	REGISTER(CRYPTO_BLAKE2B);
12790e33efe4SConrad Meyer 	REGISTER(CRYPTO_BLAKE2S);
128061590291SConrad Meyer 	REGISTER(CRYPTO_CHACHA20);
128125b7033bSConrad Meyer 	REGISTER(CRYPTO_POLY1305);
1282091d81d1SSam Leffler #undef REGISTER
12836810ad6fSSam Leffler 
12846810ad6fSSam Leffler 	return 0;
1285091d81d1SSam Leffler }
12864b465da2SPawel Jakub Dawidek 
12873f147ab2SWarner Losh static int
12886810ad6fSSam Leffler swcr_detach(device_t dev)
12894b465da2SPawel Jakub Dawidek {
12906810ad6fSSam Leffler 	crypto_unregister_all(swcr_id);
12913f147ab2SWarner Losh 	return 0;
12924b465da2SPawel Jakub Dawidek }
12936810ad6fSSam Leffler 
12946810ad6fSSam Leffler static device_method_t swcr_methods[] = {
12956810ad6fSSam Leffler 	DEVMETHOD(device_identify,	swcr_identify),
12966810ad6fSSam Leffler 	DEVMETHOD(device_probe,		swcr_probe),
12976810ad6fSSam Leffler 	DEVMETHOD(device_attach,	swcr_attach),
12986810ad6fSSam Leffler 	DEVMETHOD(device_detach,	swcr_detach),
12996810ad6fSSam Leffler 
13006810ad6fSSam Leffler 	DEVMETHOD(cryptodev_newsession,	swcr_newsession),
13016810ad6fSSam Leffler 	DEVMETHOD(cryptodev_freesession,swcr_freesession),
13026810ad6fSSam Leffler 	DEVMETHOD(cryptodev_process,	swcr_process),
13036810ad6fSSam Leffler 
13046810ad6fSSam Leffler 	{0, 0},
13056810ad6fSSam Leffler };
13066810ad6fSSam Leffler 
13076810ad6fSSam Leffler static driver_t swcr_driver = {
13086810ad6fSSam Leffler 	"cryptosoft",
13096810ad6fSSam Leffler 	swcr_methods,
13106810ad6fSSam Leffler 	0,		/* NB: no softc */
13116810ad6fSSam Leffler };
13126810ad6fSSam Leffler static devclass_t swcr_devclass;
13136810ad6fSSam Leffler 
13146810ad6fSSam Leffler /*
13156810ad6fSSam Leffler  * NB: We explicitly reference the crypto module so we
13166810ad6fSSam Leffler  * get the necessary ordering when built as a loadable
13176810ad6fSSam Leffler  * module.  This is required because we bundle the crypto
13186810ad6fSSam Leffler  * module code together with the cryptosoft driver (otherwise
13196810ad6fSSam Leffler  * normal module dependencies would handle things).
13206810ad6fSSam Leffler  */
13216810ad6fSSam Leffler extern int crypto_modevent(struct module *, int, void *);
13226810ad6fSSam Leffler /* XXX where to attach */
13236810ad6fSSam Leffler DRIVER_MODULE(cryptosoft, nexus, swcr_driver, swcr_devclass, crypto_modevent,0);
13246810ad6fSSam Leffler MODULE_VERSION(cryptosoft, 1);
13256810ad6fSSam Leffler MODULE_DEPEND(cryptosoft, crypto, 1, 1, 1);
1326