xref: /freebsd/sys/opencrypto/cryptosoft.c (revision 507281e55e3903e8ea1007ddf201f6703860189d)
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>
48a7fcb1afSSean Eric Fagan #include <sys/mutex.h>
49091d81d1SSam Leffler 
50091d81d1SSam Leffler #include <crypto/blowfish/blowfish.h>
51091d81d1SSam Leffler #include <crypto/sha1.h>
52091d81d1SSam Leffler #include <opencrypto/rmd160.h>
539f65b10bSHajimu UMEMOTO #include <opencrypto/cast.h>
54091d81d1SSam Leffler #include <opencrypto/skipjack.h>
55091d81d1SSam Leffler #include <sys/md5.h>
56091d81d1SSam Leffler 
57091d81d1SSam Leffler #include <opencrypto/cryptodev.h>
58091d81d1SSam Leffler #include <opencrypto/cryptosoft.h>
59091d81d1SSam Leffler #include <opencrypto/xform.h>
60091d81d1SSam Leffler 
616810ad6fSSam Leffler #include <sys/kobj.h>
626810ad6fSSam Leffler #include <sys/bus.h>
636810ad6fSSam Leffler #include "cryptodev_if.h"
64091d81d1SSam Leffler 
65*507281e5SSean Eric Fagan _Static_assert(AES_CCM_IV_LEN == AES_GCM_IV_LEN,
66*507281e5SSean Eric Fagan     "AES_GCM_IV_LEN must currently be the same as AES_CCM_IV_LEN");
67*507281e5SSean Eric Fagan 
686810ad6fSSam Leffler static	int32_t swcr_id;
696810ad6fSSam Leffler 
706810ad6fSSam Leffler u_int8_t hmac_ipad_buffer[HMAC_MAX_BLOCK_LEN];
716810ad6fSSam Leffler u_int8_t hmac_opad_buffer[HMAC_MAX_BLOCK_LEN];
72091d81d1SSam Leffler 
73091d81d1SSam Leffler static	int swcr_encdec(struct cryptodesc *, struct swcr_data *, caddr_t, int);
74f34a967bSPawel Jakub Dawidek static	int swcr_authcompute(struct cryptodesc *, struct swcr_data *, caddr_t, int);
7508fca7a5SJohn-Mark Gurney static	int swcr_authenc(struct cryptop *crp);
76091d81d1SSam Leffler static	int swcr_compdec(struct cryptodesc *, struct swcr_data *, caddr_t, int);
771b0909d5SConrad Meyer static	void swcr_freesession(device_t dev, crypto_session_t cses);
78091d81d1SSam Leffler 
79091d81d1SSam Leffler /*
80091d81d1SSam Leffler  * Apply a symmetric encryption/decryption algorithm.
81091d81d1SSam Leffler  */
82091d81d1SSam Leffler static int
83091d81d1SSam Leffler swcr_encdec(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf,
84f34a967bSPawel Jakub Dawidek     int flags)
85091d81d1SSam Leffler {
865d7ae54aSConrad Meyer 	unsigned char iv[EALG_MAX_BLOCK_LEN], blk[EALG_MAX_BLOCK_LEN];
8708fca7a5SJohn-Mark Gurney 	unsigned char *ivp, *nivp, iv2[EALG_MAX_BLOCK_LEN];
88091d81d1SSam Leffler 	struct enc_xform *exf;
8908fca7a5SJohn-Mark Gurney 	int i, j, k, blks, ind, count, ivlen;
9008fca7a5SJohn-Mark Gurney 	struct uio *uio, uiolcl;
9108fca7a5SJohn-Mark Gurney 	struct iovec iovlcl[4];
9208fca7a5SJohn-Mark Gurney 	struct iovec *iov;
9308fca7a5SJohn-Mark Gurney 	int iovcnt, iovalloc;
9408fca7a5SJohn-Mark Gurney 	int error;
9508fca7a5SJohn-Mark Gurney 
9608fca7a5SJohn-Mark Gurney 	error = 0;
97091d81d1SSam Leffler 
98091d81d1SSam Leffler 	exf = sw->sw_exf;
99091d81d1SSam Leffler 	blks = exf->blocksize;
10008fca7a5SJohn-Mark Gurney 	ivlen = exf->ivsize;
101091d81d1SSam Leffler 
102091d81d1SSam Leffler 	/* Check for non-padded data */
103091d81d1SSam Leffler 	if (crd->crd_len % blks)
104091d81d1SSam Leffler 		return EINVAL;
105091d81d1SSam Leffler 
10608fca7a5SJohn-Mark Gurney 	if (crd->crd_alg == CRYPTO_AES_ICM &&
10708fca7a5SJohn-Mark Gurney 	    (crd->crd_flags & CRD_F_IV_EXPLICIT) == 0)
10808fca7a5SJohn-Mark Gurney 		return (EINVAL);
10908fca7a5SJohn-Mark Gurney 
110091d81d1SSam Leffler 	/* Initialize the IV */
111091d81d1SSam Leffler 	if (crd->crd_flags & CRD_F_ENCRYPT) {
112091d81d1SSam Leffler 		/* IV explicitly provided ? */
113091d81d1SSam Leffler 		if (crd->crd_flags & CRD_F_IV_EXPLICIT)
11408fca7a5SJohn-Mark Gurney 			bcopy(crd->crd_iv, iv, ivlen);
11548b0f2e1SPawel Jakub Dawidek 		else
11608fca7a5SJohn-Mark Gurney 			arc4rand(iv, ivlen, 0);
117091d81d1SSam Leffler 
118091d81d1SSam Leffler 		/* Do we need to write the IV */
119f34a967bSPawel Jakub Dawidek 		if (!(crd->crd_flags & CRD_F_IV_PRESENT))
12008fca7a5SJohn-Mark Gurney 			crypto_copyback(flags, buf, crd->crd_inject, ivlen, iv);
121091d81d1SSam Leffler 
122091d81d1SSam Leffler 	} else {	/* Decryption */
123091d81d1SSam Leffler 		/* IV explicitly provided ? */
124091d81d1SSam Leffler 		if (crd->crd_flags & CRD_F_IV_EXPLICIT)
12508fca7a5SJohn-Mark Gurney 			bcopy(crd->crd_iv, iv, ivlen);
126091d81d1SSam Leffler 		else {
127091d81d1SSam Leffler 			/* Get IV off buf */
12808fca7a5SJohn-Mark Gurney 			crypto_copydata(flags, buf, crd->crd_inject, ivlen, iv);
129091d81d1SSam Leffler 		}
130091d81d1SSam Leffler 	}
131091d81d1SSam Leffler 
132c740ae4bSPoul-Henning Kamp 	if (crd->crd_flags & CRD_F_KEY_EXPLICIT) {
133c740ae4bSPoul-Henning Kamp 		int error;
134c740ae4bSPoul-Henning Kamp 
135c740ae4bSPoul-Henning Kamp 		if (sw->sw_kschedule)
136c740ae4bSPoul-Henning Kamp 			exf->zerokey(&(sw->sw_kschedule));
13708fca7a5SJohn-Mark Gurney 
138c740ae4bSPoul-Henning Kamp 		error = exf->setkey(&sw->sw_kschedule,
139c740ae4bSPoul-Henning Kamp 				crd->crd_key, crd->crd_klen / 8);
140c740ae4bSPoul-Henning Kamp 		if (error)
141c740ae4bSPoul-Henning Kamp 			return (error);
142c740ae4bSPoul-Henning Kamp 	}
143d295bdeeSPawel Jakub Dawidek 
14408fca7a5SJohn-Mark Gurney 	iov = iovlcl;
14508fca7a5SJohn-Mark Gurney 	iovcnt = nitems(iovlcl);
14608fca7a5SJohn-Mark Gurney 	iovalloc = 0;
14708fca7a5SJohn-Mark Gurney 	uio = &uiolcl;
14808fca7a5SJohn-Mark Gurney 	if ((flags & CRYPTO_F_IMBUF) != 0) {
149748a12e2SJohn-Mark Gurney 		error = crypto_mbuftoiov((struct mbuf *)buf, &iov, &iovcnt,
15008fca7a5SJohn-Mark Gurney 		    &iovalloc);
151748a12e2SJohn-Mark Gurney 		if (error)
152748a12e2SJohn-Mark Gurney 			return (error);
15308fca7a5SJohn-Mark Gurney 		uio->uio_iov = iov;
15408fca7a5SJohn-Mark Gurney 		uio->uio_iovcnt = iovcnt;
15508fca7a5SJohn-Mark Gurney 	} else if ((flags & CRYPTO_F_IOV) != 0)
15608fca7a5SJohn-Mark Gurney 		uio = (struct uio *)buf;
15708fca7a5SJohn-Mark Gurney 	else {
15808fca7a5SJohn-Mark Gurney 		iov[0].iov_base = buf;
15908fca7a5SJohn-Mark Gurney 		iov[0].iov_len = crd->crd_skip + crd->crd_len;
16008fca7a5SJohn-Mark Gurney 		uio->uio_iov = iov;
16108fca7a5SJohn-Mark Gurney 		uio->uio_iovcnt = 1;
16208fca7a5SJohn-Mark Gurney 	}
16308fca7a5SJohn-Mark Gurney 
164091d81d1SSam Leffler 	ivp = iv;
165091d81d1SSam Leffler 
16608fca7a5SJohn-Mark Gurney 	if (exf->reinit) {
167d295bdeeSPawel Jakub Dawidek 		/*
168d295bdeeSPawel Jakub Dawidek 		 * xforms that provide a reinit method perform all IV
169d295bdeeSPawel Jakub Dawidek 		 * handling themselves.
170d295bdeeSPawel Jakub Dawidek 		 */
171d295bdeeSPawel Jakub Dawidek 		exf->reinit(sw->sw_kschedule, iv);
172091d81d1SSam Leffler 	}
173091d81d1SSam Leffler 
17408fca7a5SJohn-Mark Gurney 	count = crd->crd_skip;
17508fca7a5SJohn-Mark Gurney 	ind = cuio_getptr(uio, count, &k);
17608fca7a5SJohn-Mark Gurney 	if (ind == -1) {
17708fca7a5SJohn-Mark Gurney 		error = EINVAL;
17808fca7a5SJohn-Mark Gurney 		goto out;
179091d81d1SSam Leffler 	}
180091d81d1SSam Leffler 
181091d81d1SSam Leffler 	i = crd->crd_len;
182091d81d1SSam Leffler 
183091d81d1SSam Leffler 	while (i > 0) {
184091d81d1SSam Leffler 		/*
185091d81d1SSam Leffler 		 * If there's insufficient data at the end of
186091d81d1SSam Leffler 		 * an iovec, we have to do some copying.
187091d81d1SSam Leffler 		 */
18808fca7a5SJohn-Mark Gurney 		if (uio->uio_iov[ind].iov_len < k + blks &&
18908fca7a5SJohn-Mark Gurney 		    uio->uio_iov[ind].iov_len != k) {
19008fca7a5SJohn-Mark Gurney 			cuio_copydata(uio, count, blks, blk);
191091d81d1SSam Leffler 
192091d81d1SSam Leffler 			/* Actual encryption/decryption */
193d295bdeeSPawel Jakub Dawidek 			if (exf->reinit) {
194091d81d1SSam Leffler 				if (crd->crd_flags & CRD_F_ENCRYPT) {
195d295bdeeSPawel Jakub Dawidek 					exf->encrypt(sw->sw_kschedule,
196d295bdeeSPawel Jakub Dawidek 					    blk);
197d295bdeeSPawel Jakub Dawidek 				} else {
198d295bdeeSPawel Jakub Dawidek 					exf->decrypt(sw->sw_kschedule,
199d295bdeeSPawel Jakub Dawidek 					    blk);
200d295bdeeSPawel Jakub Dawidek 				}
201d295bdeeSPawel Jakub Dawidek 			} else if (crd->crd_flags & CRD_F_ENCRYPT) {
202091d81d1SSam Leffler 				/* XOR with previous block */
203091d81d1SSam Leffler 				for (j = 0; j < blks; j++)
204091d81d1SSam Leffler 					blk[j] ^= ivp[j];
205091d81d1SSam Leffler 
206091d81d1SSam Leffler 				exf->encrypt(sw->sw_kschedule, blk);
207091d81d1SSam Leffler 
208091d81d1SSam Leffler 				/*
209091d81d1SSam Leffler 				 * Keep encrypted block for XOR'ing
210091d81d1SSam Leffler 				 * with next block
211091d81d1SSam Leffler 				 */
212091d81d1SSam Leffler 				bcopy(blk, iv, blks);
213091d81d1SSam Leffler 				ivp = iv;
214091d81d1SSam Leffler 			} else {	/* decrypt */
215091d81d1SSam Leffler 				/*
216091d81d1SSam Leffler 				 * Keep encrypted block for XOR'ing
217091d81d1SSam Leffler 				 * with next block
218091d81d1SSam Leffler 				 */
21908fca7a5SJohn-Mark Gurney 				nivp = (ivp == iv) ? iv2 : iv;
22008fca7a5SJohn-Mark Gurney 				bcopy(blk, nivp, blks);
221091d81d1SSam Leffler 
222091d81d1SSam Leffler 				exf->decrypt(sw->sw_kschedule, blk);
223091d81d1SSam Leffler 
224091d81d1SSam Leffler 				/* XOR with previous block */
225091d81d1SSam Leffler 				for (j = 0; j < blks; j++)
226091d81d1SSam Leffler 					blk[j] ^= ivp[j];
227091d81d1SSam Leffler 
22808fca7a5SJohn-Mark Gurney 				ivp = nivp;
229091d81d1SSam Leffler 			}
230091d81d1SSam Leffler 
231091d81d1SSam Leffler 			/* Copy back decrypted block */
23208fca7a5SJohn-Mark Gurney 			cuio_copyback(uio, count, blks, blk);
23308fca7a5SJohn-Mark Gurney 
23408fca7a5SJohn-Mark Gurney 			count += blks;
235091d81d1SSam Leffler 
236091d81d1SSam Leffler 			/* Advance pointer */
23708fca7a5SJohn-Mark Gurney 			ind = cuio_getptr(uio, count, &k);
23808fca7a5SJohn-Mark Gurney 			if (ind == -1) {
23908fca7a5SJohn-Mark Gurney 				error = EINVAL;
24008fca7a5SJohn-Mark Gurney 				goto out;
24108fca7a5SJohn-Mark Gurney 			}
242091d81d1SSam Leffler 
243091d81d1SSam Leffler 			i -= blks;
244091d81d1SSam Leffler 
245091d81d1SSam Leffler 			/* Could be done... */
246091d81d1SSam Leffler 			if (i == 0)
247091d81d1SSam Leffler 				break;
248091d81d1SSam Leffler 		}
249091d81d1SSam Leffler 
2502f1f9cceSConrad Meyer 		while (uio->uio_iov[ind].iov_len >= k + blks && i > 0) {
2515d7ae54aSConrad Meyer 			uint8_t *idat;
2522f1f9cceSConrad Meyer 			size_t nb, rem;
2532f1f9cceSConrad Meyer 
2542f1f9cceSConrad Meyer 			nb = blks;
255179b21e8SConrad Meyer 			rem = MIN((size_t)i,
256179b21e8SConrad Meyer 			    uio->uio_iov[ind].iov_len - (size_t)k);
2575d7ae54aSConrad Meyer 			idat = (uint8_t *)uio->uio_iov[ind].iov_base + k;
258091d81d1SSam Leffler 
259d295bdeeSPawel Jakub Dawidek 			if (exf->reinit) {
2602f1f9cceSConrad Meyer 				if ((crd->crd_flags & CRD_F_ENCRYPT) != 0 &&
2612f1f9cceSConrad Meyer 				    exf->encrypt_multi == NULL)
262d295bdeeSPawel Jakub Dawidek 					exf->encrypt(sw->sw_kschedule,
263d295bdeeSPawel Jakub Dawidek 					    idat);
2642f1f9cceSConrad Meyer 				else if ((crd->crd_flags & CRD_F_ENCRYPT) != 0) {
2652f1f9cceSConrad Meyer 					nb = rounddown(rem, blks);
2662f1f9cceSConrad Meyer 					exf->encrypt_multi(sw->sw_kschedule,
2672f1f9cceSConrad Meyer 					    idat, nb);
2682f1f9cceSConrad Meyer 				} else if (exf->decrypt_multi == NULL)
269d295bdeeSPawel Jakub Dawidek 					exf->decrypt(sw->sw_kschedule,
270d295bdeeSPawel Jakub Dawidek 					    idat);
2712f1f9cceSConrad Meyer 				else {
2722f1f9cceSConrad Meyer 					nb = rounddown(rem, blks);
2732f1f9cceSConrad Meyer 					exf->decrypt_multi(sw->sw_kschedule,
2742f1f9cceSConrad Meyer 					    idat, nb);
275d295bdeeSPawel Jakub Dawidek 				}
276d295bdeeSPawel Jakub Dawidek 			} else if (crd->crd_flags & CRD_F_ENCRYPT) {
277091d81d1SSam Leffler 				/* XOR with previous block/IV */
278091d81d1SSam Leffler 				for (j = 0; j < blks; j++)
279091d81d1SSam Leffler 					idat[j] ^= ivp[j];
280091d81d1SSam Leffler 
281091d81d1SSam Leffler 				exf->encrypt(sw->sw_kschedule, idat);
282091d81d1SSam Leffler 				ivp = idat;
283091d81d1SSam Leffler 			} else {	/* decrypt */
284091d81d1SSam Leffler 				/*
285091d81d1SSam Leffler 				 * Keep encrypted block to be used
286091d81d1SSam Leffler 				 * in next block's processing.
287091d81d1SSam Leffler 				 */
28808fca7a5SJohn-Mark Gurney 				nivp = (ivp == iv) ? iv2 : iv;
28908fca7a5SJohn-Mark Gurney 				bcopy(idat, nivp, blks);
290091d81d1SSam Leffler 
291091d81d1SSam Leffler 				exf->decrypt(sw->sw_kschedule, idat);
292091d81d1SSam Leffler 
293091d81d1SSam Leffler 				/* XOR with previous block/IV */
294091d81d1SSam Leffler 				for (j = 0; j < blks; j++)
295091d81d1SSam Leffler 					idat[j] ^= ivp[j];
296091d81d1SSam Leffler 
29708fca7a5SJohn-Mark Gurney 				ivp = nivp;
298091d81d1SSam Leffler 			}
299091d81d1SSam Leffler 
3002f1f9cceSConrad Meyer 			count += nb;
3012f1f9cceSConrad Meyer 			k += nb;
3022f1f9cceSConrad Meyer 			i -= nb;
303091d81d1SSam Leffler 		}
304091d81d1SSam Leffler 
305f34a967bSPawel Jakub Dawidek 		/*
30608fca7a5SJohn-Mark Gurney 		 * Advance to the next iov if the end of the current iov
30708fca7a5SJohn-Mark Gurney 		 * is aligned with the end of a cipher block.
30808fca7a5SJohn-Mark Gurney 		 * Note that the code is equivalent to calling:
30908fca7a5SJohn-Mark Gurney 		 *      ind = cuio_getptr(uio, count, &k);
310f34a967bSPawel Jakub Dawidek 		 */
31108fca7a5SJohn-Mark Gurney 		if (i > 0 && k == uio->uio_iov[ind].iov_len) {
31208fca7a5SJohn-Mark Gurney 			k = 0;
31308fca7a5SJohn-Mark Gurney 			ind++;
31408fca7a5SJohn-Mark Gurney 			if (ind >= uio->uio_iovcnt) {
31508fca7a5SJohn-Mark Gurney 				error = EINVAL;
31608fca7a5SJohn-Mark Gurney 				goto out;
31708fca7a5SJohn-Mark Gurney 			}
318f34a967bSPawel Jakub Dawidek 		}
319f34a967bSPawel Jakub Dawidek 	}
320f34a967bSPawel Jakub Dawidek 
32108fca7a5SJohn-Mark Gurney out:
32208fca7a5SJohn-Mark Gurney 	if (iovalloc)
32308fca7a5SJohn-Mark Gurney 		free(iov, M_CRYPTO_DATA);
324091d81d1SSam Leffler 
32508fca7a5SJohn-Mark Gurney 	return (error);
326091d81d1SSam Leffler }
327091d81d1SSam Leffler 
32825b7033bSConrad Meyer static int __result_use_check
329f6c4bc3bSPawel Jakub Dawidek swcr_authprepare(struct auth_hash *axf, struct swcr_data *sw, u_char *key,
330f6c4bc3bSPawel Jakub Dawidek     int klen)
331f6c4bc3bSPawel Jakub Dawidek {
332f6c4bc3bSPawel Jakub Dawidek 	int k;
333f6c4bc3bSPawel Jakub Dawidek 
334f6c4bc3bSPawel Jakub Dawidek 	klen /= 8;
335f6c4bc3bSPawel Jakub Dawidek 
336f6c4bc3bSPawel Jakub Dawidek 	switch (axf->type) {
337f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_MD5_HMAC:
338f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA1_HMAC:
339c97f39ceSConrad Meyer 	case CRYPTO_SHA2_224_HMAC:
340f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_256_HMAC:
341f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_384_HMAC:
342f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_512_HMAC:
343f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_NULL_HMAC:
344f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_RIPEMD160_HMAC:
345f6c4bc3bSPawel Jakub Dawidek 		for (k = 0; k < klen; k++)
346f6c4bc3bSPawel Jakub Dawidek 			key[k] ^= HMAC_IPAD_VAL;
347f6c4bc3bSPawel Jakub Dawidek 
348f6c4bc3bSPawel Jakub Dawidek 		axf->Init(sw->sw_ictx);
349f6c4bc3bSPawel Jakub Dawidek 		axf->Update(sw->sw_ictx, key, klen);
350f6c4bc3bSPawel Jakub Dawidek 		axf->Update(sw->sw_ictx, hmac_ipad_buffer, axf->blocksize - klen);
351f6c4bc3bSPawel Jakub Dawidek 
352f6c4bc3bSPawel Jakub Dawidek 		for (k = 0; k < klen; k++)
353f6c4bc3bSPawel Jakub Dawidek 			key[k] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL);
354f6c4bc3bSPawel Jakub Dawidek 
355f6c4bc3bSPawel Jakub Dawidek 		axf->Init(sw->sw_octx);
356f6c4bc3bSPawel Jakub Dawidek 		axf->Update(sw->sw_octx, key, klen);
357f6c4bc3bSPawel Jakub Dawidek 		axf->Update(sw->sw_octx, hmac_opad_buffer, axf->blocksize - klen);
358f6c4bc3bSPawel Jakub Dawidek 
359f6c4bc3bSPawel Jakub Dawidek 		for (k = 0; k < klen; k++)
360f6c4bc3bSPawel Jakub Dawidek 			key[k] ^= HMAC_OPAD_VAL;
361f6c4bc3bSPawel Jakub Dawidek 		break;
362f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_MD5_KPDK:
363f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA1_KPDK:
3641f4990a6SBjoern A. Zeeb 	{
36577680d96SBjoern A. Zeeb 		/*
36677680d96SBjoern A. Zeeb 		 * We need a buffer that can hold an md5 and a sha1 result
36777680d96SBjoern A. Zeeb 		 * just to throw it away.
36877680d96SBjoern A. Zeeb 		 * What we do here is the initial part of:
36977680d96SBjoern A. Zeeb 		 *   ALGO( key, keyfill, .. )
37077680d96SBjoern A. Zeeb 		 * adding the key to sw_ictx and abusing Final() to get the
37177680d96SBjoern A. Zeeb 		 * "keyfill" padding.
37277680d96SBjoern A. Zeeb 		 * In addition we abuse the sw_octx to save the key to have
37377680d96SBjoern A. Zeeb 		 * it to be able to append it at the end in swcr_authcompute().
37477680d96SBjoern A. Zeeb 		 */
3751f4990a6SBjoern A. Zeeb 		u_char buf[SHA1_RESULTLEN];
3761f4990a6SBjoern A. Zeeb 
377f6c4bc3bSPawel Jakub Dawidek 		sw->sw_klen = klen;
378f6c4bc3bSPawel Jakub Dawidek 		bcopy(key, sw->sw_octx, klen);
379f6c4bc3bSPawel Jakub Dawidek 		axf->Init(sw->sw_ictx);
380f6c4bc3bSPawel Jakub Dawidek 		axf->Update(sw->sw_ictx, key, klen);
3811f4990a6SBjoern A. Zeeb 		axf->Final(buf, sw->sw_ictx);
382f6c4bc3bSPawel Jakub Dawidek 		break;
3831f4990a6SBjoern A. Zeeb 	}
38425b7033bSConrad Meyer 	case CRYPTO_POLY1305:
38525b7033bSConrad Meyer 		if (klen != POLY1305_KEY_LEN) {
38625b7033bSConrad Meyer 			CRYPTDEB("bad poly1305 key size %d", klen);
38725b7033bSConrad Meyer 			return EINVAL;
38825b7033bSConrad Meyer 		}
38925b7033bSConrad Meyer 		/* FALLTHROUGH */
3900e33efe4SConrad Meyer 	case CRYPTO_BLAKE2B:
3910e33efe4SConrad Meyer 	case CRYPTO_BLAKE2S:
3920e33efe4SConrad Meyer 		axf->Setkey(sw->sw_ictx, key, klen);
3930e33efe4SConrad Meyer 		axf->Init(sw->sw_ictx);
3940e33efe4SConrad Meyer 		break;
395f6c4bc3bSPawel Jakub Dawidek 	default:
396f6c4bc3bSPawel Jakub Dawidek 		printf("%s: CRD_F_KEY_EXPLICIT flag given, but algorithm %d "
397f6c4bc3bSPawel Jakub Dawidek 		    "doesn't use keys.\n", __func__, axf->type);
39825b7033bSConrad Meyer 		return EINVAL;
399f6c4bc3bSPawel Jakub Dawidek 	}
40025b7033bSConrad Meyer 	return 0;
401f6c4bc3bSPawel Jakub Dawidek }
402f6c4bc3bSPawel Jakub Dawidek 
403091d81d1SSam Leffler /*
404091d81d1SSam Leffler  * Compute keyed-hash authenticator.
405091d81d1SSam Leffler  */
406091d81d1SSam Leffler static int
40738d2f8d6SPawel Jakub Dawidek swcr_authcompute(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf,
408f34a967bSPawel Jakub Dawidek     int flags)
409091d81d1SSam Leffler {
4100bbc4bf9SPawel Jakub Dawidek 	unsigned char aalg[HASH_MAX_LEN];
411091d81d1SSam Leffler 	struct auth_hash *axf;
412091d81d1SSam Leffler 	union authctx ctx;
413091d81d1SSam Leffler 	int err;
414091d81d1SSam Leffler 
415091d81d1SSam Leffler 	if (sw->sw_ictx == 0)
416091d81d1SSam Leffler 		return EINVAL;
417091d81d1SSam Leffler 
418091d81d1SSam Leffler 	axf = sw->sw_axf;
419091d81d1SSam Leffler 
42025b7033bSConrad Meyer 	if (crd->crd_flags & CRD_F_KEY_EXPLICIT) {
42125b7033bSConrad Meyer 		err = swcr_authprepare(axf, sw, crd->crd_key, crd->crd_klen);
42225b7033bSConrad Meyer 		if (err != 0)
42325b7033bSConrad Meyer 			return err;
42425b7033bSConrad Meyer 	}
425f6c4bc3bSPawel Jakub Dawidek 
426091d81d1SSam Leffler 	bcopy(sw->sw_ictx, &ctx, axf->ctxsize);
427091d81d1SSam Leffler 
428f34a967bSPawel Jakub Dawidek 	err = crypto_apply(flags, buf, crd->crd_skip, crd->crd_len,
429f34a967bSPawel Jakub Dawidek 	    (int (*)(void *, void *, unsigned int))axf->Update, (caddr_t)&ctx);
430091d81d1SSam Leffler 	if (err)
431091d81d1SSam Leffler 		return err;
432091d81d1SSam Leffler 
433091d81d1SSam Leffler 	switch (sw->sw_alg) {
434c4729f6eSConrad Meyer 	case CRYPTO_SHA1:
435c4729f6eSConrad Meyer 	case CRYPTO_SHA2_224:
436c4729f6eSConrad Meyer 	case CRYPTO_SHA2_256:
437c4729f6eSConrad Meyer 	case CRYPTO_SHA2_384:
438c4729f6eSConrad Meyer 	case CRYPTO_SHA2_512:
439c4729f6eSConrad Meyer 		axf->Final(aalg, &ctx);
440c4729f6eSConrad Meyer 		break;
441c4729f6eSConrad Meyer 
442091d81d1SSam Leffler 	case CRYPTO_MD5_HMAC:
443091d81d1SSam Leffler 	case CRYPTO_SHA1_HMAC:
444c97f39ceSConrad Meyer 	case CRYPTO_SHA2_224_HMAC:
445f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_256_HMAC:
446f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_384_HMAC:
447f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_512_HMAC:
448091d81d1SSam Leffler 	case CRYPTO_RIPEMD160_HMAC:
449091d81d1SSam Leffler 		if (sw->sw_octx == NULL)
450091d81d1SSam Leffler 			return EINVAL;
451091d81d1SSam Leffler 
452091d81d1SSam Leffler 		axf->Final(aalg, &ctx);
453091d81d1SSam Leffler 		bcopy(sw->sw_octx, &ctx, axf->ctxsize);
454091d81d1SSam Leffler 		axf->Update(&ctx, aalg, axf->hashsize);
455091d81d1SSam Leffler 		axf->Final(aalg, &ctx);
456091d81d1SSam Leffler 		break;
457091d81d1SSam Leffler 
458091d81d1SSam Leffler 	case CRYPTO_MD5_KPDK:
459091d81d1SSam Leffler 	case CRYPTO_SHA1_KPDK:
46077680d96SBjoern A. Zeeb 		/* If we have no key saved, return error. */
461091d81d1SSam Leffler 		if (sw->sw_octx == NULL)
462091d81d1SSam Leffler 			return EINVAL;
463091d81d1SSam Leffler 
46477680d96SBjoern A. Zeeb 		/*
46577680d96SBjoern A. Zeeb 		 * Add the trailing copy of the key (see comment in
46677680d96SBjoern A. Zeeb 		 * swcr_authprepare()) after the data:
46777680d96SBjoern A. Zeeb 		 *   ALGO( .., key, algofill )
46877680d96SBjoern A. Zeeb 		 * and let Final() do the proper, natural "algofill"
46977680d96SBjoern A. Zeeb 		 * padding.
47077680d96SBjoern A. Zeeb 		 */
471091d81d1SSam Leffler 		axf->Update(&ctx, sw->sw_octx, sw->sw_klen);
472091d81d1SSam Leffler 		axf->Final(aalg, &ctx);
473091d81d1SSam Leffler 		break;
474091d81d1SSam Leffler 
4750e33efe4SConrad Meyer 	case CRYPTO_BLAKE2B:
4760e33efe4SConrad Meyer 	case CRYPTO_BLAKE2S:
477091d81d1SSam Leffler 	case CRYPTO_NULL_HMAC:
47825b7033bSConrad Meyer 	case CRYPTO_POLY1305:
479091d81d1SSam Leffler 		axf->Final(aalg, &ctx);
480091d81d1SSam Leffler 		break;
481091d81d1SSam Leffler 	}
482091d81d1SSam Leffler 
483091d81d1SSam Leffler 	/* Inject the authentication data */
484f34a967bSPawel Jakub Dawidek 	crypto_copyback(flags, buf, crd->crd_inject,
485f6c4bc3bSPawel Jakub Dawidek 	    sw->sw_mlen == 0 ? axf->hashsize : sw->sw_mlen, aalg);
486091d81d1SSam Leffler 	return 0;
487091d81d1SSam Leffler }
488091d81d1SSam Leffler 
48908fca7a5SJohn-Mark Gurney CTASSERT(INT_MAX <= (1ll<<39) - 256);	/* GCM: plain text < 2^39-256 */
49008fca7a5SJohn-Mark Gurney CTASSERT(INT_MAX <= (uint64_t)-1);	/* GCM: associated data <= 2^64-1 */
49108fca7a5SJohn-Mark Gurney 
49208fca7a5SJohn-Mark Gurney /*
49308fca7a5SJohn-Mark Gurney  * Apply a combined encryption-authentication transformation
49408fca7a5SJohn-Mark Gurney  */
49508fca7a5SJohn-Mark Gurney static int
49608fca7a5SJohn-Mark Gurney swcr_authenc(struct cryptop *crp)
49708fca7a5SJohn-Mark Gurney {
49808fca7a5SJohn-Mark Gurney 	uint32_t blkbuf[howmany(EALG_MAX_BLOCK_LEN, sizeof(uint32_t))];
49908fca7a5SJohn-Mark Gurney 	u_char *blk = (u_char *)blkbuf;
50008fca7a5SJohn-Mark Gurney 	u_char aalg[AALG_MAX_RESULT_LEN];
50108fca7a5SJohn-Mark Gurney 	u_char uaalg[AALG_MAX_RESULT_LEN];
50208fca7a5SJohn-Mark Gurney 	u_char iv[EALG_MAX_BLOCK_LEN];
50308fca7a5SJohn-Mark Gurney 	union authctx ctx;
5049ebbebe4SConrad Meyer 	struct swcr_session *ses;
50508fca7a5SJohn-Mark Gurney 	struct cryptodesc *crd, *crda = NULL, *crde = NULL;
50608fca7a5SJohn-Mark Gurney 	struct swcr_data *sw, *swa, *swe = NULL;
50708fca7a5SJohn-Mark Gurney 	struct auth_hash *axf = NULL;
50808fca7a5SJohn-Mark Gurney 	struct enc_xform *exf = NULL;
50908fca7a5SJohn-Mark Gurney 	caddr_t buf = (caddr_t)crp->crp_buf;
51008fca7a5SJohn-Mark Gurney 	uint32_t *blkp;
51108fca7a5SJohn-Mark Gurney 	int aadlen, blksz, i, ivlen, len, iskip, oskip, r;
512*507281e5SSean Eric Fagan 	int isccm = 0;
51308fca7a5SJohn-Mark Gurney 
51408fca7a5SJohn-Mark Gurney 	ivlen = blksz = iskip = oskip = 0;
51508fca7a5SJohn-Mark Gurney 
5169ebbebe4SConrad Meyer 	ses = crypto_get_driver_session(crp->crp_session);
5179ebbebe4SConrad Meyer 
51808fca7a5SJohn-Mark Gurney 	for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
5199ebbebe4SConrad Meyer 		for (i = 0; i < nitems(ses->swcr_algorithms) &&
5209ebbebe4SConrad Meyer 		    ses->swcr_algorithms[i].sw_alg != crd->crd_alg; i++)
52108fca7a5SJohn-Mark Gurney 			;
5229ebbebe4SConrad Meyer 		if (i == nitems(ses->swcr_algorithms))
52308fca7a5SJohn-Mark Gurney 			return (EINVAL);
52408fca7a5SJohn-Mark Gurney 
5259ebbebe4SConrad Meyer 		sw = &ses->swcr_algorithms[i];
52608fca7a5SJohn-Mark Gurney 		switch (sw->sw_alg) {
527*507281e5SSean Eric Fagan 		case CRYPTO_AES_CCM_16:
52808fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_NIST_GCM_16:
52908fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_NIST_GMAC:
53008fca7a5SJohn-Mark Gurney 			swe = sw;
53108fca7a5SJohn-Mark Gurney 			crde = crd;
53208fca7a5SJohn-Mark Gurney 			exf = swe->sw_exf;
533*507281e5SSean Eric Fagan 			/* AES_CCM_IV_LEN and AES_GCM_IV_LEN are both 12 */
534*507281e5SSean Eric Fagan 			ivlen = AES_CCM_IV_LEN;
53508fca7a5SJohn-Mark Gurney 			break;
536*507281e5SSean Eric Fagan 		case CRYPTO_AES_CCM_CBC_MAC:
537*507281e5SSean Eric Fagan 			isccm = 1;
538*507281e5SSean Eric Fagan 			/* FALLTHROUGH */
53908fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_128_NIST_GMAC:
54008fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_192_NIST_GMAC:
54108fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_256_NIST_GMAC:
54208fca7a5SJohn-Mark Gurney 			swa = sw;
54308fca7a5SJohn-Mark Gurney 			crda = crd;
54408fca7a5SJohn-Mark Gurney 			axf = swa->sw_axf;
54508fca7a5SJohn-Mark Gurney 			if (swa->sw_ictx == 0)
54608fca7a5SJohn-Mark Gurney 				return (EINVAL);
54708fca7a5SJohn-Mark Gurney 			bcopy(swa->sw_ictx, &ctx, axf->ctxsize);
54808fca7a5SJohn-Mark Gurney 			blksz = axf->blocksize;
54908fca7a5SJohn-Mark Gurney 			break;
55008fca7a5SJohn-Mark Gurney 		default:
55108fca7a5SJohn-Mark Gurney 			return (EINVAL);
55208fca7a5SJohn-Mark Gurney 		}
55308fca7a5SJohn-Mark Gurney 	}
55408fca7a5SJohn-Mark Gurney 	if (crde == NULL || crda == NULL)
55508fca7a5SJohn-Mark Gurney 		return (EINVAL);
556*507281e5SSean Eric Fagan 	/*
557*507281e5SSean Eric Fagan 	 * We need to make sure that the auth algorithm matches the
558*507281e5SSean Eric Fagan 	 * encr algorithm.  Specifically, for AES-GCM must go with
559*507281e5SSean Eric Fagan 	 * AES NIST GMAC, and AES-CCM must go with CBC-MAC.
560*507281e5SSean Eric Fagan 	 */
561*507281e5SSean Eric Fagan 	if (crde->crd_alg == CRYPTO_AES_NIST_GCM_16) {
562*507281e5SSean Eric Fagan 		switch (crda->crd_alg) {
563*507281e5SSean Eric Fagan 		case CRYPTO_AES_128_NIST_GMAC:
564*507281e5SSean Eric Fagan 		case CRYPTO_AES_192_NIST_GMAC:
565*507281e5SSean Eric Fagan 		case CRYPTO_AES_256_NIST_GMAC:
566*507281e5SSean Eric Fagan 			break;	/* Good! */
567*507281e5SSean Eric Fagan 		default:
568*507281e5SSean Eric Fagan 			return (EINVAL);	/* Not good! */
569*507281e5SSean Eric Fagan 		}
570*507281e5SSean Eric Fagan 	} else if (crde->crd_alg == CRYPTO_AES_CCM_16 &&
571*507281e5SSean Eric Fagan 	    crda->crd_alg != CRYPTO_AES_CCM_CBC_MAC)
572*507281e5SSean Eric Fagan 		return (EINVAL);
57308fca7a5SJohn-Mark Gurney 
574*507281e5SSean Eric Fagan 	if ((crde->crd_alg == CRYPTO_AES_NIST_GCM_16 ||
575*507281e5SSean Eric Fagan 	     crde->crd_alg == CRYPTO_AES_CCM_16) &&
57608fca7a5SJohn-Mark Gurney 	    (crde->crd_flags & CRD_F_IV_EXPLICIT) == 0)
57708fca7a5SJohn-Mark Gurney 		return (EINVAL);
57808fca7a5SJohn-Mark Gurney 
57908fca7a5SJohn-Mark Gurney 	if (crde->crd_klen != crda->crd_klen)
58008fca7a5SJohn-Mark Gurney 		return (EINVAL);
58108fca7a5SJohn-Mark Gurney 
58208fca7a5SJohn-Mark Gurney 	/* Initialize the IV */
58308fca7a5SJohn-Mark Gurney 	if (crde->crd_flags & CRD_F_ENCRYPT) {
58408fca7a5SJohn-Mark Gurney 		/* IV explicitly provided ? */
58508fca7a5SJohn-Mark Gurney 		if (crde->crd_flags & CRD_F_IV_EXPLICIT)
58608fca7a5SJohn-Mark Gurney 			bcopy(crde->crd_iv, iv, ivlen);
58708fca7a5SJohn-Mark Gurney 		else
58808fca7a5SJohn-Mark Gurney 			arc4rand(iv, ivlen, 0);
58908fca7a5SJohn-Mark Gurney 
59008fca7a5SJohn-Mark Gurney 		/* Do we need to write the IV */
59108fca7a5SJohn-Mark Gurney 		if (!(crde->crd_flags & CRD_F_IV_PRESENT))
59208fca7a5SJohn-Mark Gurney 			crypto_copyback(crp->crp_flags, buf, crde->crd_inject,
59308fca7a5SJohn-Mark Gurney 			    ivlen, iv);
59408fca7a5SJohn-Mark Gurney 
59508fca7a5SJohn-Mark Gurney 	} else {	/* Decryption */
59608fca7a5SJohn-Mark Gurney 			/* IV explicitly provided ? */
59708fca7a5SJohn-Mark Gurney 		if (crde->crd_flags & CRD_F_IV_EXPLICIT)
59808fca7a5SJohn-Mark Gurney 			bcopy(crde->crd_iv, iv, ivlen);
59908fca7a5SJohn-Mark Gurney 		else {
60008fca7a5SJohn-Mark Gurney 			/* Get IV off buf */
60108fca7a5SJohn-Mark Gurney 			crypto_copydata(crp->crp_flags, buf, crde->crd_inject,
60208fca7a5SJohn-Mark Gurney 			    ivlen, iv);
60308fca7a5SJohn-Mark Gurney 		}
60408fca7a5SJohn-Mark Gurney 	}
60508fca7a5SJohn-Mark Gurney 
606*507281e5SSean Eric Fagan 	if (swa->sw_alg == CRYPTO_AES_CCM_CBC_MAC) {
607*507281e5SSean Eric Fagan 		/*
608*507281e5SSean Eric Fagan 		 * AES CCM-CBC needs to know the length of
609*507281e5SSean Eric Fagan 		 * both the auth data, and payload data, before
610*507281e5SSean Eric Fagan 		 * doing the auth computation.
611*507281e5SSean Eric Fagan 		 */
612*507281e5SSean Eric Fagan 		ctx.aes_cbc_mac_ctx.authDataLength = crda->crd_len;
613*507281e5SSean Eric Fagan 		ctx.aes_cbc_mac_ctx.cryptDataLength = crde->crd_len;
614*507281e5SSean Eric Fagan 	}
61508fca7a5SJohn-Mark Gurney 	/* Supply MAC with IV */
61608fca7a5SJohn-Mark Gurney 	if (axf->Reinit)
61708fca7a5SJohn-Mark Gurney 		axf->Reinit(&ctx, iv, ivlen);
61808fca7a5SJohn-Mark Gurney 
61908fca7a5SJohn-Mark Gurney 	/* Supply MAC with AAD */
62008fca7a5SJohn-Mark Gurney 	aadlen = crda->crd_len;
62108fca7a5SJohn-Mark Gurney 
62208fca7a5SJohn-Mark Gurney 	for (i = iskip; i < crda->crd_len; i += blksz) {
62308fca7a5SJohn-Mark Gurney 		len = MIN(crda->crd_len - i, blksz - oskip);
62408fca7a5SJohn-Mark Gurney 		crypto_copydata(crp->crp_flags, buf, crda->crd_skip + i, len,
62508fca7a5SJohn-Mark Gurney 		    blk + oskip);
62608fca7a5SJohn-Mark Gurney 		bzero(blk + len + oskip, blksz - len - oskip);
62708fca7a5SJohn-Mark Gurney 		axf->Update(&ctx, blk, blksz);
62808fca7a5SJohn-Mark Gurney 		oskip = 0; /* reset initial output offset */
62908fca7a5SJohn-Mark Gurney 	}
63008fca7a5SJohn-Mark Gurney 
63108fca7a5SJohn-Mark Gurney 	if (exf->reinit)
63208fca7a5SJohn-Mark Gurney 		exf->reinit(swe->sw_kschedule, iv);
63308fca7a5SJohn-Mark Gurney 
63408fca7a5SJohn-Mark Gurney 	/* Do encryption/decryption with MAC */
6352f1f9cceSConrad Meyer 	for (i = 0; i < crde->crd_len; i += len) {
6362f1f9cceSConrad Meyer 		if (exf->encrypt_multi != NULL) {
6372f1f9cceSConrad Meyer 			len = rounddown(crde->crd_len - i, blksz);
6382f1f9cceSConrad Meyer 			if (len == 0)
6392f1f9cceSConrad Meyer 				len = blksz;
6402f1f9cceSConrad Meyer 			else
6412f1f9cceSConrad Meyer 				len = MIN(len, sizeof(blkbuf));
6422f1f9cceSConrad Meyer 		} else
6432f1f9cceSConrad Meyer 			len = blksz;
6442f1f9cceSConrad Meyer 		len = MIN(crde->crd_len - i, len);
64508fca7a5SJohn-Mark Gurney 		if (len < blksz)
64608fca7a5SJohn-Mark Gurney 			bzero(blk, blksz);
64708fca7a5SJohn-Mark Gurney 		crypto_copydata(crp->crp_flags, buf, crde->crd_skip + i, len,
64808fca7a5SJohn-Mark Gurney 		    blk);
649*507281e5SSean Eric Fagan 		/*
650*507281e5SSean Eric Fagan 		 * One of the problems with CCM+CBC is that the authentication
651*507281e5SSean Eric Fagan 		 * is done on the unecncrypted data.  As a result, we have
652*507281e5SSean Eric Fagan 		 * to do the authentication update at different times,
653*507281e5SSean Eric Fagan 		 * depending on whether it's CCM or not.
654*507281e5SSean Eric Fagan 		 */
65508fca7a5SJohn-Mark Gurney 		if (crde->crd_flags & CRD_F_ENCRYPT) {
656*507281e5SSean Eric Fagan 			if (isccm)
657*507281e5SSean Eric Fagan 				axf->Update(&ctx, blk, len);
6582f1f9cceSConrad Meyer 			if (exf->encrypt_multi != NULL)
6592f1f9cceSConrad Meyer 				exf->encrypt_multi(swe->sw_kschedule, blk,
6602f1f9cceSConrad Meyer 				    len);
6612f1f9cceSConrad Meyer 			else
66208fca7a5SJohn-Mark Gurney 				exf->encrypt(swe->sw_kschedule, blk);
663*507281e5SSean Eric Fagan 			if (!isccm)
66408fca7a5SJohn-Mark Gurney 				axf->Update(&ctx, blk, len);
66508fca7a5SJohn-Mark Gurney 			crypto_copyback(crp->crp_flags, buf,
66608fca7a5SJohn-Mark Gurney 			    crde->crd_skip + i, len, blk);
66708fca7a5SJohn-Mark Gurney 		} else {
668*507281e5SSean Eric Fagan 			if (isccm) {
669*507281e5SSean Eric Fagan 				KASSERT(exf->encrypt_multi == NULL,
670*507281e5SSean Eric Fagan 				    ("assume CCM is single-block only"));
671*507281e5SSean Eric Fagan 				exf->decrypt(swe->sw_kschedule, blk);
672*507281e5SSean Eric Fagan 			}
67308fca7a5SJohn-Mark Gurney 			axf->Update(&ctx, blk, len);
67408fca7a5SJohn-Mark Gurney 		}
67508fca7a5SJohn-Mark Gurney 	}
67608fca7a5SJohn-Mark Gurney 
67708fca7a5SJohn-Mark Gurney 	/* Do any required special finalization */
67808fca7a5SJohn-Mark Gurney 	switch (crda->crd_alg) {
67908fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_128_NIST_GMAC:
68008fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_192_NIST_GMAC:
68108fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_256_NIST_GMAC:
68208fca7a5SJohn-Mark Gurney 			/* length block */
68308fca7a5SJohn-Mark Gurney 			bzero(blk, blksz);
68408fca7a5SJohn-Mark Gurney 			blkp = (uint32_t *)blk + 1;
68508fca7a5SJohn-Mark Gurney 			*blkp = htobe32(aadlen * 8);
68608fca7a5SJohn-Mark Gurney 			blkp = (uint32_t *)blk + 3;
68708fca7a5SJohn-Mark Gurney 			*blkp = htobe32(crde->crd_len * 8);
68808fca7a5SJohn-Mark Gurney 			axf->Update(&ctx, blk, blksz);
68908fca7a5SJohn-Mark Gurney 			break;
69008fca7a5SJohn-Mark Gurney 	}
69108fca7a5SJohn-Mark Gurney 
69208fca7a5SJohn-Mark Gurney 	/* Finalize MAC */
69308fca7a5SJohn-Mark Gurney 	axf->Final(aalg, &ctx);
69408fca7a5SJohn-Mark Gurney 
69508fca7a5SJohn-Mark Gurney 	/* Validate tag */
69608fca7a5SJohn-Mark Gurney 	if (!(crde->crd_flags & CRD_F_ENCRYPT)) {
69708fca7a5SJohn-Mark Gurney 		crypto_copydata(crp->crp_flags, buf, crda->crd_inject,
69808fca7a5SJohn-Mark Gurney 		    axf->hashsize, uaalg);
69908fca7a5SJohn-Mark Gurney 
70008fca7a5SJohn-Mark Gurney 		r = timingsafe_bcmp(aalg, uaalg, axf->hashsize);
70108fca7a5SJohn-Mark Gurney 		if (r == 0) {
70208fca7a5SJohn-Mark Gurney 			/* tag matches, decrypt data */
703*507281e5SSean Eric Fagan 			if (isccm) {
704*507281e5SSean Eric Fagan 				KASSERT(exf->reinit != NULL,
705*507281e5SSean Eric Fagan 				    ("AES-CCM reinit function must be set"));
706*507281e5SSean Eric Fagan 				exf->reinit(swe->sw_kschedule, iv);
707*507281e5SSean Eric Fagan 			}
70808fca7a5SJohn-Mark Gurney 			for (i = 0; i < crde->crd_len; i += blksz) {
70908fca7a5SJohn-Mark Gurney 				len = MIN(crde->crd_len - i, blksz);
71008fca7a5SJohn-Mark Gurney 				if (len < blksz)
71108fca7a5SJohn-Mark Gurney 					bzero(blk, blksz);
71208fca7a5SJohn-Mark Gurney 				crypto_copydata(crp->crp_flags, buf,
71308fca7a5SJohn-Mark Gurney 				    crde->crd_skip + i, len, blk);
71408fca7a5SJohn-Mark Gurney 				exf->decrypt(swe->sw_kschedule, blk);
71508fca7a5SJohn-Mark Gurney 				crypto_copyback(crp->crp_flags, buf,
71608fca7a5SJohn-Mark Gurney 				    crde->crd_skip + i, len, blk);
71708fca7a5SJohn-Mark Gurney 			}
71808fca7a5SJohn-Mark Gurney 		} else
71908fca7a5SJohn-Mark Gurney 			return (EBADMSG);
72008fca7a5SJohn-Mark Gurney 	} else {
72108fca7a5SJohn-Mark Gurney 		/* Inject the authentication data */
72208fca7a5SJohn-Mark Gurney 		crypto_copyback(crp->crp_flags, buf, crda->crd_inject,
72308fca7a5SJohn-Mark Gurney 		    axf->hashsize, aalg);
72408fca7a5SJohn-Mark Gurney 	}
72508fca7a5SJohn-Mark Gurney 
72608fca7a5SJohn-Mark Gurney 	return (0);
72708fca7a5SJohn-Mark Gurney }
72808fca7a5SJohn-Mark Gurney 
729091d81d1SSam Leffler /*
730091d81d1SSam Leffler  * Apply a compression/decompression algorithm
731091d81d1SSam Leffler  */
732091d81d1SSam Leffler static int
733091d81d1SSam Leffler swcr_compdec(struct cryptodesc *crd, struct swcr_data *sw,
734f34a967bSPawel Jakub Dawidek     caddr_t buf, int flags)
735091d81d1SSam Leffler {
736091d81d1SSam Leffler 	u_int8_t *data, *out;
737091d81d1SSam Leffler 	struct comp_algo *cxf;
738091d81d1SSam Leffler 	int adj;
739091d81d1SSam Leffler 	u_int32_t result;
740091d81d1SSam Leffler 
741091d81d1SSam Leffler 	cxf = sw->sw_cxf;
742091d81d1SSam Leffler 
743091d81d1SSam Leffler 	/* We must handle the whole buffer of data in one time
744091d81d1SSam Leffler 	 * then if there is not all the data in the mbuf, we must
745091d81d1SSam Leffler 	 * copy in a buffer.
746091d81d1SSam Leffler 	 */
747091d81d1SSam Leffler 
7481ede983cSDag-Erling Smørgrav 	data = malloc(crd->crd_len, M_CRYPTO_DATA,  M_NOWAIT);
749091d81d1SSam Leffler 	if (data == NULL)
750091d81d1SSam Leffler 		return (EINVAL);
751f34a967bSPawel Jakub Dawidek 	crypto_copydata(flags, buf, crd->crd_skip, crd->crd_len, data);
752091d81d1SSam Leffler 
753091d81d1SSam Leffler 	if (crd->crd_flags & CRD_F_COMP)
754091d81d1SSam Leffler 		result = cxf->compress(data, crd->crd_len, &out);
755091d81d1SSam Leffler 	else
756091d81d1SSam Leffler 		result = cxf->decompress(data, crd->crd_len, &out);
757091d81d1SSam Leffler 
7581ede983cSDag-Erling Smørgrav 	free(data, M_CRYPTO_DATA);
759091d81d1SSam Leffler 	if (result == 0)
760091d81d1SSam Leffler 		return EINVAL;
761091d81d1SSam Leffler 
762091d81d1SSam Leffler 	/* Copy back the (de)compressed data. m_copyback is
763091d81d1SSam Leffler 	 * extending the mbuf as necessary.
764091d81d1SSam Leffler 	 */
765091d81d1SSam Leffler 	sw->sw_size = result;
766091d81d1SSam Leffler 	/* Check the compressed size when doing compression */
767091d81d1SSam Leffler 	if (crd->crd_flags & CRD_F_COMP) {
768df4dece1SBjoern A. Zeeb 		if (result >= crd->crd_len) {
769091d81d1SSam Leffler 			/* Compression was useless, we lost time */
7701ede983cSDag-Erling Smørgrav 			free(out, M_CRYPTO_DATA);
771091d81d1SSam Leffler 			return 0;
772091d81d1SSam Leffler 		}
773091d81d1SSam Leffler 	}
774091d81d1SSam Leffler 
775f34a967bSPawel Jakub Dawidek 	crypto_copyback(flags, buf, crd->crd_skip, result, out);
776091d81d1SSam Leffler 	if (result < crd->crd_len) {
777091d81d1SSam Leffler 		adj = result - crd->crd_len;
778f34a967bSPawel Jakub Dawidek 		if (flags & CRYPTO_F_IMBUF) {
779091d81d1SSam Leffler 			adj = result - crd->crd_len;
780091d81d1SSam Leffler 			m_adj((struct mbuf *)buf, adj);
781f34a967bSPawel Jakub Dawidek 		} else if (flags & CRYPTO_F_IOV) {
782091d81d1SSam Leffler 			struct uio *uio = (struct uio *)buf;
783091d81d1SSam Leffler 			int ind;
784091d81d1SSam Leffler 
785091d81d1SSam Leffler 			adj = crd->crd_len - result;
786091d81d1SSam Leffler 			ind = uio->uio_iovcnt - 1;
787091d81d1SSam Leffler 
788091d81d1SSam Leffler 			while (adj > 0 && ind >= 0) {
789091d81d1SSam Leffler 				if (adj < uio->uio_iov[ind].iov_len) {
790091d81d1SSam Leffler 					uio->uio_iov[ind].iov_len -= adj;
791091d81d1SSam Leffler 					break;
792091d81d1SSam Leffler 				}
793091d81d1SSam Leffler 
794091d81d1SSam Leffler 				adj -= uio->uio_iov[ind].iov_len;
795091d81d1SSam Leffler 				uio->uio_iov[ind].iov_len = 0;
796091d81d1SSam Leffler 				ind--;
797091d81d1SSam Leffler 				uio->uio_iovcnt--;
798091d81d1SSam Leffler 			}
799091d81d1SSam Leffler 		}
800091d81d1SSam Leffler 	}
8011ede983cSDag-Erling Smørgrav 	free(out, M_CRYPTO_DATA);
802091d81d1SSam Leffler 	return 0;
803091d81d1SSam Leffler }
804091d81d1SSam Leffler 
805091d81d1SSam Leffler /*
806091d81d1SSam Leffler  * Generate a new software session.
807091d81d1SSam Leffler  */
808091d81d1SSam Leffler static int
8091b0909d5SConrad Meyer swcr_newsession(device_t dev, crypto_session_t cses, struct cryptoini *cri)
810091d81d1SSam Leffler {
8119ebbebe4SConrad Meyer 	struct swcr_session *ses;
8129ebbebe4SConrad Meyer 	struct swcr_data *swd;
813091d81d1SSam Leffler 	struct auth_hash *axf;
814091d81d1SSam Leffler 	struct enc_xform *txf;
815091d81d1SSam Leffler 	struct comp_algo *cxf;
8169ebbebe4SConrad Meyer 	size_t i;
817a2bc81bfSJohn-Mark Gurney 	int len;
818f6c4bc3bSPawel Jakub Dawidek 	int error;
819091d81d1SSam Leffler 
8201b0909d5SConrad Meyer 	if (cses == NULL || cri == NULL)
821091d81d1SSam Leffler 		return EINVAL;
822091d81d1SSam Leffler 
8231b0909d5SConrad Meyer 	ses = crypto_get_driver_session(cses);
824a7fcb1afSSean Eric Fagan 	mtx_init(&ses->swcr_lock, "swcr session lock", NULL, MTX_DEF);
825091d81d1SSam Leffler 
8269ebbebe4SConrad Meyer 	for (i = 0; cri != NULL && i < nitems(ses->swcr_algorithms); i++) {
8279ebbebe4SConrad Meyer 		swd = &ses->swcr_algorithms[i];
828091d81d1SSam Leffler 
829091d81d1SSam Leffler 		switch (cri->cri_alg) {
830091d81d1SSam Leffler 		case CRYPTO_DES_CBC:
831091d81d1SSam Leffler 			txf = &enc_xform_des;
832091d81d1SSam Leffler 			goto enccommon;
833091d81d1SSam Leffler 		case CRYPTO_3DES_CBC:
834091d81d1SSam Leffler 			txf = &enc_xform_3des;
835091d81d1SSam Leffler 			goto enccommon;
836091d81d1SSam Leffler 		case CRYPTO_BLF_CBC:
837091d81d1SSam Leffler 			txf = &enc_xform_blf;
838091d81d1SSam Leffler 			goto enccommon;
839091d81d1SSam Leffler 		case CRYPTO_CAST_CBC:
840091d81d1SSam Leffler 			txf = &enc_xform_cast5;
841091d81d1SSam Leffler 			goto enccommon;
842091d81d1SSam Leffler 		case CRYPTO_SKIPJACK_CBC:
843091d81d1SSam Leffler 			txf = &enc_xform_skipjack;
844091d81d1SSam Leffler 			goto enccommon;
845091d81d1SSam Leffler 		case CRYPTO_RIJNDAEL128_CBC:
846091d81d1SSam Leffler 			txf = &enc_xform_rijndael128;
847091d81d1SSam Leffler 			goto enccommon;
848d295bdeeSPawel Jakub Dawidek 		case CRYPTO_AES_XTS:
849d295bdeeSPawel Jakub Dawidek 			txf = &enc_xform_aes_xts;
850d295bdeeSPawel Jakub Dawidek 			goto enccommon;
85108fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_ICM:
85208fca7a5SJohn-Mark Gurney 			txf = &enc_xform_aes_icm;
85308fca7a5SJohn-Mark Gurney 			goto enccommon;
85408fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_NIST_GCM_16:
85508fca7a5SJohn-Mark Gurney 			txf = &enc_xform_aes_nist_gcm;
85608fca7a5SJohn-Mark Gurney 			goto enccommon;
857*507281e5SSean Eric Fagan 		case CRYPTO_AES_CCM_16:
858*507281e5SSean Eric Fagan 			txf = &enc_xform_ccm;
859*507281e5SSean Eric Fagan 			goto enccommon;
86008fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_NIST_GMAC:
86108fca7a5SJohn-Mark Gurney 			txf = &enc_xform_aes_nist_gmac;
8629ebbebe4SConrad Meyer 			swd->sw_exf = txf;
86308fca7a5SJohn-Mark Gurney 			break;
864559d3390SGeorge V. Neville-Neil 		case CRYPTO_CAMELLIA_CBC:
865559d3390SGeorge V. Neville-Neil 			txf = &enc_xform_camellia;
866559d3390SGeorge V. Neville-Neil 			goto enccommon;
867091d81d1SSam Leffler 		case CRYPTO_NULL_CBC:
868091d81d1SSam Leffler 			txf = &enc_xform_null;
869091d81d1SSam Leffler 			goto enccommon;
87061590291SConrad Meyer 		case CRYPTO_CHACHA20:
87161590291SConrad Meyer 			txf = &enc_xform_chacha20;
87261590291SConrad Meyer 			goto enccommon;
873091d81d1SSam Leffler 		enccommon:
874f6c4bc3bSPawel Jakub Dawidek 			if (cri->cri_key != NULL) {
8759ebbebe4SConrad Meyer 				error = txf->setkey(&swd->sw_kschedule,
876091d81d1SSam Leffler 				    cri->cri_key, cri->cri_klen / 8);
877091d81d1SSam Leffler 				if (error) {
8781b0909d5SConrad Meyer 					swcr_freesession(dev, cses);
879091d81d1SSam Leffler 					return error;
880091d81d1SSam Leffler 				}
881f6c4bc3bSPawel Jakub Dawidek 			}
8829ebbebe4SConrad Meyer 			swd->sw_exf = txf;
883091d81d1SSam Leffler 			break;
884091d81d1SSam Leffler 
885091d81d1SSam Leffler 		case CRYPTO_MD5_HMAC:
886f6c4bc3bSPawel Jakub Dawidek 			axf = &auth_hash_hmac_md5;
887091d81d1SSam Leffler 			goto authcommon;
888091d81d1SSam Leffler 		case CRYPTO_SHA1_HMAC:
889f6c4bc3bSPawel Jakub Dawidek 			axf = &auth_hash_hmac_sha1;
890091d81d1SSam Leffler 			goto authcommon;
891c97f39ceSConrad Meyer 		case CRYPTO_SHA2_224_HMAC:
892c97f39ceSConrad Meyer 			axf = &auth_hash_hmac_sha2_224;
893c97f39ceSConrad Meyer 			goto authcommon;
894f6c4bc3bSPawel Jakub Dawidek 		case CRYPTO_SHA2_256_HMAC:
895091d81d1SSam Leffler 			axf = &auth_hash_hmac_sha2_256;
896f6c4bc3bSPawel Jakub Dawidek 			goto authcommon;
897f6c4bc3bSPawel Jakub Dawidek 		case CRYPTO_SHA2_384_HMAC:
898091d81d1SSam Leffler 			axf = &auth_hash_hmac_sha2_384;
899f6c4bc3bSPawel Jakub Dawidek 			goto authcommon;
900f6c4bc3bSPawel Jakub Dawidek 		case CRYPTO_SHA2_512_HMAC:
901091d81d1SSam Leffler 			axf = &auth_hash_hmac_sha2_512;
902091d81d1SSam Leffler 			goto authcommon;
903091d81d1SSam Leffler 		case CRYPTO_NULL_HMAC:
904091d81d1SSam Leffler 			axf = &auth_hash_null;
905091d81d1SSam Leffler 			goto authcommon;
906091d81d1SSam Leffler 		case CRYPTO_RIPEMD160_HMAC:
907f6c4bc3bSPawel Jakub Dawidek 			axf = &auth_hash_hmac_ripemd_160;
908091d81d1SSam Leffler 		authcommon:
9099ebbebe4SConrad Meyer 			swd->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
910091d81d1SSam Leffler 			    M_NOWAIT);
9119ebbebe4SConrad Meyer 			if (swd->sw_ictx == NULL) {
9121b0909d5SConrad Meyer 				swcr_freesession(dev, cses);
913091d81d1SSam Leffler 				return ENOBUFS;
914091d81d1SSam Leffler 			}
915091d81d1SSam Leffler 
9169ebbebe4SConrad Meyer 			swd->sw_octx = malloc(axf->ctxsize, M_CRYPTO_DATA,
917091d81d1SSam Leffler 			    M_NOWAIT);
9189ebbebe4SConrad Meyer 			if (swd->sw_octx == NULL) {
9191b0909d5SConrad Meyer 				swcr_freesession(dev, cses);
920091d81d1SSam Leffler 				return ENOBUFS;
921091d81d1SSam Leffler 			}
922091d81d1SSam Leffler 
923f6c4bc3bSPawel Jakub Dawidek 			if (cri->cri_key != NULL) {
9249ebbebe4SConrad Meyer 				error = swcr_authprepare(axf, swd,
92525b7033bSConrad Meyer 				    cri->cri_key, cri->cri_klen);
92625b7033bSConrad Meyer 				if (error != 0) {
92725b7033bSConrad Meyer 					swcr_freesession(dev, cses);
92825b7033bSConrad Meyer 					return error;
92925b7033bSConrad Meyer 				}
930f6c4bc3bSPawel Jakub Dawidek 			}
931091d81d1SSam Leffler 
9329ebbebe4SConrad Meyer 			swd->sw_mlen = cri->cri_mlen;
9339ebbebe4SConrad Meyer 			swd->sw_axf = axf;
934091d81d1SSam Leffler 			break;
935091d81d1SSam Leffler 
936091d81d1SSam Leffler 		case CRYPTO_MD5_KPDK:
937091d81d1SSam Leffler 			axf = &auth_hash_key_md5;
938091d81d1SSam Leffler 			goto auth2common;
939091d81d1SSam Leffler 
940091d81d1SSam Leffler 		case CRYPTO_SHA1_KPDK:
941091d81d1SSam Leffler 			axf = &auth_hash_key_sha1;
942091d81d1SSam Leffler 		auth2common:
9439ebbebe4SConrad Meyer 			swd->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
944091d81d1SSam Leffler 			    M_NOWAIT);
9459ebbebe4SConrad Meyer 			if (swd->sw_ictx == NULL) {
9461b0909d5SConrad Meyer 				swcr_freesession(dev, cses);
947091d81d1SSam Leffler 				return ENOBUFS;
948091d81d1SSam Leffler 			}
949091d81d1SSam Leffler 
9509ebbebe4SConrad Meyer 			swd->sw_octx = malloc(cri->cri_klen / 8,
951f6c4bc3bSPawel Jakub Dawidek 			    M_CRYPTO_DATA, M_NOWAIT);
9529ebbebe4SConrad Meyer 			if (swd->sw_octx == NULL) {
9531b0909d5SConrad Meyer 				swcr_freesession(dev, cses);
954091d81d1SSam Leffler 				return ENOBUFS;
955091d81d1SSam Leffler 			}
956091d81d1SSam Leffler 
957f6c4bc3bSPawel Jakub Dawidek 			/* Store the key so we can "append" it to the payload */
958f6c4bc3bSPawel Jakub Dawidek 			if (cri->cri_key != NULL) {
9599ebbebe4SConrad Meyer 				error = swcr_authprepare(axf, swd,
96025b7033bSConrad Meyer 				    cri->cri_key, cri->cri_klen);
96125b7033bSConrad Meyer 				if (error != 0) {
96225b7033bSConrad Meyer 					swcr_freesession(dev, cses);
96325b7033bSConrad Meyer 					return error;
96425b7033bSConrad Meyer 				}
965f6c4bc3bSPawel Jakub Dawidek 			}
966f6c4bc3bSPawel Jakub Dawidek 
9679ebbebe4SConrad Meyer 			swd->sw_mlen = cri->cri_mlen;
9689ebbebe4SConrad Meyer 			swd->sw_axf = axf;
969091d81d1SSam Leffler 			break;
970091d81d1SSam Leffler #ifdef notdef
971091d81d1SSam Leffler 		case CRYPTO_MD5:
972091d81d1SSam Leffler 			axf = &auth_hash_md5;
973091d81d1SSam Leffler 			goto auth3common;
974c4729f6eSConrad Meyer #endif
975091d81d1SSam Leffler 
976091d81d1SSam Leffler 		case CRYPTO_SHA1:
977091d81d1SSam Leffler 			axf = &auth_hash_sha1;
978c4729f6eSConrad Meyer 			goto auth3common;
979c4729f6eSConrad Meyer 		case CRYPTO_SHA2_224:
980c4729f6eSConrad Meyer 			axf = &auth_hash_sha2_224;
981c4729f6eSConrad Meyer 			goto auth3common;
982c4729f6eSConrad Meyer 		case CRYPTO_SHA2_256:
983c4729f6eSConrad Meyer 			axf = &auth_hash_sha2_256;
984c4729f6eSConrad Meyer 			goto auth3common;
985c4729f6eSConrad Meyer 		case CRYPTO_SHA2_384:
986c4729f6eSConrad Meyer 			axf = &auth_hash_sha2_384;
987c4729f6eSConrad Meyer 			goto auth3common;
988c4729f6eSConrad Meyer 		case CRYPTO_SHA2_512:
989c4729f6eSConrad Meyer 			axf = &auth_hash_sha2_512;
990c4729f6eSConrad Meyer 
991091d81d1SSam Leffler 		auth3common:
9929ebbebe4SConrad Meyer 			swd->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
993091d81d1SSam Leffler 			    M_NOWAIT);
9949ebbebe4SConrad Meyer 			if (swd->sw_ictx == NULL) {
9951b0909d5SConrad Meyer 				swcr_freesession(dev, cses);
996091d81d1SSam Leffler 				return ENOBUFS;
997091d81d1SSam Leffler 			}
998091d81d1SSam Leffler 
9999ebbebe4SConrad Meyer 			axf->Init(swd->sw_ictx);
10009ebbebe4SConrad Meyer 			swd->sw_mlen = cri->cri_mlen;
10019ebbebe4SConrad Meyer 			swd->sw_axf = axf;
1002091d81d1SSam Leffler 			break;
100308fca7a5SJohn-Mark Gurney 
1004*507281e5SSean Eric Fagan 		case CRYPTO_AES_CCM_CBC_MAC:
1005*507281e5SSean Eric Fagan 			switch (cri->cri_klen) {
1006*507281e5SSean Eric Fagan 			case 128:
1007*507281e5SSean Eric Fagan 				axf = &auth_hash_ccm_cbc_mac_128;
1008*507281e5SSean Eric Fagan 				break;
1009*507281e5SSean Eric Fagan 			case 192:
1010*507281e5SSean Eric Fagan 				axf = &auth_hash_ccm_cbc_mac_192;
1011*507281e5SSean Eric Fagan 				break;
1012*507281e5SSean Eric Fagan 			case 256:
1013*507281e5SSean Eric Fagan 				axf = &auth_hash_ccm_cbc_mac_256;
1014*507281e5SSean Eric Fagan 				break;
1015*507281e5SSean Eric Fagan 			default:
1016*507281e5SSean Eric Fagan 				swcr_freesession(dev, cses);
1017*507281e5SSean Eric Fagan 				return EINVAL;
1018*507281e5SSean Eric Fagan 			}
1019*507281e5SSean Eric Fagan 			goto auth4common;
102008fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_128_NIST_GMAC:
102108fca7a5SJohn-Mark Gurney 			axf = &auth_hash_nist_gmac_aes_128;
102208fca7a5SJohn-Mark Gurney 			goto auth4common;
102308fca7a5SJohn-Mark Gurney 
102408fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_192_NIST_GMAC:
102508fca7a5SJohn-Mark Gurney 			axf = &auth_hash_nist_gmac_aes_192;
102608fca7a5SJohn-Mark Gurney 			goto auth4common;
102708fca7a5SJohn-Mark Gurney 
102808fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_256_NIST_GMAC:
102908fca7a5SJohn-Mark Gurney 			axf = &auth_hash_nist_gmac_aes_256;
103008fca7a5SJohn-Mark Gurney 		auth4common:
1031a2bc81bfSJohn-Mark Gurney 			len = cri->cri_klen / 8;
10322e2e26d1SJohn Baldwin 			if (len != 16 && len != 24 && len != 32) {
10331b0909d5SConrad Meyer 				swcr_freesession(dev, cses);
1034a2bc81bfSJohn-Mark Gurney 				return EINVAL;
10352e2e26d1SJohn Baldwin 			}
1036a2bc81bfSJohn-Mark Gurney 
10379ebbebe4SConrad Meyer 			swd->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
103808fca7a5SJohn-Mark Gurney 			    M_NOWAIT);
10399ebbebe4SConrad Meyer 			if (swd->sw_ictx == NULL) {
10401b0909d5SConrad Meyer 				swcr_freesession(dev, cses);
104108fca7a5SJohn-Mark Gurney 				return ENOBUFS;
104208fca7a5SJohn-Mark Gurney 			}
10439ebbebe4SConrad Meyer 			axf->Init(swd->sw_ictx);
10449ebbebe4SConrad Meyer 			axf->Setkey(swd->sw_ictx, cri->cri_key, len);
10459ebbebe4SConrad Meyer 			swd->sw_axf = axf;
104608fca7a5SJohn-Mark Gurney 			break;
104708fca7a5SJohn-Mark Gurney 
10480e33efe4SConrad Meyer 		case CRYPTO_BLAKE2B:
10490e33efe4SConrad Meyer 			axf = &auth_hash_blake2b;
10500e33efe4SConrad Meyer 			goto auth5common;
10510e33efe4SConrad Meyer 		case CRYPTO_BLAKE2S:
10520e33efe4SConrad Meyer 			axf = &auth_hash_blake2s;
105325b7033bSConrad Meyer 			goto auth5common;
105425b7033bSConrad Meyer 		case CRYPTO_POLY1305:
105525b7033bSConrad Meyer 			axf = &auth_hash_poly1305;
10560e33efe4SConrad Meyer 		auth5common:
10579ebbebe4SConrad Meyer 			swd->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
10580e33efe4SConrad Meyer 			    M_NOWAIT);
10599ebbebe4SConrad Meyer 			if (swd->sw_ictx == NULL) {
10601b0909d5SConrad Meyer 				swcr_freesession(dev, cses);
10610e33efe4SConrad Meyer 				return ENOBUFS;
10620e33efe4SConrad Meyer 			}
10639ebbebe4SConrad Meyer 			axf->Setkey(swd->sw_ictx, cri->cri_key,
10640e33efe4SConrad Meyer 			    cri->cri_klen / 8);
10659ebbebe4SConrad Meyer 			axf->Init(swd->sw_ictx);
10669ebbebe4SConrad Meyer 			swd->sw_axf = axf;
10670e33efe4SConrad Meyer 			break;
10680e33efe4SConrad Meyer 
1069091d81d1SSam Leffler 		case CRYPTO_DEFLATE_COMP:
1070091d81d1SSam Leffler 			cxf = &comp_algo_deflate;
10719ebbebe4SConrad Meyer 			swd->sw_cxf = cxf;
1072091d81d1SSam Leffler 			break;
1073091d81d1SSam Leffler 		default:
10741b0909d5SConrad Meyer 			swcr_freesession(dev, cses);
1075091d81d1SSam Leffler 			return EINVAL;
1076091d81d1SSam Leffler 		}
1077091d81d1SSam Leffler 
10789ebbebe4SConrad Meyer 		swd->sw_alg = cri->cri_alg;
1079091d81d1SSam Leffler 		cri = cri->cri_next;
10809ebbebe4SConrad Meyer 		ses->swcr_nalgs++;
10819ebbebe4SConrad Meyer 	}
10829ebbebe4SConrad Meyer 
10839ebbebe4SConrad Meyer 	if (cri != NULL) {
10849ebbebe4SConrad Meyer 		CRYPTDEB("Bogus session request for three or more algorithms");
10859ebbebe4SConrad Meyer 		return EINVAL;
1086091d81d1SSam Leffler 	}
1087091d81d1SSam Leffler 	return 0;
1088091d81d1SSam Leffler }
1089091d81d1SSam Leffler 
10901b0909d5SConrad Meyer static void
10911b0909d5SConrad Meyer swcr_freesession(device_t dev, crypto_session_t cses)
1092109919c6SBenno Rice {
10939ebbebe4SConrad Meyer 	struct swcr_session *ses;
10949ebbebe4SConrad Meyer 	struct swcr_data *swd;
1095091d81d1SSam Leffler 	struct enc_xform *txf;
1096091d81d1SSam Leffler 	struct auth_hash *axf;
10979ebbebe4SConrad Meyer 	size_t i;
1098091d81d1SSam Leffler 
10991b0909d5SConrad Meyer 	ses = crypto_get_driver_session(cses);
1100091d81d1SSam Leffler 
1101a7fcb1afSSean Eric Fagan 	mtx_destroy(&ses->swcr_lock);
11029ebbebe4SConrad Meyer 	for (i = 0; i < nitems(ses->swcr_algorithms); i++) {
11039ebbebe4SConrad Meyer 		swd = &ses->swcr_algorithms[i];
1104091d81d1SSam Leffler 
1105091d81d1SSam Leffler 		switch (swd->sw_alg) {
1106091d81d1SSam Leffler 		case CRYPTO_DES_CBC:
1107091d81d1SSam Leffler 		case CRYPTO_3DES_CBC:
1108091d81d1SSam Leffler 		case CRYPTO_BLF_CBC:
1109091d81d1SSam Leffler 		case CRYPTO_CAST_CBC:
1110091d81d1SSam Leffler 		case CRYPTO_SKIPJACK_CBC:
1111091d81d1SSam Leffler 		case CRYPTO_RIJNDAEL128_CBC:
1112d295bdeeSPawel Jakub Dawidek 		case CRYPTO_AES_XTS:
111308fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_ICM:
111408fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_NIST_GCM_16:
111508fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_NIST_GMAC:
1116559d3390SGeorge V. Neville-Neil 		case CRYPTO_CAMELLIA_CBC:
1117091d81d1SSam Leffler 		case CRYPTO_NULL_CBC:
111861590291SConrad Meyer 		case CRYPTO_CHACHA20:
1119*507281e5SSean Eric Fagan 		case CRYPTO_AES_CCM_16:
1120091d81d1SSam Leffler 			txf = swd->sw_exf;
1121091d81d1SSam Leffler 
1122091d81d1SSam Leffler 			if (swd->sw_kschedule)
1123091d81d1SSam Leffler 				txf->zerokey(&(swd->sw_kschedule));
1124091d81d1SSam Leffler 			break;
1125091d81d1SSam Leffler 
1126091d81d1SSam Leffler 		case CRYPTO_MD5_HMAC:
1127091d81d1SSam Leffler 		case CRYPTO_SHA1_HMAC:
1128c97f39ceSConrad Meyer 		case CRYPTO_SHA2_224_HMAC:
1129f6c4bc3bSPawel Jakub Dawidek 		case CRYPTO_SHA2_256_HMAC:
1130f6c4bc3bSPawel Jakub Dawidek 		case CRYPTO_SHA2_384_HMAC:
1131f6c4bc3bSPawel Jakub Dawidek 		case CRYPTO_SHA2_512_HMAC:
1132091d81d1SSam Leffler 		case CRYPTO_RIPEMD160_HMAC:
1133091d81d1SSam Leffler 		case CRYPTO_NULL_HMAC:
1134*507281e5SSean Eric Fagan 		case CRYPTO_AES_CCM_CBC_MAC:
1135091d81d1SSam Leffler 			axf = swd->sw_axf;
1136091d81d1SSam Leffler 
1137091d81d1SSam Leffler 			if (swd->sw_ictx) {
1138091d81d1SSam Leffler 				bzero(swd->sw_ictx, axf->ctxsize);
1139091d81d1SSam Leffler 				free(swd->sw_ictx, M_CRYPTO_DATA);
1140091d81d1SSam Leffler 			}
1141091d81d1SSam Leffler 			if (swd->sw_octx) {
1142091d81d1SSam Leffler 				bzero(swd->sw_octx, axf->ctxsize);
1143091d81d1SSam Leffler 				free(swd->sw_octx, M_CRYPTO_DATA);
1144091d81d1SSam Leffler 			}
1145091d81d1SSam Leffler 			break;
1146091d81d1SSam Leffler 
1147091d81d1SSam Leffler 		case CRYPTO_MD5_KPDK:
1148091d81d1SSam Leffler 		case CRYPTO_SHA1_KPDK:
1149091d81d1SSam Leffler 			axf = swd->sw_axf;
1150091d81d1SSam Leffler 
1151091d81d1SSam Leffler 			if (swd->sw_ictx) {
1152091d81d1SSam Leffler 				bzero(swd->sw_ictx, axf->ctxsize);
1153091d81d1SSam Leffler 				free(swd->sw_ictx, M_CRYPTO_DATA);
1154091d81d1SSam Leffler 			}
1155091d81d1SSam Leffler 			if (swd->sw_octx) {
1156091d81d1SSam Leffler 				bzero(swd->sw_octx, swd->sw_klen);
1157091d81d1SSam Leffler 				free(swd->sw_octx, M_CRYPTO_DATA);
1158091d81d1SSam Leffler 			}
1159091d81d1SSam Leffler 			break;
1160091d81d1SSam Leffler 
11610e33efe4SConrad Meyer 		case CRYPTO_BLAKE2B:
11620e33efe4SConrad Meyer 		case CRYPTO_BLAKE2S:
1163091d81d1SSam Leffler 		case CRYPTO_MD5:
116425b7033bSConrad Meyer 		case CRYPTO_POLY1305:
1165091d81d1SSam Leffler 		case CRYPTO_SHA1:
1166c4729f6eSConrad Meyer 		case CRYPTO_SHA2_224:
1167c4729f6eSConrad Meyer 		case CRYPTO_SHA2_256:
1168c4729f6eSConrad Meyer 		case CRYPTO_SHA2_384:
1169c4729f6eSConrad Meyer 		case CRYPTO_SHA2_512:
11706062df03SAndrey V. Elsukov 		case CRYPTO_AES_128_NIST_GMAC:
11716062df03SAndrey V. Elsukov 		case CRYPTO_AES_192_NIST_GMAC:
11726062df03SAndrey V. Elsukov 		case CRYPTO_AES_256_NIST_GMAC:
1173091d81d1SSam Leffler 			axf = swd->sw_axf;
1174091d81d1SSam Leffler 
11755fbc5b5aSConrad Meyer 			if (swd->sw_ictx) {
11765fbc5b5aSConrad Meyer 				explicit_bzero(swd->sw_ictx, axf->ctxsize);
1177091d81d1SSam Leffler 				free(swd->sw_ictx, M_CRYPTO_DATA);
11785fbc5b5aSConrad Meyer 			}
1179091d81d1SSam Leffler 			break;
1180091d81d1SSam Leffler 
1181091d81d1SSam Leffler 		case CRYPTO_DEFLATE_COMP:
1182151ba793SAlexander Kabaev 			/* Nothing to do */
1183091d81d1SSam Leffler 			break;
1184091d81d1SSam Leffler 		}
1185091d81d1SSam Leffler 	}
1186091d81d1SSam Leffler }
1187091d81d1SSam Leffler 
1188091d81d1SSam Leffler /*
1189091d81d1SSam Leffler  * Process a software request.
1190091d81d1SSam Leffler  */
1191091d81d1SSam Leffler static int
11926810ad6fSSam Leffler swcr_process(device_t dev, struct cryptop *crp, int hint)
1193091d81d1SSam Leffler {
1194a7fcb1afSSean Eric Fagan 	struct swcr_session *ses = NULL;
1195091d81d1SSam Leffler 	struct cryptodesc *crd;
11969ebbebe4SConrad Meyer 	struct swcr_data *sw;
11979ebbebe4SConrad Meyer 	size_t i;
1198091d81d1SSam Leffler 
1199091d81d1SSam Leffler 	/* Sanity check */
1200091d81d1SSam Leffler 	if (crp == NULL)
1201091d81d1SSam Leffler 		return EINVAL;
1202091d81d1SSam Leffler 
1203091d81d1SSam Leffler 	if (crp->crp_desc == NULL || crp->crp_buf == NULL) {
1204091d81d1SSam Leffler 		crp->crp_etype = EINVAL;
1205091d81d1SSam Leffler 		goto done;
1206091d81d1SSam Leffler 	}
1207091d81d1SSam Leffler 
12081b0909d5SConrad Meyer 	ses = crypto_get_driver_session(crp->crp_session);
1209a7fcb1afSSean Eric Fagan 	mtx_lock(&ses->swcr_lock);
1210091d81d1SSam Leffler 
1211091d81d1SSam Leffler 	/* Go through crypto descriptors, processing as we go */
1212091d81d1SSam Leffler 	for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
1213091d81d1SSam Leffler 		/*
1214091d81d1SSam Leffler 		 * Find the crypto context.
1215091d81d1SSam Leffler 		 *
1216091d81d1SSam Leffler 		 * XXX Note that the logic here prevents us from having
1217091d81d1SSam Leffler 		 * XXX the same algorithm multiple times in a session
1218091d81d1SSam Leffler 		 * XXX (or rather, we can but it won't give us the right
1219091d81d1SSam Leffler 		 * XXX results). To do that, we'd need some way of differentiating
1220091d81d1SSam Leffler 		 * XXX between the various instances of an algorithm (so we can
1221091d81d1SSam Leffler 		 * XXX locate the correct crypto context).
1222091d81d1SSam Leffler 		 */
12239ebbebe4SConrad Meyer 		for (i = 0; i < nitems(ses->swcr_algorithms) &&
12249ebbebe4SConrad Meyer 		    ses->swcr_algorithms[i].sw_alg != crd->crd_alg; i++)
1225091d81d1SSam Leffler 			;
1226091d81d1SSam Leffler 
1227091d81d1SSam Leffler 		/* No such context ? */
12289ebbebe4SConrad Meyer 		if (i == nitems(ses->swcr_algorithms)) {
1229091d81d1SSam Leffler 			crp->crp_etype = EINVAL;
1230091d81d1SSam Leffler 			goto done;
1231091d81d1SSam Leffler 		}
12329ebbebe4SConrad Meyer 		sw = &ses->swcr_algorithms[i];
1233091d81d1SSam Leffler 		switch (sw->sw_alg) {
1234091d81d1SSam Leffler 		case CRYPTO_DES_CBC:
1235091d81d1SSam Leffler 		case CRYPTO_3DES_CBC:
1236091d81d1SSam Leffler 		case CRYPTO_BLF_CBC:
1237091d81d1SSam Leffler 		case CRYPTO_CAST_CBC:
1238091d81d1SSam Leffler 		case CRYPTO_SKIPJACK_CBC:
1239091d81d1SSam Leffler 		case CRYPTO_RIJNDAEL128_CBC:
1240d295bdeeSPawel Jakub Dawidek 		case CRYPTO_AES_XTS:
124108fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_ICM:
1242559d3390SGeorge V. Neville-Neil 		case CRYPTO_CAMELLIA_CBC:
124361590291SConrad Meyer 		case CRYPTO_CHACHA20:
1244091d81d1SSam Leffler 			if ((crp->crp_etype = swcr_encdec(crd, sw,
1245f34a967bSPawel Jakub Dawidek 			    crp->crp_buf, crp->crp_flags)) != 0)
1246091d81d1SSam Leffler 				goto done;
1247091d81d1SSam Leffler 			break;
1248091d81d1SSam Leffler 		case CRYPTO_NULL_CBC:
1249091d81d1SSam Leffler 			crp->crp_etype = 0;
1250091d81d1SSam Leffler 			break;
1251091d81d1SSam Leffler 		case CRYPTO_MD5_HMAC:
1252091d81d1SSam Leffler 		case CRYPTO_SHA1_HMAC:
1253c97f39ceSConrad Meyer 		case CRYPTO_SHA2_224_HMAC:
1254f6c4bc3bSPawel Jakub Dawidek 		case CRYPTO_SHA2_256_HMAC:
1255f6c4bc3bSPawel Jakub Dawidek 		case CRYPTO_SHA2_384_HMAC:
1256f6c4bc3bSPawel Jakub Dawidek 		case CRYPTO_SHA2_512_HMAC:
1257091d81d1SSam Leffler 		case CRYPTO_RIPEMD160_HMAC:
1258091d81d1SSam Leffler 		case CRYPTO_NULL_HMAC:
1259091d81d1SSam Leffler 		case CRYPTO_MD5_KPDK:
1260091d81d1SSam Leffler 		case CRYPTO_SHA1_KPDK:
1261091d81d1SSam Leffler 		case CRYPTO_MD5:
1262091d81d1SSam Leffler 		case CRYPTO_SHA1:
1263c4729f6eSConrad Meyer 		case CRYPTO_SHA2_224:
1264c4729f6eSConrad Meyer 		case CRYPTO_SHA2_256:
1265c4729f6eSConrad Meyer 		case CRYPTO_SHA2_384:
1266c4729f6eSConrad Meyer 		case CRYPTO_SHA2_512:
12670e33efe4SConrad Meyer 		case CRYPTO_BLAKE2B:
12680e33efe4SConrad Meyer 		case CRYPTO_BLAKE2S:
126925b7033bSConrad Meyer 		case CRYPTO_POLY1305:
127038d2f8d6SPawel Jakub Dawidek 			if ((crp->crp_etype = swcr_authcompute(crd, sw,
1271f34a967bSPawel Jakub Dawidek 			    crp->crp_buf, crp->crp_flags)) != 0)
1272091d81d1SSam Leffler 				goto done;
1273091d81d1SSam Leffler 			break;
1274091d81d1SSam Leffler 
127508fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_NIST_GCM_16:
127608fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_NIST_GMAC:
127708fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_128_NIST_GMAC:
127808fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_192_NIST_GMAC:
127908fca7a5SJohn-Mark Gurney 		case CRYPTO_AES_256_NIST_GMAC:
1280*507281e5SSean Eric Fagan 		case CRYPTO_AES_CCM_16:
1281*507281e5SSean Eric Fagan 		case CRYPTO_AES_CCM_CBC_MAC:
128208fca7a5SJohn-Mark Gurney 			crp->crp_etype = swcr_authenc(crp);
128308fca7a5SJohn-Mark Gurney 			goto done;
128408fca7a5SJohn-Mark Gurney 
1285091d81d1SSam Leffler 		case CRYPTO_DEFLATE_COMP:
1286091d81d1SSam Leffler 			if ((crp->crp_etype = swcr_compdec(crd, sw,
1287f34a967bSPawel Jakub Dawidek 			    crp->crp_buf, crp->crp_flags)) != 0)
1288091d81d1SSam Leffler 				goto done;
1289091d81d1SSam Leffler 			else
1290091d81d1SSam Leffler 				crp->crp_olen = (int)sw->sw_size;
1291091d81d1SSam Leffler 			break;
1292091d81d1SSam Leffler 
1293091d81d1SSam Leffler 		default:
1294091d81d1SSam Leffler 			/* Unknown/unsupported algorithm */
1295091d81d1SSam Leffler 			crp->crp_etype = EINVAL;
1296091d81d1SSam Leffler 			goto done;
1297091d81d1SSam Leffler 		}
1298091d81d1SSam Leffler 	}
1299091d81d1SSam Leffler 
1300091d81d1SSam Leffler done:
1301a7fcb1afSSean Eric Fagan 	if (ses)
1302a7fcb1afSSean Eric Fagan 		mtx_unlock(&ses->swcr_lock);
1303091d81d1SSam Leffler 	crypto_done(crp);
1304091d81d1SSam Leffler 	return 0;
1305091d81d1SSam Leffler }
1306091d81d1SSam Leffler 
1307091d81d1SSam Leffler static void
13083f147ab2SWarner Losh swcr_identify(driver_t *drv, device_t parent)
1309091d81d1SSam Leffler {
13106810ad6fSSam Leffler 	/* NB: order 10 is so we get attached after h/w devices */
13116810ad6fSSam Leffler 	if (device_find_child(parent, "cryptosoft", -1) == NULL &&
131286c585d9SMarius Strobl 	    BUS_ADD_CHILD(parent, 10, "cryptosoft", 0) == 0)
13136810ad6fSSam Leffler 		panic("cryptosoft: could not attach");
13146810ad6fSSam Leffler }
1315f6c4bc3bSPawel Jakub Dawidek 
13166810ad6fSSam Leffler static int
13176810ad6fSSam Leffler swcr_probe(device_t dev)
13186810ad6fSSam Leffler {
13196810ad6fSSam Leffler 	device_set_desc(dev, "software crypto");
132086c585d9SMarius Strobl 	return (BUS_PROBE_NOWILDCARD);
13216810ad6fSSam Leffler }
1322f6c4bc3bSPawel Jakub Dawidek 
13236810ad6fSSam Leffler static int
13246810ad6fSSam Leffler swcr_attach(device_t dev)
13256810ad6fSSam Leffler {
13266810ad6fSSam Leffler 	memset(hmac_ipad_buffer, HMAC_IPAD_VAL, HMAC_MAX_BLOCK_LEN);
13276810ad6fSSam Leffler 	memset(hmac_opad_buffer, HMAC_OPAD_VAL, HMAC_MAX_BLOCK_LEN);
13286810ad6fSSam Leffler 
13299ebbebe4SConrad Meyer 	swcr_id = crypto_get_driverid(dev, sizeof(struct swcr_session),
13306810ad6fSSam Leffler 			CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC);
13316810ad6fSSam Leffler 	if (swcr_id < 0) {
13326810ad6fSSam Leffler 		device_printf(dev, "cannot initialize!");
13336810ad6fSSam Leffler 		return ENOMEM;
13346810ad6fSSam Leffler 	}
1335091d81d1SSam Leffler #define	REGISTER(alg) \
13366810ad6fSSam Leffler 	crypto_register(swcr_id, alg, 0,0)
13376810ad6fSSam Leffler 	REGISTER(CRYPTO_DES_CBC);
1338091d81d1SSam Leffler 	REGISTER(CRYPTO_3DES_CBC);
1339091d81d1SSam Leffler 	REGISTER(CRYPTO_BLF_CBC);
1340091d81d1SSam Leffler 	REGISTER(CRYPTO_CAST_CBC);
1341091d81d1SSam Leffler 	REGISTER(CRYPTO_SKIPJACK_CBC);
1342091d81d1SSam Leffler 	REGISTER(CRYPTO_NULL_CBC);
1343091d81d1SSam Leffler 	REGISTER(CRYPTO_MD5_HMAC);
1344091d81d1SSam Leffler 	REGISTER(CRYPTO_SHA1_HMAC);
1345c97f39ceSConrad Meyer 	REGISTER(CRYPTO_SHA2_224_HMAC);
1346f6c4bc3bSPawel Jakub Dawidek 	REGISTER(CRYPTO_SHA2_256_HMAC);
1347f6c4bc3bSPawel Jakub Dawidek 	REGISTER(CRYPTO_SHA2_384_HMAC);
1348f6c4bc3bSPawel Jakub Dawidek 	REGISTER(CRYPTO_SHA2_512_HMAC);
1349091d81d1SSam Leffler 	REGISTER(CRYPTO_RIPEMD160_HMAC);
1350091d81d1SSam Leffler 	REGISTER(CRYPTO_NULL_HMAC);
1351091d81d1SSam Leffler 	REGISTER(CRYPTO_MD5_KPDK);
1352091d81d1SSam Leffler 	REGISTER(CRYPTO_SHA1_KPDK);
1353091d81d1SSam Leffler 	REGISTER(CRYPTO_MD5);
1354091d81d1SSam Leffler 	REGISTER(CRYPTO_SHA1);
1355c4729f6eSConrad Meyer 	REGISTER(CRYPTO_SHA2_224);
1356c4729f6eSConrad Meyer 	REGISTER(CRYPTO_SHA2_256);
1357c4729f6eSConrad Meyer 	REGISTER(CRYPTO_SHA2_384);
1358c4729f6eSConrad Meyer 	REGISTER(CRYPTO_SHA2_512);
1359091d81d1SSam Leffler 	REGISTER(CRYPTO_RIJNDAEL128_CBC);
1360d295bdeeSPawel Jakub Dawidek 	REGISTER(CRYPTO_AES_XTS);
136108fca7a5SJohn-Mark Gurney 	REGISTER(CRYPTO_AES_ICM);
136208fca7a5SJohn-Mark Gurney 	REGISTER(CRYPTO_AES_NIST_GCM_16);
136308fca7a5SJohn-Mark Gurney 	REGISTER(CRYPTO_AES_NIST_GMAC);
136408fca7a5SJohn-Mark Gurney 	REGISTER(CRYPTO_AES_128_NIST_GMAC);
136508fca7a5SJohn-Mark Gurney 	REGISTER(CRYPTO_AES_192_NIST_GMAC);
136608fca7a5SJohn-Mark Gurney 	REGISTER(CRYPTO_AES_256_NIST_GMAC);
1367559d3390SGeorge V. Neville-Neil  	REGISTER(CRYPTO_CAMELLIA_CBC);
1368091d81d1SSam Leffler 	REGISTER(CRYPTO_DEFLATE_COMP);
13690e33efe4SConrad Meyer 	REGISTER(CRYPTO_BLAKE2B);
13700e33efe4SConrad Meyer 	REGISTER(CRYPTO_BLAKE2S);
137161590291SConrad Meyer 	REGISTER(CRYPTO_CHACHA20);
1372*507281e5SSean Eric Fagan 	REGISTER(CRYPTO_AES_CCM_16);
1373*507281e5SSean Eric Fagan 	REGISTER(CRYPTO_AES_CCM_CBC_MAC);
137425b7033bSConrad Meyer 	REGISTER(CRYPTO_POLY1305);
1375091d81d1SSam Leffler #undef REGISTER
13766810ad6fSSam Leffler 
13776810ad6fSSam Leffler 	return 0;
1378091d81d1SSam Leffler }
13794b465da2SPawel Jakub Dawidek 
13803f147ab2SWarner Losh static int
13816810ad6fSSam Leffler swcr_detach(device_t dev)
13824b465da2SPawel Jakub Dawidek {
13836810ad6fSSam Leffler 	crypto_unregister_all(swcr_id);
13843f147ab2SWarner Losh 	return 0;
13854b465da2SPawel Jakub Dawidek }
13866810ad6fSSam Leffler 
13876810ad6fSSam Leffler static device_method_t swcr_methods[] = {
13886810ad6fSSam Leffler 	DEVMETHOD(device_identify,	swcr_identify),
13896810ad6fSSam Leffler 	DEVMETHOD(device_probe,		swcr_probe),
13906810ad6fSSam Leffler 	DEVMETHOD(device_attach,	swcr_attach),
13916810ad6fSSam Leffler 	DEVMETHOD(device_detach,	swcr_detach),
13926810ad6fSSam Leffler 
13936810ad6fSSam Leffler 	DEVMETHOD(cryptodev_newsession,	swcr_newsession),
13946810ad6fSSam Leffler 	DEVMETHOD(cryptodev_freesession,swcr_freesession),
13956810ad6fSSam Leffler 	DEVMETHOD(cryptodev_process,	swcr_process),
13966810ad6fSSam Leffler 
13976810ad6fSSam Leffler 	{0, 0},
13986810ad6fSSam Leffler };
13996810ad6fSSam Leffler 
14006810ad6fSSam Leffler static driver_t swcr_driver = {
14016810ad6fSSam Leffler 	"cryptosoft",
14026810ad6fSSam Leffler 	swcr_methods,
14036810ad6fSSam Leffler 	0,		/* NB: no softc */
14046810ad6fSSam Leffler };
14056810ad6fSSam Leffler static devclass_t swcr_devclass;
14066810ad6fSSam Leffler 
14076810ad6fSSam Leffler /*
14086810ad6fSSam Leffler  * NB: We explicitly reference the crypto module so we
14096810ad6fSSam Leffler  * get the necessary ordering when built as a loadable
14106810ad6fSSam Leffler  * module.  This is required because we bundle the crypto
14116810ad6fSSam Leffler  * module code together with the cryptosoft driver (otherwise
14126810ad6fSSam Leffler  * normal module dependencies would handle things).
14136810ad6fSSam Leffler  */
14146810ad6fSSam Leffler extern int crypto_modevent(struct module *, int, void *);
14156810ad6fSSam Leffler /* XXX where to attach */
14166810ad6fSSam Leffler DRIVER_MODULE(cryptosoft, nexus, swcr_driver, swcr_devclass, crypto_modevent,0);
14176810ad6fSSam Leffler MODULE_VERSION(cryptosoft, 1);
14186810ad6fSSam Leffler MODULE_DEPEND(cryptosoft, crypto, 1, 1, 1);
1419