xref: /freebsd/sys/opencrypto/cryptosoft.c (revision e0b155fe4a1704948a463b128d3683aa00e47e82)
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/sha1.h>
51091d81d1SSam Leffler #include <opencrypto/rmd160.h>
52091d81d1SSam Leffler 
53091d81d1SSam Leffler #include <opencrypto/cryptodev.h>
54091d81d1SSam Leffler #include <opencrypto/xform.h>
55091d81d1SSam Leffler 
566810ad6fSSam Leffler #include <sys/kobj.h>
576810ad6fSSam Leffler #include <sys/bus.h>
586810ad6fSSam Leffler #include "cryptodev_if.h"
59091d81d1SSam Leffler 
60c0341432SJohn Baldwin struct swcr_auth {
61c0341432SJohn Baldwin 	void		*sw_ictx;
62c0341432SJohn Baldwin 	void		*sw_octx;
63c0341432SJohn Baldwin 	struct auth_hash *sw_axf;
64c0341432SJohn Baldwin 	uint16_t	sw_mlen;
65c0341432SJohn Baldwin };
66c0341432SJohn Baldwin 
67c0341432SJohn Baldwin struct swcr_encdec {
683e947048SJohn Baldwin 	void		*sw_kschedule;
69c0341432SJohn Baldwin 	struct enc_xform *sw_exf;
70c0341432SJohn Baldwin };
71c0341432SJohn Baldwin 
72c0341432SJohn Baldwin struct swcr_compdec {
73c0341432SJohn Baldwin 	struct comp_algo *sw_cxf;
74c0341432SJohn Baldwin };
75c0341432SJohn Baldwin 
76c0341432SJohn Baldwin struct swcr_session {
77c0341432SJohn Baldwin 	struct mtx	swcr_lock;
78c0341432SJohn Baldwin 	int	(*swcr_process)(struct swcr_session *, struct cryptop *);
79c0341432SJohn Baldwin 
80c0341432SJohn Baldwin 	struct swcr_auth swcr_auth;
81c0341432SJohn Baldwin 	struct swcr_encdec swcr_encdec;
82c0341432SJohn Baldwin 	struct swcr_compdec swcr_compdec;
83c0341432SJohn Baldwin };
84507281e5SSean Eric Fagan 
856810ad6fSSam Leffler static	int32_t swcr_id;
866810ad6fSSam Leffler 
871b0909d5SConrad Meyer static	void swcr_freesession(device_t dev, crypto_session_t cses);
88091d81d1SSam Leffler 
89c0341432SJohn Baldwin /* Used for CRYPTO_NULL_CBC. */
90c0341432SJohn Baldwin static int
91c0341432SJohn Baldwin swcr_null(struct swcr_session *ses, struct cryptop *crp)
92c0341432SJohn Baldwin {
93c0341432SJohn Baldwin 
94c0341432SJohn Baldwin 	return (0);
95c0341432SJohn Baldwin }
96c0341432SJohn Baldwin 
97091d81d1SSam Leffler /*
98091d81d1SSam Leffler  * Apply a symmetric encryption/decryption algorithm.
99091d81d1SSam Leffler  */
100091d81d1SSam Leffler static int
101c0341432SJohn Baldwin swcr_encdec(struct swcr_session *ses, struct cryptop *crp)
102091d81d1SSam Leffler {
1035d7ae54aSConrad Meyer 	unsigned char iv[EALG_MAX_BLOCK_LEN], blk[EALG_MAX_BLOCK_LEN];
10408fca7a5SJohn-Mark Gurney 	unsigned char *ivp, *nivp, iv2[EALG_MAX_BLOCK_LEN];
105c0341432SJohn Baldwin 	const struct crypto_session_params *csp;
106c0341432SJohn Baldwin 	struct swcr_encdec *sw;
107091d81d1SSam Leffler 	struct enc_xform *exf;
1089c0e3d3aSJohn Baldwin 	int i, blks, inlen, ivlen, outlen, resid;
1099c0e3d3aSJohn Baldwin 	struct crypto_buffer_cursor cc_in, cc_out;
11026d292d3SJohn Baldwin 	const unsigned char *inblk;
11126d292d3SJohn Baldwin 	unsigned char *outblk;
11208fca7a5SJohn-Mark Gurney 	int error;
113c0341432SJohn Baldwin 	bool encrypting;
11408fca7a5SJohn-Mark Gurney 
11508fca7a5SJohn-Mark Gurney 	error = 0;
116091d81d1SSam Leffler 
117c0341432SJohn Baldwin 	sw = &ses->swcr_encdec;
118091d81d1SSam Leffler 	exf = sw->sw_exf;
11908fca7a5SJohn-Mark Gurney 	ivlen = exf->ivsize;
120091d81d1SSam Leffler 
121723d8764SJohn Baldwin 	if (exf->native_blocksize == 0) {
122091d81d1SSam Leffler 		/* Check for non-padded data */
123723d8764SJohn Baldwin 		if ((crp->crp_payload_length % exf->blocksize) != 0)
124723d8764SJohn Baldwin 			return (EINVAL);
125723d8764SJohn Baldwin 
126723d8764SJohn Baldwin 		blks = exf->blocksize;
127723d8764SJohn Baldwin 	} else
128723d8764SJohn Baldwin 		blks = exf->native_blocksize;
129091d81d1SSam Leffler 
130c0341432SJohn Baldwin 	if (exf == &enc_xform_aes_icm &&
131c0341432SJohn Baldwin 	    (crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0)
13208fca7a5SJohn-Mark Gurney 		return (EINVAL);
13308fca7a5SJohn-Mark Gurney 
134c0341432SJohn Baldwin 	if (crp->crp_cipher_key != NULL) {
135c0341432SJohn Baldwin 		csp = crypto_get_params(crp->crp_session);
1363e947048SJohn Baldwin 		error = exf->setkey(sw->sw_kschedule,
137c0341432SJohn Baldwin 		    crp->crp_cipher_key, csp->csp_cipher_klen);
138c740ae4bSPoul-Henning Kamp 		if (error)
139c740ae4bSPoul-Henning Kamp 			return (error);
140c740ae4bSPoul-Henning Kamp 	}
141d295bdeeSPawel Jakub Dawidek 
14220c128daSJohn Baldwin 	crypto_read_iv(crp, iv);
14320c128daSJohn Baldwin 
14408fca7a5SJohn-Mark Gurney 	if (exf->reinit) {
145d295bdeeSPawel Jakub Dawidek 		/*
146d295bdeeSPawel Jakub Dawidek 		 * xforms that provide a reinit method perform all IV
147d295bdeeSPawel Jakub Dawidek 		 * handling themselves.
148d295bdeeSPawel Jakub Dawidek 		 */
149d295bdeeSPawel Jakub Dawidek 		exf->reinit(sw->sw_kschedule, iv);
150091d81d1SSam Leffler 	}
151091d81d1SSam Leffler 
1529c0e3d3aSJohn Baldwin 	ivp = iv;
153091d81d1SSam Leffler 
1549c0e3d3aSJohn Baldwin 	crypto_cursor_init(&cc_in, &crp->crp_buf);
1559c0e3d3aSJohn Baldwin 	crypto_cursor_advance(&cc_in, crp->crp_payload_start);
1569c0e3d3aSJohn Baldwin 	inlen = crypto_cursor_seglen(&cc_in);
1579c0e3d3aSJohn Baldwin 	inblk = crypto_cursor_segbase(&cc_in);
1589c0e3d3aSJohn Baldwin 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
1599c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_out, &crp->crp_obuf);
1609c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_out, crp->crp_payload_output_start);
1619c0e3d3aSJohn Baldwin 	} else
1629c0e3d3aSJohn Baldwin 		cc_out = cc_in;
1639c0e3d3aSJohn Baldwin 	outlen = crypto_cursor_seglen(&cc_out);
1649c0e3d3aSJohn Baldwin 	outblk = crypto_cursor_segbase(&cc_out);
1659c0e3d3aSJohn Baldwin 
1669c0e3d3aSJohn Baldwin 	resid = crp->crp_payload_length;
167c0341432SJohn Baldwin 	encrypting = CRYPTO_OP_IS_ENCRYPT(crp->crp_op);
168091d81d1SSam Leffler 
169091d81d1SSam Leffler 	/*
1709c0e3d3aSJohn Baldwin 	 * Loop through encrypting blocks.  'inlen' is the remaining
1719c0e3d3aSJohn Baldwin 	 * length of the current segment in the input buffer.
1729c0e3d3aSJohn Baldwin 	 * 'outlen' is the remaining length of current segment in the
1739c0e3d3aSJohn Baldwin 	 * output buffer.
174091d81d1SSam Leffler 	 */
1759c0e3d3aSJohn Baldwin 	while (resid >= blks) {
1769c0e3d3aSJohn Baldwin 		/*
1779c0e3d3aSJohn Baldwin 		 * If the current block is not contained within the
1789c0e3d3aSJohn Baldwin 		 * current input/output segment, use 'blk' as a local
1799c0e3d3aSJohn Baldwin 		 * buffer.
1809c0e3d3aSJohn Baldwin 		 */
1819c0e3d3aSJohn Baldwin 		if (inlen < blks) {
1829c0e3d3aSJohn Baldwin 			crypto_cursor_copydata(&cc_in, blks, blk);
1839c0e3d3aSJohn Baldwin 			inblk = blk;
184d295bdeeSPawel Jakub Dawidek 		}
1859c0e3d3aSJohn Baldwin 		if (outlen < blks)
1869c0e3d3aSJohn Baldwin 			outblk = blk;
1879c0e3d3aSJohn Baldwin 
1889c0e3d3aSJohn Baldwin 		/*
1899c0e3d3aSJohn Baldwin 		 * Ciphers without a 'reinit' hook are assumed to be
1909c0e3d3aSJohn Baldwin 		 * used in CBC mode where the chaining is done here.
1919c0e3d3aSJohn Baldwin 		 */
1929c0e3d3aSJohn Baldwin 		if (exf->reinit != NULL) {
1939c0e3d3aSJohn Baldwin 			if (encrypting)
1949c0e3d3aSJohn Baldwin 				exf->encrypt(sw->sw_kschedule, inblk, outblk);
1959c0e3d3aSJohn Baldwin 			else
1969c0e3d3aSJohn Baldwin 				exf->decrypt(sw->sw_kschedule, inblk, outblk);
197c0341432SJohn Baldwin 		} else if (encrypting) {
198091d81d1SSam Leffler 			/* XOR with previous block */
1999c0e3d3aSJohn Baldwin 			for (i = 0; i < blks; i++)
2009c0e3d3aSJohn Baldwin 				outblk[i] = inblk[i] ^ ivp[i];
201091d81d1SSam Leffler 
2029c0e3d3aSJohn Baldwin 			exf->encrypt(sw->sw_kschedule, outblk, outblk);
203091d81d1SSam Leffler 
204091d81d1SSam Leffler 			/*
205091d81d1SSam Leffler 			 * Keep encrypted block for XOR'ing
206091d81d1SSam Leffler 			 * with next block
207091d81d1SSam Leffler 			 */
2089c0e3d3aSJohn Baldwin 			memcpy(iv, outblk, 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;
2169c0e3d3aSJohn Baldwin 			memcpy(nivp, inblk, blks);
217091d81d1SSam Leffler 
2189c0e3d3aSJohn Baldwin 			exf->decrypt(sw->sw_kschedule, inblk, outblk);
219091d81d1SSam Leffler 
220091d81d1SSam Leffler 			/* XOR with previous block */
2219c0e3d3aSJohn Baldwin 			for (i = 0; i < blks; i++)
2229c0e3d3aSJohn Baldwin 				outblk[i] ^= ivp[i];
223091d81d1SSam Leffler 
22408fca7a5SJohn-Mark Gurney 			ivp = nivp;
225091d81d1SSam Leffler 		}
226091d81d1SSam Leffler 
2279c0e3d3aSJohn Baldwin 		if (inlen < blks) {
2289c0e3d3aSJohn Baldwin 			inlen = crypto_cursor_seglen(&cc_in);
2299c0e3d3aSJohn Baldwin 			inblk = crypto_cursor_segbase(&cc_in);
2309c0e3d3aSJohn Baldwin 		} else {
2319c0e3d3aSJohn Baldwin 			crypto_cursor_advance(&cc_in, blks);
2329c0e3d3aSJohn Baldwin 			inlen -= blks;
2339c0e3d3aSJohn Baldwin 			inblk += blks;
23408fca7a5SJohn-Mark Gurney 		}
235091d81d1SSam Leffler 
2369c0e3d3aSJohn Baldwin 		if (outlen < blks) {
2379c0e3d3aSJohn Baldwin 			crypto_cursor_copyback(&cc_out, blks, blk);
2389c0e3d3aSJohn Baldwin 			outlen = crypto_cursor_seglen(&cc_out);
2399c0e3d3aSJohn Baldwin 			outblk = crypto_cursor_segbase(&cc_out);
2409c0e3d3aSJohn Baldwin 		} else {
2419c0e3d3aSJohn Baldwin 			crypto_cursor_advance(&cc_out, blks);
2429c0e3d3aSJohn Baldwin 			outlen -= blks;
2439c0e3d3aSJohn Baldwin 			outblk += blks;
244091d81d1SSam Leffler 		}
245091d81d1SSam Leffler 
2469c0e3d3aSJohn Baldwin 		resid -= blks;
247f34a967bSPawel Jakub Dawidek 	}
248f34a967bSPawel Jakub Dawidek 
249723d8764SJohn Baldwin 	/* Handle trailing partial block for stream ciphers. */
2509c0e3d3aSJohn Baldwin 	if (resid > 0) {
251723d8764SJohn Baldwin 		KASSERT(exf->native_blocksize != 0,
252723d8764SJohn Baldwin 		    ("%s: partial block of %d bytes for cipher %s",
253723d8764SJohn Baldwin 		    __func__, i, exf->name));
254723d8764SJohn Baldwin 		KASSERT(exf->reinit != NULL,
255723d8764SJohn Baldwin 		    ("%s: partial block cipher %s without reinit hook",
256723d8764SJohn Baldwin 		    __func__, exf->name));
2579c0e3d3aSJohn Baldwin 		KASSERT(resid < blks, ("%s: partial block too big", __func__));
258723d8764SJohn Baldwin 
2599c0e3d3aSJohn Baldwin 		inlen = crypto_cursor_seglen(&cc_in);
2609c0e3d3aSJohn Baldwin 		outlen = crypto_cursor_seglen(&cc_out);
2619c0e3d3aSJohn Baldwin 		if (inlen < resid) {
2629c0e3d3aSJohn Baldwin 			crypto_cursor_copydata(&cc_in, resid, blk);
2639c0e3d3aSJohn Baldwin 			inblk = blk;
2649c0e3d3aSJohn Baldwin 		} else
2659c0e3d3aSJohn Baldwin 			inblk = crypto_cursor_segbase(&cc_in);
2669c0e3d3aSJohn Baldwin 		if (outlen < resid)
2679c0e3d3aSJohn Baldwin 			outblk = blk;
2689c0e3d3aSJohn Baldwin 		else
2699c0e3d3aSJohn Baldwin 			outblk = crypto_cursor_segbase(&cc_out);
2709c0e3d3aSJohn Baldwin 		if (encrypting)
2719c0e3d3aSJohn Baldwin 			exf->encrypt_last(sw->sw_kschedule, inblk, outblk,
2729c0e3d3aSJohn Baldwin 			    resid);
2739c0e3d3aSJohn Baldwin 		else
2749c0e3d3aSJohn Baldwin 			exf->decrypt_last(sw->sw_kschedule, inblk, outblk,
2759c0e3d3aSJohn Baldwin 			    resid);
2769c0e3d3aSJohn Baldwin 		if (outlen < resid)
2779c0e3d3aSJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
278723d8764SJohn Baldwin 	}
279723d8764SJohn Baldwin 
28020c128daSJohn Baldwin 	explicit_bzero(blk, sizeof(blk));
28120c128daSJohn Baldwin 	explicit_bzero(iv, sizeof(iv));
28220c128daSJohn Baldwin 	explicit_bzero(iv2, sizeof(iv2));
2839c0e3d3aSJohn Baldwin 	return (0);
284091d81d1SSam Leffler }
285091d81d1SSam Leffler 
286c0341432SJohn Baldwin static void
287c0341432SJohn Baldwin swcr_authprepare(struct auth_hash *axf, struct swcr_auth *sw,
288c0341432SJohn Baldwin     const uint8_t *key, int klen)
289f6c4bc3bSPawel Jakub Dawidek {
290f6c4bc3bSPawel Jakub Dawidek 
291f6c4bc3bSPawel Jakub Dawidek 	switch (axf->type) {
292f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA1_HMAC:
293c97f39ceSConrad Meyer 	case CRYPTO_SHA2_224_HMAC:
294f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_256_HMAC:
295f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_384_HMAC:
296f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_512_HMAC:
297f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_NULL_HMAC:
298f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_RIPEMD160_HMAC:
299c0341432SJohn Baldwin 		hmac_init_ipad(axf, key, klen, sw->sw_ictx);
300c0341432SJohn Baldwin 		hmac_init_opad(axf, key, klen, sw->sw_octx);
301f6c4bc3bSPawel Jakub Dawidek 		break;
30225b7033bSConrad Meyer 	case CRYPTO_POLY1305:
3030e33efe4SConrad Meyer 	case CRYPTO_BLAKE2B:
3040e33efe4SConrad Meyer 	case CRYPTO_BLAKE2S:
3050e33efe4SConrad Meyer 		axf->Setkey(sw->sw_ictx, key, klen);
3060e33efe4SConrad Meyer 		axf->Init(sw->sw_ictx);
3070e33efe4SConrad Meyer 		break;
308f6c4bc3bSPawel Jakub Dawidek 	default:
309c0341432SJohn Baldwin 		panic("%s: algorithm %d doesn't use keys", __func__, axf->type);
310f6c4bc3bSPawel Jakub Dawidek 	}
311f6c4bc3bSPawel Jakub Dawidek }
312f6c4bc3bSPawel Jakub Dawidek 
313091d81d1SSam Leffler /*
314c0341432SJohn Baldwin  * Compute or verify hash.
315091d81d1SSam Leffler  */
316091d81d1SSam Leffler static int
317c0341432SJohn Baldwin swcr_authcompute(struct swcr_session *ses, struct cryptop *crp)
318091d81d1SSam Leffler {
319c0341432SJohn Baldwin 	u_char aalg[HASH_MAX_LEN];
320c0341432SJohn Baldwin 	const struct crypto_session_params *csp;
321c0341432SJohn Baldwin 	struct swcr_auth *sw;
322091d81d1SSam Leffler 	struct auth_hash *axf;
323091d81d1SSam Leffler 	union authctx ctx;
324091d81d1SSam Leffler 	int err;
325091d81d1SSam Leffler 
326c0341432SJohn Baldwin 	sw = &ses->swcr_auth;
327091d81d1SSam Leffler 
328091d81d1SSam Leffler 	axf = sw->sw_axf;
329091d81d1SSam Leffler 
330c0341432SJohn Baldwin 	if (crp->crp_auth_key != NULL) {
331c0341432SJohn Baldwin 		csp = crypto_get_params(crp->crp_session);
332c0341432SJohn Baldwin 		swcr_authprepare(axf, sw, crp->crp_auth_key,
333c0341432SJohn Baldwin 		    csp->csp_auth_klen);
33425b7033bSConrad Meyer 	}
335f6c4bc3bSPawel Jakub Dawidek 
336091d81d1SSam Leffler 	bcopy(sw->sw_ictx, &ctx, axf->ctxsize);
337091d81d1SSam Leffler 
3389b774dc0SJohn Baldwin 	if (crp->crp_aad != NULL)
3399b774dc0SJohn Baldwin 		err = axf->Update(&ctx, crp->crp_aad, crp->crp_aad_length);
3409b774dc0SJohn Baldwin 	else
341c0341432SJohn Baldwin 		err = crypto_apply(crp, crp->crp_aad_start, crp->crp_aad_length,
3429b6b2f86SJohn Baldwin 		    axf->Update, &ctx);
343091d81d1SSam Leffler 	if (err)
344*e0b155feSJohn Baldwin 		goto out;
345091d81d1SSam Leffler 
3469c0e3d3aSJohn Baldwin 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp) &&
3479c0e3d3aSJohn Baldwin 	    CRYPTO_OP_IS_ENCRYPT(crp->crp_op))
3489c0e3d3aSJohn Baldwin 		err = crypto_apply_buf(&crp->crp_obuf,
3499c0e3d3aSJohn Baldwin 		    crp->crp_payload_output_start, crp->crp_payload_length,
3509b6b2f86SJohn Baldwin 		    axf->Update, &ctx);
3519c0e3d3aSJohn Baldwin 	else
3529c0e3d3aSJohn Baldwin 		err = crypto_apply(crp, crp->crp_payload_start,
3539b6b2f86SJohn Baldwin 		    crp->crp_payload_length, axf->Update, &ctx);
354c0341432SJohn Baldwin 	if (err)
355*e0b155feSJohn Baldwin 		goto out;
356091d81d1SSam Leffler 
357091d81d1SSam Leffler 	axf->Final(aalg, &ctx);
358*e0b155feSJohn Baldwin 	if (sw->sw_octx != NULL) {
359091d81d1SSam Leffler 		bcopy(sw->sw_octx, &ctx, axf->ctxsize);
360091d81d1SSam Leffler 		axf->Update(&ctx, aalg, axf->hashsize);
361091d81d1SSam Leffler 		axf->Final(aalg, &ctx);
362091d81d1SSam Leffler 	}
363091d81d1SSam Leffler 
364c0341432SJohn Baldwin 	if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
36520c128daSJohn Baldwin 		u_char uaalg[HASH_MAX_LEN];
36620c128daSJohn Baldwin 
367c0341432SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, sw->sw_mlen, uaalg);
368c0341432SJohn Baldwin 		if (timingsafe_bcmp(aalg, uaalg, sw->sw_mlen) != 0)
36920c128daSJohn Baldwin 			err = EBADMSG;
37020c128daSJohn Baldwin 		explicit_bzero(uaalg, sizeof(uaalg));
371c0341432SJohn Baldwin 	} else {
372091d81d1SSam Leffler 		/* Inject the authentication data */
373c0341432SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, sw->sw_mlen, aalg);
374c0341432SJohn Baldwin 	}
37520c128daSJohn Baldwin 	explicit_bzero(aalg, sizeof(aalg));
376*e0b155feSJohn Baldwin out:
377*e0b155feSJohn Baldwin 	explicit_bzero(&ctx, sizeof(ctx));
37820c128daSJohn Baldwin 	return (err);
379091d81d1SSam Leffler }
380091d81d1SSam Leffler 
38108fca7a5SJohn-Mark Gurney CTASSERT(INT_MAX <= (1ll<<39) - 256);	/* GCM: plain text < 2^39-256 */
38208fca7a5SJohn-Mark Gurney CTASSERT(INT_MAX <= (uint64_t)-1);	/* GCM: associated data <= 2^64-1 */
38308fca7a5SJohn-Mark Gurney 
38408fca7a5SJohn-Mark Gurney static int
385c0341432SJohn Baldwin swcr_gmac(struct swcr_session *ses, struct cryptop *crp)
38608fca7a5SJohn-Mark Gurney {
38726d292d3SJohn Baldwin 	uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))];
38808fca7a5SJohn-Mark Gurney 	u_char *blk = (u_char *)blkbuf;
38926d292d3SJohn Baldwin 	u_char tag[GMAC_DIGEST_LEN];
39026d292d3SJohn Baldwin 	u_char iv[AES_BLOCK_LEN];
3919c0e3d3aSJohn Baldwin 	struct crypto_buffer_cursor cc;
39226d292d3SJohn Baldwin 	const u_char *inblk;
39308fca7a5SJohn-Mark Gurney 	union authctx ctx;
394c0341432SJohn Baldwin 	struct swcr_auth *swa;
395c0341432SJohn Baldwin 	struct auth_hash *axf;
39608fca7a5SJohn-Mark Gurney 	uint32_t *blkp;
39720c128daSJohn Baldwin 	int blksz, error, ivlen, len, resid;
39808fca7a5SJohn-Mark Gurney 
399c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
40008fca7a5SJohn-Mark Gurney 	axf = swa->sw_axf;
401c0341432SJohn Baldwin 
40208fca7a5SJohn-Mark Gurney 	bcopy(swa->sw_ictx, &ctx, axf->ctxsize);
40326d292d3SJohn Baldwin 	blksz = GMAC_BLOCK_LEN;
40426d292d3SJohn Baldwin 	KASSERT(axf->blocksize == blksz, ("%s: axf block size mismatch",
40526d292d3SJohn Baldwin 	    __func__));
40608fca7a5SJohn-Mark Gurney 
40708fca7a5SJohn-Mark Gurney 	/* Initialize the IV */
408c0341432SJohn Baldwin 	ivlen = AES_GCM_IV_LEN;
40929fe41ddSJohn Baldwin 	crypto_read_iv(crp, iv);
41008fca7a5SJohn-Mark Gurney 
41108fca7a5SJohn-Mark Gurney 	axf->Reinit(&ctx, iv, ivlen);
4129c0e3d3aSJohn Baldwin 	crypto_cursor_init(&cc, &crp->crp_buf);
4139c0e3d3aSJohn Baldwin 	crypto_cursor_advance(&cc, crp->crp_payload_start);
41426d292d3SJohn Baldwin 	for (resid = crp->crp_payload_length; resid >= blksz; resid -= len) {
41526d292d3SJohn Baldwin 		len = crypto_cursor_seglen(&cc);
41626d292d3SJohn Baldwin 		if (len >= blksz) {
41726d292d3SJohn Baldwin 			inblk = crypto_cursor_segbase(&cc);
41826d292d3SJohn Baldwin 			len = rounddown(MIN(len, resid), blksz);
41926d292d3SJohn Baldwin 			crypto_cursor_advance(&cc, len);
42026d292d3SJohn Baldwin 		} else {
42126d292d3SJohn Baldwin 			len = blksz;
4229c0e3d3aSJohn Baldwin 			crypto_cursor_copydata(&cc, len, blk);
42326d292d3SJohn Baldwin 			inblk = blk;
42426d292d3SJohn Baldwin 		}
42526d292d3SJohn Baldwin 		axf->Update(&ctx, inblk, len);
42626d292d3SJohn Baldwin 	}
42726d292d3SJohn Baldwin 	if (resid > 0) {
42826d292d3SJohn Baldwin 		memset(blk, 0, blksz);
42926d292d3SJohn Baldwin 		crypto_cursor_copydata(&cc, resid, blk);
43008fca7a5SJohn-Mark Gurney 		axf->Update(&ctx, blk, blksz);
43108fca7a5SJohn-Mark Gurney 	}
43208fca7a5SJohn-Mark Gurney 
43308fca7a5SJohn-Mark Gurney 	/* length block */
43426d292d3SJohn Baldwin 	memset(blk, 0, blksz);
43508fca7a5SJohn-Mark Gurney 	blkp = (uint32_t *)blk + 1;
436c0341432SJohn Baldwin 	*blkp = htobe32(crp->crp_payload_length * 8);
43708fca7a5SJohn-Mark Gurney 	axf->Update(&ctx, blk, blksz);
438c0341432SJohn Baldwin 
439c0341432SJohn Baldwin 	/* Finalize MAC */
44026d292d3SJohn Baldwin 	axf->Final(tag, &ctx);
441c0341432SJohn Baldwin 
44220c128daSJohn Baldwin 	error = 0;
443c0341432SJohn Baldwin 	if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
44426d292d3SJohn Baldwin 		u_char tag2[GMAC_DIGEST_LEN];
44520c128daSJohn Baldwin 
446c0341432SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen,
44726d292d3SJohn Baldwin 		    tag2);
44826d292d3SJohn Baldwin 		if (timingsafe_bcmp(tag, tag2, swa->sw_mlen) != 0)
44920c128daSJohn Baldwin 			error = EBADMSG;
45026d292d3SJohn Baldwin 		explicit_bzero(tag2, sizeof(tag2));
451c0341432SJohn Baldwin 	} else {
452c0341432SJohn Baldwin 		/* Inject the authentication data */
45326d292d3SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag);
454c0341432SJohn Baldwin 	}
45520c128daSJohn Baldwin 	explicit_bzero(blkbuf, sizeof(blkbuf));
45626d292d3SJohn Baldwin 	explicit_bzero(tag, sizeof(tag));
45720c128daSJohn Baldwin 	explicit_bzero(iv, sizeof(iv));
45820c128daSJohn Baldwin 	return (error);
459c0341432SJohn Baldwin }
460c0341432SJohn Baldwin 
461c0341432SJohn Baldwin static int
462c0341432SJohn Baldwin swcr_gcm(struct swcr_session *ses, struct cryptop *crp)
463c0341432SJohn Baldwin {
46426d292d3SJohn Baldwin 	uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))];
465c0341432SJohn Baldwin 	u_char *blk = (u_char *)blkbuf;
46626d292d3SJohn Baldwin 	u_char tag[GMAC_DIGEST_LEN];
46726d292d3SJohn Baldwin 	u_char iv[AES_BLOCK_LEN];
4689c0e3d3aSJohn Baldwin 	struct crypto_buffer_cursor cc_in, cc_out;
46926d292d3SJohn Baldwin 	const u_char *inblk;
47026d292d3SJohn Baldwin 	u_char *outblk;
471c0341432SJohn Baldwin 	union authctx ctx;
472c0341432SJohn Baldwin 	struct swcr_auth *swa;
473c0341432SJohn Baldwin 	struct swcr_encdec *swe;
474c0341432SJohn Baldwin 	struct auth_hash *axf;
475c0341432SJohn Baldwin 	struct enc_xform *exf;
476c0341432SJohn Baldwin 	uint32_t *blkp;
47720c128daSJohn Baldwin 	int blksz, error, ivlen, len, r, resid;
478c0341432SJohn Baldwin 
479c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
480c0341432SJohn Baldwin 	axf = swa->sw_axf;
481c0341432SJohn Baldwin 
482c0341432SJohn Baldwin 	bcopy(swa->sw_ictx, &ctx, axf->ctxsize);
48326d292d3SJohn Baldwin 	blksz = GMAC_BLOCK_LEN;
48426d292d3SJohn Baldwin 	KASSERT(axf->blocksize == blksz, ("%s: axf block size mismatch",
48526d292d3SJohn Baldwin 	    __func__));
486c0341432SJohn Baldwin 
487c0341432SJohn Baldwin 	swe = &ses->swcr_encdec;
488c0341432SJohn Baldwin 	exf = swe->sw_exf;
489723d8764SJohn Baldwin 	KASSERT(axf->blocksize == exf->native_blocksize,
490723d8764SJohn Baldwin 	    ("%s: blocksize mismatch", __func__));
491c0341432SJohn Baldwin 
492c0341432SJohn Baldwin 	if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0)
493c0341432SJohn Baldwin 		return (EINVAL);
494c0341432SJohn Baldwin 
495c0341432SJohn Baldwin 	/* Initialize the IV */
496c0341432SJohn Baldwin 	ivlen = AES_GCM_IV_LEN;
497c0341432SJohn Baldwin 	bcopy(crp->crp_iv, iv, ivlen);
498c0341432SJohn Baldwin 
499c0341432SJohn Baldwin 	/* Supply MAC with IV */
500c0341432SJohn Baldwin 	axf->Reinit(&ctx, iv, ivlen);
501c0341432SJohn Baldwin 
502c0341432SJohn Baldwin 	/* Supply MAC with AAD */
5039b774dc0SJohn Baldwin 	if (crp->crp_aad != NULL) {
5049b774dc0SJohn Baldwin 		len = rounddown(crp->crp_aad_length, blksz);
5059b774dc0SJohn Baldwin 		if (len != 0)
5069b774dc0SJohn Baldwin 			axf->Update(&ctx, crp->crp_aad, len);
5079b774dc0SJohn Baldwin 		if (crp->crp_aad_length != len) {
5089b774dc0SJohn Baldwin 			memset(blk, 0, blksz);
5099b774dc0SJohn Baldwin 			memcpy(blk, (char *)crp->crp_aad + len,
5109b774dc0SJohn Baldwin 			    crp->crp_aad_length - len);
5119b774dc0SJohn Baldwin 			axf->Update(&ctx, blk, blksz);
5129b774dc0SJohn Baldwin 		}
5139b774dc0SJohn Baldwin 	} else {
5149c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_in, &crp->crp_buf);
5159c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_in, crp->crp_aad_start);
5169b774dc0SJohn Baldwin 		for (resid = crp->crp_aad_length; resid >= blksz;
5179b774dc0SJohn Baldwin 		     resid -= len) {
51826d292d3SJohn Baldwin 			len = crypto_cursor_seglen(&cc_in);
51926d292d3SJohn Baldwin 			if (len >= blksz) {
52026d292d3SJohn Baldwin 				inblk = crypto_cursor_segbase(&cc_in);
52126d292d3SJohn Baldwin 				len = rounddown(MIN(len, resid), blksz);
52226d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_in, len);
52326d292d3SJohn Baldwin 			} else {
52426d292d3SJohn Baldwin 				len = blksz;
5259c0e3d3aSJohn Baldwin 				crypto_cursor_copydata(&cc_in, len, blk);
52626d292d3SJohn Baldwin 				inblk = blk;
52726d292d3SJohn Baldwin 			}
52826d292d3SJohn Baldwin 			axf->Update(&ctx, inblk, len);
52926d292d3SJohn Baldwin 		}
53026d292d3SJohn Baldwin 		if (resid > 0) {
53126d292d3SJohn Baldwin 			memset(blk, 0, blksz);
53226d292d3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, resid, blk);
533c0341432SJohn Baldwin 			axf->Update(&ctx, blk, blksz);
534c0341432SJohn Baldwin 		}
5359b774dc0SJohn Baldwin 	}
536c0341432SJohn Baldwin 
537c0341432SJohn Baldwin 	exf->reinit(swe->sw_kschedule, iv);
538c0341432SJohn Baldwin 
539c0341432SJohn Baldwin 	/* Do encryption with MAC */
5409c0e3d3aSJohn Baldwin 	crypto_cursor_init(&cc_in, &crp->crp_buf);
5419c0e3d3aSJohn Baldwin 	crypto_cursor_advance(&cc_in, crp->crp_payload_start);
5429c0e3d3aSJohn Baldwin 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
5439c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_out, &crp->crp_obuf);
5449c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_out, crp->crp_payload_output_start);
5459c0e3d3aSJohn Baldwin 	} else
5469c0e3d3aSJohn Baldwin 		cc_out = cc_in;
54726d292d3SJohn Baldwin 	for (resid = crp->crp_payload_length; resid >= blksz; resid -= blksz) {
54826d292d3SJohn Baldwin 		if (crypto_cursor_seglen(&cc_in) < blksz) {
54926d292d3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, blksz, blk);
55026d292d3SJohn Baldwin 			inblk = blk;
551c0341432SJohn Baldwin 		} else {
55226d292d3SJohn Baldwin 			inblk = crypto_cursor_segbase(&cc_in);
55326d292d3SJohn Baldwin 			crypto_cursor_advance(&cc_in, blksz);
554c0341432SJohn Baldwin 		}
55526d292d3SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
55626d292d3SJohn Baldwin 			if (crypto_cursor_seglen(&cc_out) < blksz)
55726d292d3SJohn Baldwin 				outblk = blk;
55826d292d3SJohn Baldwin 			else
55926d292d3SJohn Baldwin 				outblk = crypto_cursor_segbase(&cc_out);
56026d292d3SJohn Baldwin 			exf->encrypt(swe->sw_kschedule, inblk, outblk);
56126d292d3SJohn Baldwin 			axf->Update(&ctx, outblk, blksz);
56226d292d3SJohn Baldwin 			if (outblk == blk)
56326d292d3SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
56426d292d3SJohn Baldwin 			else
56526d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_out, blksz);
56626d292d3SJohn Baldwin 		} else {
56726d292d3SJohn Baldwin 			axf->Update(&ctx, inblk, blksz);
56826d292d3SJohn Baldwin 		}
56926d292d3SJohn Baldwin 	}
57026d292d3SJohn Baldwin 	if (resid > 0) {
57126d292d3SJohn Baldwin 		crypto_cursor_copydata(&cc_in, resid, blk);
57226d292d3SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
57326d292d3SJohn Baldwin 			exf->encrypt_last(swe->sw_kschedule, blk, blk, resid);
57426d292d3SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
57526d292d3SJohn Baldwin 		}
57626d292d3SJohn Baldwin 		axf->Update(&ctx, blk, resid);
577c0341432SJohn Baldwin 	}
578c0341432SJohn Baldwin 
579c0341432SJohn Baldwin 	/* length block */
58026d292d3SJohn Baldwin 	memset(blk, 0, blksz);
581c0341432SJohn Baldwin 	blkp = (uint32_t *)blk + 1;
582c0341432SJohn Baldwin 	*blkp = htobe32(crp->crp_aad_length * 8);
583c0341432SJohn Baldwin 	blkp = (uint32_t *)blk + 3;
584c0341432SJohn Baldwin 	*blkp = htobe32(crp->crp_payload_length * 8);
585c0341432SJohn Baldwin 	axf->Update(&ctx, blk, blksz);
586c0341432SJohn Baldwin 
587c0341432SJohn Baldwin 	/* Finalize MAC */
58826d292d3SJohn Baldwin 	axf->Final(tag, &ctx);
589c0341432SJohn Baldwin 
590c0341432SJohn Baldwin 	/* Validate tag */
59120c128daSJohn Baldwin 	error = 0;
592c0341432SJohn Baldwin 	if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
59326d292d3SJohn Baldwin 		u_char tag2[GMAC_DIGEST_LEN];
59420c128daSJohn Baldwin 
59526d292d3SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, tag2);
596c0341432SJohn Baldwin 
59726d292d3SJohn Baldwin 		r = timingsafe_bcmp(tag, tag2, swa->sw_mlen);
59826d292d3SJohn Baldwin 		explicit_bzero(tag2, sizeof(tag2));
59920c128daSJohn Baldwin 		if (r != 0) {
60020c128daSJohn Baldwin 			error = EBADMSG;
60120c128daSJohn Baldwin 			goto out;
60220c128daSJohn Baldwin 		}
603c0341432SJohn Baldwin 
604c0341432SJohn Baldwin 		/* tag matches, decrypt data */
6059c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_in, &crp->crp_buf);
6069c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_in, crp->crp_payload_start);
60726d292d3SJohn Baldwin 		for (resid = crp->crp_payload_length; resid > blksz;
60826d292d3SJohn Baldwin 		     resid -= blksz) {
60926d292d3SJohn Baldwin 			if (crypto_cursor_seglen(&cc_in) < blksz) {
61026d292d3SJohn Baldwin 				crypto_cursor_copydata(&cc_in, blksz, blk);
61126d292d3SJohn Baldwin 				inblk = blk;
61226d292d3SJohn Baldwin 			} else {
61326d292d3SJohn Baldwin 				inblk = crypto_cursor_segbase(&cc_in);
61426d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_in, blksz);
61526d292d3SJohn Baldwin 			}
61626d292d3SJohn Baldwin 			if (crypto_cursor_seglen(&cc_out) < blksz)
61726d292d3SJohn Baldwin 				outblk = blk;
61826d292d3SJohn Baldwin 			else
61926d292d3SJohn Baldwin 				outblk = crypto_cursor_segbase(&cc_out);
62026d292d3SJohn Baldwin 			exf->decrypt(swe->sw_kschedule, inblk, outblk);
62126d292d3SJohn Baldwin 			if (outblk == blk)
62226d292d3SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
62326d292d3SJohn Baldwin 			else
62426d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_out, blksz);
62526d292d3SJohn Baldwin 		}
62626d292d3SJohn Baldwin 		if (resid > 0) {
62726d292d3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, resid, blk);
62826d292d3SJohn Baldwin 			exf->decrypt_last(swe->sw_kschedule, blk, blk, resid);
62926d292d3SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
630c0341432SJohn Baldwin 		}
631c0341432SJohn Baldwin 	} else {
632c0341432SJohn Baldwin 		/* Inject the authentication data */
63326d292d3SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag);
634c0341432SJohn Baldwin 	}
635c0341432SJohn Baldwin 
63620c128daSJohn Baldwin out:
63720c128daSJohn Baldwin 	explicit_bzero(blkbuf, sizeof(blkbuf));
63826d292d3SJohn Baldwin 	explicit_bzero(tag, sizeof(tag));
63920c128daSJohn Baldwin 	explicit_bzero(iv, sizeof(iv));
64020c128daSJohn Baldwin 
64120c128daSJohn Baldwin 	return (error);
642c0341432SJohn Baldwin }
643c0341432SJohn Baldwin 
644c0341432SJohn Baldwin static int
645c0341432SJohn Baldwin swcr_ccm_cbc_mac(struct swcr_session *ses, struct cryptop *crp)
646c0341432SJohn Baldwin {
64726d292d3SJohn Baldwin 	u_char tag[AES_CBC_MAC_HASH_LEN];
64826d292d3SJohn Baldwin 	u_char iv[AES_BLOCK_LEN];
649c0341432SJohn Baldwin 	union authctx ctx;
650c0341432SJohn Baldwin 	struct swcr_auth *swa;
651c0341432SJohn Baldwin 	struct auth_hash *axf;
65226d292d3SJohn Baldwin 	int error, ivlen;
653c0341432SJohn Baldwin 
654c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
655c0341432SJohn Baldwin 	axf = swa->sw_axf;
656c0341432SJohn Baldwin 
657c0341432SJohn Baldwin 	bcopy(swa->sw_ictx, &ctx, axf->ctxsize);
658c0341432SJohn Baldwin 
659c0341432SJohn Baldwin 	/* Initialize the IV */
660c0341432SJohn Baldwin 	ivlen = AES_CCM_IV_LEN;
66129fe41ddSJohn Baldwin 	crypto_read_iv(crp, iv);
662c0341432SJohn Baldwin 
663c0341432SJohn Baldwin 	/*
664c0341432SJohn Baldwin 	 * AES CCM-CBC-MAC needs to know the length of both the auth
665c0341432SJohn Baldwin 	 * data and payload data before doing the auth computation.
666c0341432SJohn Baldwin 	 */
667c0341432SJohn Baldwin 	ctx.aes_cbc_mac_ctx.authDataLength = crp->crp_payload_length;
668c0341432SJohn Baldwin 	ctx.aes_cbc_mac_ctx.cryptDataLength = 0;
669c0341432SJohn Baldwin 
670c0341432SJohn Baldwin 	axf->Reinit(&ctx, iv, ivlen);
6719b774dc0SJohn Baldwin 	if (crp->crp_aad != NULL)
6729b774dc0SJohn Baldwin 		error = axf->Update(&ctx, crp->crp_aad, crp->crp_aad_length);
6739b774dc0SJohn Baldwin 	else
67426d292d3SJohn Baldwin 		error = crypto_apply(crp, crp->crp_payload_start,
67526d292d3SJohn Baldwin 		    crp->crp_payload_length, axf->Update, &ctx);
67626d292d3SJohn Baldwin 	if (error)
67726d292d3SJohn Baldwin 		return (error);
678c0341432SJohn Baldwin 
679c0341432SJohn Baldwin 	/* Finalize MAC */
68026d292d3SJohn Baldwin 	axf->Final(tag, &ctx);
681c0341432SJohn Baldwin 
682c0341432SJohn Baldwin 	if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
68326d292d3SJohn Baldwin 		u_char tag2[AES_CBC_MAC_HASH_LEN];
68420c128daSJohn Baldwin 
685c0341432SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen,
68626d292d3SJohn Baldwin 		    tag2);
68726d292d3SJohn Baldwin 		if (timingsafe_bcmp(tag, tag2, swa->sw_mlen) != 0)
68820c128daSJohn Baldwin 			error = EBADMSG;
68926d292d3SJohn Baldwin 		explicit_bzero(tag2, sizeof(tag));
690c0341432SJohn Baldwin 	} else {
691c0341432SJohn Baldwin 		/* Inject the authentication data */
69226d292d3SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag);
693c0341432SJohn Baldwin 	}
69426d292d3SJohn Baldwin 	explicit_bzero(tag, sizeof(tag));
69520c128daSJohn Baldwin 	explicit_bzero(iv, sizeof(iv));
69620c128daSJohn Baldwin 	return (error);
697c0341432SJohn Baldwin }
698c0341432SJohn Baldwin 
699c0341432SJohn Baldwin static int
700c0341432SJohn Baldwin swcr_ccm(struct swcr_session *ses, struct cryptop *crp)
701c0341432SJohn Baldwin {
70226d292d3SJohn Baldwin 	uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))];
703c0341432SJohn Baldwin 	u_char *blk = (u_char *)blkbuf;
70426d292d3SJohn Baldwin 	u_char tag[AES_CBC_MAC_HASH_LEN];
70526d292d3SJohn Baldwin 	u_char iv[AES_BLOCK_LEN];
7069c0e3d3aSJohn Baldwin 	struct crypto_buffer_cursor cc_in, cc_out;
70726d292d3SJohn Baldwin 	const u_char *inblk;
70826d292d3SJohn Baldwin 	u_char *outblk;
709c0341432SJohn Baldwin 	union authctx ctx;
710c0341432SJohn Baldwin 	struct swcr_auth *swa;
711c0341432SJohn Baldwin 	struct swcr_encdec *swe;
712c0341432SJohn Baldwin 	struct auth_hash *axf;
713c0341432SJohn Baldwin 	struct enc_xform *exf;
71426d292d3SJohn Baldwin 	int blksz, error, ivlen, r, resid;
715c0341432SJohn Baldwin 
716c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
717c0341432SJohn Baldwin 	axf = swa->sw_axf;
718c0341432SJohn Baldwin 
719c0341432SJohn Baldwin 	bcopy(swa->sw_ictx, &ctx, axf->ctxsize);
72026d292d3SJohn Baldwin 	blksz = AES_BLOCK_LEN;
72126d292d3SJohn Baldwin 	KASSERT(axf->blocksize == blksz, ("%s: axf block size mismatch",
72226d292d3SJohn Baldwin 	    __func__));
723c0341432SJohn Baldwin 
724c0341432SJohn Baldwin 	swe = &ses->swcr_encdec;
725c0341432SJohn Baldwin 	exf = swe->sw_exf;
726723d8764SJohn Baldwin 	KASSERT(axf->blocksize == exf->native_blocksize,
727723d8764SJohn Baldwin 	    ("%s: blocksize mismatch", __func__));
728c0341432SJohn Baldwin 
729c0341432SJohn Baldwin 	if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0)
730c0341432SJohn Baldwin 		return (EINVAL);
731c0341432SJohn Baldwin 
732c0341432SJohn Baldwin 	/* Initialize the IV */
733c0341432SJohn Baldwin 	ivlen = AES_CCM_IV_LEN;
734c0341432SJohn Baldwin 	bcopy(crp->crp_iv, iv, ivlen);
735c0341432SJohn Baldwin 
736c0341432SJohn Baldwin 	/*
737c0341432SJohn Baldwin 	 * AES CCM-CBC-MAC needs to know the length of both the auth
738c0341432SJohn Baldwin 	 * data and payload data before doing the auth computation.
739c0341432SJohn Baldwin 	 */
740c0341432SJohn Baldwin 	ctx.aes_cbc_mac_ctx.authDataLength = crp->crp_aad_length;
741c0341432SJohn Baldwin 	ctx.aes_cbc_mac_ctx.cryptDataLength = crp->crp_payload_length;
742c0341432SJohn Baldwin 
743c0341432SJohn Baldwin 	/* Supply MAC with IV */
744c0341432SJohn Baldwin 	axf->Reinit(&ctx, iv, ivlen);
745c0341432SJohn Baldwin 
746c0341432SJohn Baldwin 	/* Supply MAC with AAD */
7479b774dc0SJohn Baldwin 	if (crp->crp_aad != NULL)
7489b774dc0SJohn Baldwin 		error = axf->Update(&ctx, crp->crp_aad, crp->crp_aad_length);
7499b774dc0SJohn Baldwin 	else
7509b774dc0SJohn Baldwin 		error = crypto_apply(crp, crp->crp_aad_start,
7519b774dc0SJohn Baldwin 		    crp->crp_aad_length, axf->Update, &ctx);
75226d292d3SJohn Baldwin 	if (error)
75326d292d3SJohn Baldwin 		return (error);
754c0341432SJohn Baldwin 
755c0341432SJohn Baldwin 	exf->reinit(swe->sw_kschedule, iv);
756c0341432SJohn Baldwin 
757c0341432SJohn Baldwin 	/* Do encryption/decryption with MAC */
7589c0e3d3aSJohn Baldwin 	crypto_cursor_init(&cc_in, &crp->crp_buf);
7599c0e3d3aSJohn Baldwin 	crypto_cursor_advance(&cc_in, crp->crp_payload_start);
7609c0e3d3aSJohn Baldwin 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
7619c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_out, &crp->crp_obuf);
7629c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_out, crp->crp_payload_output_start);
7639c0e3d3aSJohn Baldwin 	} else
7649c0e3d3aSJohn Baldwin 		cc_out = cc_in;
76526d292d3SJohn Baldwin 	for (resid = crp->crp_payload_length; resid >= blksz; resid -= blksz) {
76626d292d3SJohn Baldwin 		if (crypto_cursor_seglen(&cc_in) < blksz) {
76726d292d3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, blksz, blk);
76826d292d3SJohn Baldwin 			inblk = blk;
76926d292d3SJohn Baldwin 		} else {
77026d292d3SJohn Baldwin 			inblk = crypto_cursor_segbase(&cc_in);
77126d292d3SJohn Baldwin 			crypto_cursor_advance(&cc_in, blksz);
77226d292d3SJohn Baldwin 		}
773c0341432SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
77426d292d3SJohn Baldwin 			if (crypto_cursor_seglen(&cc_out) < blksz)
77526d292d3SJohn Baldwin 				outblk = blk;
77626d292d3SJohn Baldwin 			else
77726d292d3SJohn Baldwin 				outblk = crypto_cursor_segbase(&cc_out);
77826d292d3SJohn Baldwin 			axf->Update(&ctx, inblk, blksz);
77926d292d3SJohn Baldwin 			exf->encrypt(swe->sw_kschedule, inblk, outblk);
78026d292d3SJohn Baldwin 			if (outblk == blk)
78126d292d3SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
78226d292d3SJohn Baldwin 			else
78326d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_out, blksz);
784c0341432SJohn Baldwin 		} else {
785c0341432SJohn Baldwin 			/*
786c0341432SJohn Baldwin 			 * One of the problems with CCM+CBC is that
787c0341432SJohn Baldwin 			 * the authentication is done on the
78826d292d3SJohn Baldwin 			 * unencrypted data.  As a result, we have to
789c0341432SJohn Baldwin 			 * decrypt the data twice: once to generate
790c0341432SJohn Baldwin 			 * the tag and a second time after the tag is
791c0341432SJohn Baldwin 			 * verified.
792c0341432SJohn Baldwin 			 */
79326d292d3SJohn Baldwin 			exf->decrypt(swe->sw_kschedule, inblk, blk);
79426d292d3SJohn Baldwin 			axf->Update(&ctx, blk, blksz);
79526d292d3SJohn Baldwin 		}
79626d292d3SJohn Baldwin 	}
79726d292d3SJohn Baldwin 	if (resid > 0) {
79826d292d3SJohn Baldwin 		crypto_cursor_copydata(&cc_in, resid, blk);
79926d292d3SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
80026d292d3SJohn Baldwin 			axf->Update(&ctx, blk, resid);
80126d292d3SJohn Baldwin 			exf->encrypt_last(swe->sw_kschedule, blk, blk, resid);
80226d292d3SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
80326d292d3SJohn Baldwin 		} else {
80426d292d3SJohn Baldwin 			exf->decrypt_last(swe->sw_kschedule, blk, blk, resid);
80526d292d3SJohn Baldwin 			axf->Update(&ctx, blk, resid);
806c0341432SJohn Baldwin 		}
80708fca7a5SJohn-Mark Gurney 	}
80808fca7a5SJohn-Mark Gurney 
80908fca7a5SJohn-Mark Gurney 	/* Finalize MAC */
81026d292d3SJohn Baldwin 	axf->Final(tag, &ctx);
81108fca7a5SJohn-Mark Gurney 
81208fca7a5SJohn-Mark Gurney 	/* Validate tag */
81320c128daSJohn Baldwin 	error = 0;
814c0341432SJohn Baldwin 	if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
81526d292d3SJohn Baldwin 		u_char tag2[AES_CBC_MAC_HASH_LEN];
81620c128daSJohn Baldwin 
817c0341432SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen,
81826d292d3SJohn Baldwin 		    tag2);
81908fca7a5SJohn-Mark Gurney 
82026d292d3SJohn Baldwin 		r = timingsafe_bcmp(tag, tag2, swa->sw_mlen);
82126d292d3SJohn Baldwin 		explicit_bzero(tag2, sizeof(tag2));
82220c128daSJohn Baldwin 		if (r != 0) {
82320c128daSJohn Baldwin 			error = EBADMSG;
82420c128daSJohn Baldwin 			goto out;
82520c128daSJohn Baldwin 		}
826c0341432SJohn Baldwin 
82708fca7a5SJohn-Mark Gurney 		/* tag matches, decrypt data */
828507281e5SSean Eric Fagan 		exf->reinit(swe->sw_kschedule, iv);
8299c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_in, &crp->crp_buf);
8309c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_in, crp->crp_payload_start);
83126d292d3SJohn Baldwin 		for (resid = crp->crp_payload_length; resid > blksz;
83226d292d3SJohn Baldwin 		     resid -= blksz) {
83326d292d3SJohn Baldwin 			if (crypto_cursor_seglen(&cc_in) < blksz) {
83426d292d3SJohn Baldwin 				crypto_cursor_copydata(&cc_in, blksz, blk);
83526d292d3SJohn Baldwin 				inblk = blk;
83626d292d3SJohn Baldwin 			} else {
83726d292d3SJohn Baldwin 				inblk = crypto_cursor_segbase(&cc_in);
83826d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_in, blksz);
83926d292d3SJohn Baldwin 			}
84026d292d3SJohn Baldwin 			if (crypto_cursor_seglen(&cc_out) < blksz)
84126d292d3SJohn Baldwin 				outblk = blk;
84226d292d3SJohn Baldwin 			else
84326d292d3SJohn Baldwin 				outblk = crypto_cursor_segbase(&cc_out);
84426d292d3SJohn Baldwin 			exf->decrypt(swe->sw_kschedule, inblk, outblk);
84526d292d3SJohn Baldwin 			if (outblk == blk)
84626d292d3SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
84726d292d3SJohn Baldwin 			else
84826d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_out, blksz);
84926d292d3SJohn Baldwin 		}
85026d292d3SJohn Baldwin 		if (resid > 0) {
85126d292d3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, resid, blk);
85226d292d3SJohn Baldwin 			exf->decrypt_last(swe->sw_kschedule, blk, blk, resid);
85326d292d3SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
85408fca7a5SJohn-Mark Gurney 		}
85508fca7a5SJohn-Mark Gurney 	} else {
85608fca7a5SJohn-Mark Gurney 		/* Inject the authentication data */
85726d292d3SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag);
85808fca7a5SJohn-Mark Gurney 	}
85908fca7a5SJohn-Mark Gurney 
86020c128daSJohn Baldwin out:
86120c128daSJohn Baldwin 	explicit_bzero(blkbuf, sizeof(blkbuf));
86226d292d3SJohn Baldwin 	explicit_bzero(tag, sizeof(tag));
86320c128daSJohn Baldwin 	explicit_bzero(iv, sizeof(iv));
86420c128daSJohn Baldwin 	return (error);
86508fca7a5SJohn-Mark Gurney }
86608fca7a5SJohn-Mark Gurney 
867091d81d1SSam Leffler /*
868c0341432SJohn Baldwin  * Apply a cipher and a digest to perform EtA.
869c0341432SJohn Baldwin  */
870c0341432SJohn Baldwin static int
871c0341432SJohn Baldwin swcr_eta(struct swcr_session *ses, struct cryptop *crp)
872c0341432SJohn Baldwin {
873c0341432SJohn Baldwin 	int error;
874c0341432SJohn Baldwin 
875c0341432SJohn Baldwin 	if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
876c0341432SJohn Baldwin 		error = swcr_encdec(ses, crp);
877c0341432SJohn Baldwin 		if (error == 0)
878c0341432SJohn Baldwin 			error = swcr_authcompute(ses, crp);
879c0341432SJohn Baldwin 	} else {
880c0341432SJohn Baldwin 		error = swcr_authcompute(ses, crp);
881c0341432SJohn Baldwin 		if (error == 0)
882c0341432SJohn Baldwin 			error = swcr_encdec(ses, crp);
883c0341432SJohn Baldwin 	}
884c0341432SJohn Baldwin 	return (error);
885c0341432SJohn Baldwin }
886c0341432SJohn Baldwin 
887c0341432SJohn Baldwin /*
888091d81d1SSam Leffler  * Apply a compression/decompression algorithm
889091d81d1SSam Leffler  */
890091d81d1SSam Leffler static int
891c0341432SJohn Baldwin swcr_compdec(struct swcr_session *ses, struct cryptop *crp)
892091d81d1SSam Leffler {
893091d81d1SSam Leffler 	u_int8_t *data, *out;
894091d81d1SSam Leffler 	struct comp_algo *cxf;
895091d81d1SSam Leffler 	int adj;
896091d81d1SSam Leffler 	u_int32_t result;
897091d81d1SSam Leffler 
898c0341432SJohn Baldwin 	cxf = ses->swcr_compdec.sw_cxf;
899091d81d1SSam Leffler 
900091d81d1SSam Leffler 	/* We must handle the whole buffer of data in one time
901091d81d1SSam Leffler 	 * then if there is not all the data in the mbuf, we must
902091d81d1SSam Leffler 	 * copy in a buffer.
903091d81d1SSam Leffler 	 */
904091d81d1SSam Leffler 
905c0341432SJohn Baldwin 	data = malloc(crp->crp_payload_length, M_CRYPTO_DATA,  M_NOWAIT);
906091d81d1SSam Leffler 	if (data == NULL)
907091d81d1SSam Leffler 		return (EINVAL);
908c0341432SJohn Baldwin 	crypto_copydata(crp, crp->crp_payload_start, crp->crp_payload_length,
909c0341432SJohn Baldwin 	    data);
910091d81d1SSam Leffler 
911c0341432SJohn Baldwin 	if (CRYPTO_OP_IS_COMPRESS(crp->crp_op))
912c0341432SJohn Baldwin 		result = cxf->compress(data, crp->crp_payload_length, &out);
913091d81d1SSam Leffler 	else
914c0341432SJohn Baldwin 		result = cxf->decompress(data, crp->crp_payload_length, &out);
915091d81d1SSam Leffler 
9161ede983cSDag-Erling Smørgrav 	free(data, M_CRYPTO_DATA);
917091d81d1SSam Leffler 	if (result == 0)
918c0341432SJohn Baldwin 		return (EINVAL);
919c0341432SJohn Baldwin 	crp->crp_olen = result;
920c0341432SJohn Baldwin 
921c0341432SJohn Baldwin 	/* Check the compressed size when doing compression */
922c0341432SJohn Baldwin 	if (CRYPTO_OP_IS_COMPRESS(crp->crp_op)) {
923c0341432SJohn Baldwin 		if (result >= crp->crp_payload_length) {
924c0341432SJohn Baldwin 			/* Compression was useless, we lost time */
925c0341432SJohn Baldwin 			free(out, M_CRYPTO_DATA);
926c0341432SJohn Baldwin 			return (0);
927c0341432SJohn Baldwin 		}
928c0341432SJohn Baldwin 	}
929091d81d1SSam Leffler 
930091d81d1SSam Leffler 	/* Copy back the (de)compressed data. m_copyback is
931091d81d1SSam Leffler 	 * extending the mbuf as necessary.
932091d81d1SSam Leffler 	 */
933c0341432SJohn Baldwin 	crypto_copyback(crp, crp->crp_payload_start, result, out);
934c0341432SJohn Baldwin 	if (result < crp->crp_payload_length) {
9359c0e3d3aSJohn Baldwin 		switch (crp->crp_buf.cb_type) {
936c0341432SJohn Baldwin 		case CRYPTO_BUF_MBUF:
937c0341432SJohn Baldwin 			adj = result - crp->crp_payload_length;
9389c0e3d3aSJohn Baldwin 			m_adj(crp->crp_buf.cb_mbuf, adj);
939c0341432SJohn Baldwin 			break;
940c0341432SJohn Baldwin 		case CRYPTO_BUF_UIO: {
9419c0e3d3aSJohn Baldwin 			struct uio *uio = crp->crp_buf.cb_uio;
942091d81d1SSam Leffler 			int ind;
943091d81d1SSam Leffler 
944c0341432SJohn Baldwin 			adj = crp->crp_payload_length - result;
945091d81d1SSam Leffler 			ind = uio->uio_iovcnt - 1;
946091d81d1SSam Leffler 
947091d81d1SSam Leffler 			while (adj > 0 && ind >= 0) {
948091d81d1SSam Leffler 				if (adj < uio->uio_iov[ind].iov_len) {
949091d81d1SSam Leffler 					uio->uio_iov[ind].iov_len -= adj;
950091d81d1SSam Leffler 					break;
951091d81d1SSam Leffler 				}
952091d81d1SSam Leffler 
953091d81d1SSam Leffler 				adj -= uio->uio_iov[ind].iov_len;
954091d81d1SSam Leffler 				uio->uio_iov[ind].iov_len = 0;
955091d81d1SSam Leffler 				ind--;
956091d81d1SSam Leffler 				uio->uio_iovcnt--;
957091d81d1SSam Leffler 			}
958091d81d1SSam Leffler 			}
959c0341432SJohn Baldwin 			break;
960e6f6d0c9SAlan Somers 		case CRYPTO_BUF_VMPAGE:
961e6f6d0c9SAlan Somers 			adj = crp->crp_payload_length - result;
962e6f6d0c9SAlan Somers 			crp->crp_buf.cb_vm_page_len -= adj;
963e6f6d0c9SAlan Somers 			break;
9649c0e3d3aSJohn Baldwin 		default:
9659c0e3d3aSJohn Baldwin 			break;
966c0341432SJohn Baldwin 		}
967091d81d1SSam Leffler 	}
9681ede983cSDag-Erling Smørgrav 	free(out, M_CRYPTO_DATA);
969091d81d1SSam Leffler 	return 0;
970091d81d1SSam Leffler }
971091d81d1SSam Leffler 
972091d81d1SSam Leffler static int
9733e947048SJohn Baldwin swcr_setup_cipher(struct swcr_session *ses,
974c0341432SJohn Baldwin     const struct crypto_session_params *csp)
975091d81d1SSam Leffler {
976c0341432SJohn Baldwin 	struct swcr_encdec *swe;
977091d81d1SSam Leffler 	struct enc_xform *txf;
978f6c4bc3bSPawel Jakub Dawidek 	int error;
979091d81d1SSam Leffler 
980c0341432SJohn Baldwin 	swe = &ses->swcr_encdec;
981c0341432SJohn Baldwin 	txf = crypto_cipher(csp);
982c0341432SJohn Baldwin 	MPASS(txf->ivsize == csp->csp_ivlen);
9833e947048SJohn Baldwin 	if (txf->ctxsize != 0) {
9843e947048SJohn Baldwin 		swe->sw_kschedule = malloc(txf->ctxsize, M_CRYPTO_DATA,
9853e947048SJohn Baldwin 		    M_NOWAIT);
9863e947048SJohn Baldwin 		if (swe->sw_kschedule == NULL)
9873e947048SJohn Baldwin 			return (ENOMEM);
9883e947048SJohn Baldwin 	}
989c0341432SJohn Baldwin 	if (csp->csp_cipher_key != NULL) {
9903e947048SJohn Baldwin 		error = txf->setkey(swe->sw_kschedule,
991c0341432SJohn Baldwin 		    csp->csp_cipher_key, csp->csp_cipher_klen);
992c0341432SJohn Baldwin 		if (error)
993c0341432SJohn Baldwin 			return (error);
994091d81d1SSam Leffler 	}
995c0341432SJohn Baldwin 	swe->sw_exf = txf;
996c0341432SJohn Baldwin 	return (0);
997f6c4bc3bSPawel Jakub Dawidek }
998091d81d1SSam Leffler 
999c0341432SJohn Baldwin static int
1000c0341432SJohn Baldwin swcr_setup_auth(struct swcr_session *ses,
1001c0341432SJohn Baldwin     const struct crypto_session_params *csp)
1002c0341432SJohn Baldwin {
1003c0341432SJohn Baldwin 	struct swcr_auth *swa;
1004c0341432SJohn Baldwin 	struct auth_hash *axf;
1005c0341432SJohn Baldwin 
1006c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
1007c0341432SJohn Baldwin 
1008c0341432SJohn Baldwin 	axf = crypto_auth_hash(csp);
1009c0341432SJohn Baldwin 	swa->sw_axf = axf;
1010c0341432SJohn Baldwin 	if (csp->csp_auth_mlen < 0 || csp->csp_auth_mlen > axf->hashsize)
1011c0341432SJohn Baldwin 		return (EINVAL);
1012c0341432SJohn Baldwin 	if (csp->csp_auth_mlen == 0)
1013c0341432SJohn Baldwin 		swa->sw_mlen = axf->hashsize;
1014c0341432SJohn Baldwin 	else
1015c0341432SJohn Baldwin 		swa->sw_mlen = csp->csp_auth_mlen;
1016c0341432SJohn Baldwin 	swa->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, M_NOWAIT);
1017c0341432SJohn Baldwin 	if (swa->sw_ictx == NULL)
1018c0341432SJohn Baldwin 		return (ENOBUFS);
1019c0341432SJohn Baldwin 
1020c0341432SJohn Baldwin 	switch (csp->csp_auth_alg) {
1021091d81d1SSam Leffler 	case CRYPTO_SHA1_HMAC:
1022c97f39ceSConrad Meyer 	case CRYPTO_SHA2_224_HMAC:
1023f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_256_HMAC:
1024f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_384_HMAC:
1025f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_512_HMAC:
1026091d81d1SSam Leffler 	case CRYPTO_NULL_HMAC:
1027091d81d1SSam Leffler 	case CRYPTO_RIPEMD160_HMAC:
10283a0b6a93SJohn Baldwin 		swa->sw_octx = malloc(axf->ctxsize, M_CRYPTO_DATA,
1029091d81d1SSam Leffler 		    M_NOWAIT);
1030c0341432SJohn Baldwin 		if (swa->sw_octx == NULL)
1031c0341432SJohn Baldwin 			return (ENOBUFS);
1032c0341432SJohn Baldwin 
1033c0341432SJohn Baldwin 		if (csp->csp_auth_key != NULL) {
1034c0341432SJohn Baldwin 			swcr_authprepare(axf, swa, csp->csp_auth_key,
1035c0341432SJohn Baldwin 			    csp->csp_auth_klen);
1036091d81d1SSam Leffler 		}
1037091d81d1SSam Leffler 
1038c0341432SJohn Baldwin 		if (csp->csp_mode == CSP_MODE_DIGEST)
1039c0341432SJohn Baldwin 			ses->swcr_process = swcr_authcompute;
1040091d81d1SSam Leffler 		break;
1041091d81d1SSam Leffler 	case CRYPTO_SHA1:
1042c4729f6eSConrad Meyer 	case CRYPTO_SHA2_224:
1043c4729f6eSConrad Meyer 	case CRYPTO_SHA2_256:
1044c4729f6eSConrad Meyer 	case CRYPTO_SHA2_384:
1045c4729f6eSConrad Meyer 	case CRYPTO_SHA2_512:
1046c0341432SJohn Baldwin 		axf->Init(swa->sw_ictx);
1047c0341432SJohn Baldwin 		if (csp->csp_mode == CSP_MODE_DIGEST)
1048c0341432SJohn Baldwin 			ses->swcr_process = swcr_authcompute;
1049c0341432SJohn Baldwin 		break;
1050c0341432SJohn Baldwin 	case CRYPTO_AES_NIST_GMAC:
1051c0341432SJohn Baldwin 		axf->Init(swa->sw_ictx);
1052c0341432SJohn Baldwin 		axf->Setkey(swa->sw_ictx, csp->csp_auth_key,
1053c0341432SJohn Baldwin 		    csp->csp_auth_klen);
1054c0341432SJohn Baldwin 		if (csp->csp_mode == CSP_MODE_DIGEST)
1055c0341432SJohn Baldwin 			ses->swcr_process = swcr_gmac;
1056c0341432SJohn Baldwin 		break;
1057c0341432SJohn Baldwin 	case CRYPTO_POLY1305:
1058c0341432SJohn Baldwin 	case CRYPTO_BLAKE2B:
1059c0341432SJohn Baldwin 	case CRYPTO_BLAKE2S:
1060c0341432SJohn Baldwin 		/*
1061c0341432SJohn Baldwin 		 * Blake2b and Blake2s support an optional key but do
1062c0341432SJohn Baldwin 		 * not require one.
1063c0341432SJohn Baldwin 		 */
1064c0341432SJohn Baldwin 		if (csp->csp_auth_klen == 0 || csp->csp_auth_key != NULL)
1065c0341432SJohn Baldwin 			axf->Setkey(swa->sw_ictx, csp->csp_auth_key,
1066c0341432SJohn Baldwin 			    csp->csp_auth_klen);
1067c0341432SJohn Baldwin 		axf->Init(swa->sw_ictx);
1068c0341432SJohn Baldwin 		if (csp->csp_mode == CSP_MODE_DIGEST)
1069c0341432SJohn Baldwin 			ses->swcr_process = swcr_authcompute;
1070c0341432SJohn Baldwin 		break;
1071c0341432SJohn Baldwin 	case CRYPTO_AES_CCM_CBC_MAC:
1072c0341432SJohn Baldwin 		axf->Init(swa->sw_ictx);
1073c0341432SJohn Baldwin 		axf->Setkey(swa->sw_ictx, csp->csp_auth_key,
1074c0341432SJohn Baldwin 		    csp->csp_auth_klen);
1075c0341432SJohn Baldwin 		if (csp->csp_mode == CSP_MODE_DIGEST)
1076c0341432SJohn Baldwin 			ses->swcr_process = swcr_ccm_cbc_mac;
1077c0341432SJohn Baldwin 		break;
1078091d81d1SSam Leffler 	}
1079091d81d1SSam Leffler 
1080c0341432SJohn Baldwin 	return (0);
1081c0341432SJohn Baldwin }
108208fca7a5SJohn-Mark Gurney 
1083c0341432SJohn Baldwin static int
1084c0341432SJohn Baldwin swcr_setup_gcm(struct swcr_session *ses,
1085c0341432SJohn Baldwin     const struct crypto_session_params *csp)
1086c0341432SJohn Baldwin {
1087c0341432SJohn Baldwin 	struct swcr_auth *swa;
1088c0341432SJohn Baldwin 	struct auth_hash *axf;
1089c0341432SJohn Baldwin 
1090c0341432SJohn Baldwin 	if (csp->csp_ivlen != AES_GCM_IV_LEN)
1091c0341432SJohn Baldwin 		return (EINVAL);
1092c0341432SJohn Baldwin 
1093c0341432SJohn Baldwin 	/* First, setup the auth side. */
1094c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
1095c0341432SJohn Baldwin 	switch (csp->csp_cipher_klen * 8) {
1096c0341432SJohn Baldwin 	case 128:
1097c0341432SJohn Baldwin 		axf = &auth_hash_nist_gmac_aes_128;
1098c0341432SJohn Baldwin 		break;
1099c0341432SJohn Baldwin 	case 192:
1100c0341432SJohn Baldwin 		axf = &auth_hash_nist_gmac_aes_192;
1101c0341432SJohn Baldwin 		break;
1102c0341432SJohn Baldwin 	case 256:
1103c0341432SJohn Baldwin 		axf = &auth_hash_nist_gmac_aes_256;
1104c0341432SJohn Baldwin 		break;
1105c0341432SJohn Baldwin 	default:
1106c0341432SJohn Baldwin 		return (EINVAL);
1107c0341432SJohn Baldwin 	}
1108c0341432SJohn Baldwin 	swa->sw_axf = axf;
1109c0341432SJohn Baldwin 	if (csp->csp_auth_mlen < 0 || csp->csp_auth_mlen > axf->hashsize)
1110c0341432SJohn Baldwin 		return (EINVAL);
1111c0341432SJohn Baldwin 	if (csp->csp_auth_mlen == 0)
1112c0341432SJohn Baldwin 		swa->sw_mlen = axf->hashsize;
1113c0341432SJohn Baldwin 	else
1114c0341432SJohn Baldwin 		swa->sw_mlen = csp->csp_auth_mlen;
1115c0341432SJohn Baldwin 	swa->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, M_NOWAIT);
1116c0341432SJohn Baldwin 	if (swa->sw_ictx == NULL)
1117c0341432SJohn Baldwin 		return (ENOBUFS);
1118c0341432SJohn Baldwin 	axf->Init(swa->sw_ictx);
1119c0341432SJohn Baldwin 	if (csp->csp_cipher_key != NULL)
1120c0341432SJohn Baldwin 		axf->Setkey(swa->sw_ictx, csp->csp_cipher_key,
1121c0341432SJohn Baldwin 		    csp->csp_cipher_klen);
1122c0341432SJohn Baldwin 
1123c0341432SJohn Baldwin 	/* Second, setup the cipher side. */
11243e947048SJohn Baldwin 	return (swcr_setup_cipher(ses, csp));
1125c0341432SJohn Baldwin }
1126c0341432SJohn Baldwin 
1127c0341432SJohn Baldwin static int
1128c0341432SJohn Baldwin swcr_setup_ccm(struct swcr_session *ses,
1129c0341432SJohn Baldwin     const struct crypto_session_params *csp)
1130c0341432SJohn Baldwin {
1131c0341432SJohn Baldwin 	struct swcr_auth *swa;
1132c0341432SJohn Baldwin 	struct auth_hash *axf;
1133c0341432SJohn Baldwin 
1134c0341432SJohn Baldwin 	if (csp->csp_ivlen != AES_CCM_IV_LEN)
1135c0341432SJohn Baldwin 		return (EINVAL);
1136c0341432SJohn Baldwin 
1137c0341432SJohn Baldwin 	/* First, setup the auth side. */
1138c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
1139c0341432SJohn Baldwin 	switch (csp->csp_cipher_klen * 8) {
1140507281e5SSean Eric Fagan 	case 128:
1141507281e5SSean Eric Fagan 		axf = &auth_hash_ccm_cbc_mac_128;
1142507281e5SSean Eric Fagan 		break;
1143507281e5SSean Eric Fagan 	case 192:
1144507281e5SSean Eric Fagan 		axf = &auth_hash_ccm_cbc_mac_192;
1145507281e5SSean Eric Fagan 		break;
1146507281e5SSean Eric Fagan 	case 256:
1147507281e5SSean Eric Fagan 		axf = &auth_hash_ccm_cbc_mac_256;
1148507281e5SSean Eric Fagan 		break;
1149507281e5SSean Eric Fagan 	default:
1150c0341432SJohn Baldwin 		return (EINVAL);
1151507281e5SSean Eric Fagan 	}
1152c0341432SJohn Baldwin 	swa->sw_axf = axf;
1153c0341432SJohn Baldwin 	if (csp->csp_auth_mlen < 0 || csp->csp_auth_mlen > axf->hashsize)
1154c0341432SJohn Baldwin 		return (EINVAL);
1155c0341432SJohn Baldwin 	if (csp->csp_auth_mlen == 0)
1156c0341432SJohn Baldwin 		swa->sw_mlen = axf->hashsize;
1157c0341432SJohn Baldwin 	else
1158c0341432SJohn Baldwin 		swa->sw_mlen = csp->csp_auth_mlen;
1159c0341432SJohn Baldwin 	swa->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, M_NOWAIT);
1160c0341432SJohn Baldwin 	if (swa->sw_ictx == NULL)
1161c0341432SJohn Baldwin 		return (ENOBUFS);
1162c0341432SJohn Baldwin 	axf->Init(swa->sw_ictx);
1163c0341432SJohn Baldwin 	if (csp->csp_cipher_key != NULL)
1164c0341432SJohn Baldwin 		axf->Setkey(swa->sw_ictx, csp->csp_cipher_key,
1165c0341432SJohn Baldwin 		    csp->csp_cipher_klen);
116608fca7a5SJohn-Mark Gurney 
1167c0341432SJohn Baldwin 	/* Second, setup the cipher side. */
11683e947048SJohn Baldwin 	return (swcr_setup_cipher(ses, csp));
11692e2e26d1SJohn Baldwin }
1170a2bc81bfSJohn-Mark Gurney 
1171c0341432SJohn Baldwin static bool
1172c0341432SJohn Baldwin swcr_auth_supported(const struct crypto_session_params *csp)
1173109919c6SBenno Rice {
1174091d81d1SSam Leffler 	struct auth_hash *axf;
1175091d81d1SSam Leffler 
1176c0341432SJohn Baldwin 	axf = crypto_auth_hash(csp);
1177c0341432SJohn Baldwin 	if (axf == NULL)
1178c0341432SJohn Baldwin 		return (false);
1179c0341432SJohn Baldwin 	switch (csp->csp_auth_alg) {
1180091d81d1SSam Leffler 	case CRYPTO_SHA1_HMAC:
1181c97f39ceSConrad Meyer 	case CRYPTO_SHA2_224_HMAC:
1182f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_256_HMAC:
1183f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_384_HMAC:
1184f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_512_HMAC:
1185091d81d1SSam Leffler 	case CRYPTO_NULL_HMAC:
1186c0341432SJohn Baldwin 	case CRYPTO_RIPEMD160_HMAC:
1187091d81d1SSam Leffler 		break;
1188c0341432SJohn Baldwin 	case CRYPTO_AES_NIST_GMAC:
1189c0341432SJohn Baldwin 		switch (csp->csp_auth_klen * 8) {
1190c0341432SJohn Baldwin 		case 128:
1191c0341432SJohn Baldwin 		case 192:
1192c0341432SJohn Baldwin 		case 256:
1193c0341432SJohn Baldwin 			break;
1194c0341432SJohn Baldwin 		default:
1195c0341432SJohn Baldwin 			return (false);
1196c0341432SJohn Baldwin 		}
1197c0341432SJohn Baldwin 		if (csp->csp_auth_key == NULL)
1198c0341432SJohn Baldwin 			return (false);
1199c0341432SJohn Baldwin 		if (csp->csp_ivlen != AES_GCM_IV_LEN)
1200c0341432SJohn Baldwin 			return (false);
1201c0341432SJohn Baldwin 		break;
120225b7033bSConrad Meyer 	case CRYPTO_POLY1305:
1203c0341432SJohn Baldwin 		if (csp->csp_auth_klen != POLY1305_KEY_LEN)
1204c0341432SJohn Baldwin 			return (false);
1205c0341432SJohn Baldwin 		break;
1206c0341432SJohn Baldwin 	case CRYPTO_AES_CCM_CBC_MAC:
1207c0341432SJohn Baldwin 		switch (csp->csp_auth_klen * 8) {
1208c0341432SJohn Baldwin 		case 128:
1209c0341432SJohn Baldwin 		case 192:
1210c0341432SJohn Baldwin 		case 256:
1211c0341432SJohn Baldwin 			break;
1212c0341432SJohn Baldwin 		default:
1213c0341432SJohn Baldwin 			return (false);
1214c0341432SJohn Baldwin 		}
1215c0341432SJohn Baldwin 		if (csp->csp_auth_key == NULL)
1216c0341432SJohn Baldwin 			return (false);
1217c0341432SJohn Baldwin 		if (csp->csp_ivlen != AES_CCM_IV_LEN)
1218c0341432SJohn Baldwin 			return (false);
1219c0341432SJohn Baldwin 		break;
1220c0341432SJohn Baldwin 	}
1221c0341432SJohn Baldwin 	return (true);
1222c0341432SJohn Baldwin }
1223091d81d1SSam Leffler 
1224c0341432SJohn Baldwin static bool
1225c0341432SJohn Baldwin swcr_cipher_supported(const struct crypto_session_params *csp)
1226c0341432SJohn Baldwin {
1227c0341432SJohn Baldwin 	struct enc_xform *txf;
1228c0341432SJohn Baldwin 
1229c0341432SJohn Baldwin 	txf = crypto_cipher(csp);
1230c0341432SJohn Baldwin 	if (txf == NULL)
1231c0341432SJohn Baldwin 		return (false);
1232c0341432SJohn Baldwin 	if (csp->csp_cipher_alg != CRYPTO_NULL_CBC &&
1233c0341432SJohn Baldwin 	    txf->ivsize != csp->csp_ivlen)
1234c0341432SJohn Baldwin 		return (false);
1235c0341432SJohn Baldwin 	return (true);
1236c0341432SJohn Baldwin }
1237c0341432SJohn Baldwin 
1238c0341432SJohn Baldwin static int
1239c0341432SJohn Baldwin swcr_probesession(device_t dev, const struct crypto_session_params *csp)
1240c0341432SJohn Baldwin {
1241c0341432SJohn Baldwin 
12429b774dc0SJohn Baldwin 	if ((csp->csp_flags & ~(CSP_F_SEPARATE_OUTPUT | CSP_F_SEPARATE_AAD)) !=
12439b774dc0SJohn Baldwin 	    0)
1244c0341432SJohn Baldwin 		return (EINVAL);
1245c0341432SJohn Baldwin 	switch (csp->csp_mode) {
1246c0341432SJohn Baldwin 	case CSP_MODE_COMPRESS:
1247c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1248c0341432SJohn Baldwin 		case CRYPTO_DEFLATE_COMP:
1249c0341432SJohn Baldwin 			break;
1250c0341432SJohn Baldwin 		default:
1251c0341432SJohn Baldwin 			return (EINVAL);
12525fbc5b5aSConrad Meyer 		}
1253091d81d1SSam Leffler 		break;
1254c0341432SJohn Baldwin 	case CSP_MODE_CIPHER:
1255c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1256c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1257c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1258c0341432SJohn Baldwin 			return (EINVAL);
1259c0341432SJohn Baldwin 		default:
1260c0341432SJohn Baldwin 			if (!swcr_cipher_supported(csp))
1261c0341432SJohn Baldwin 				return (EINVAL);
1262091d81d1SSam Leffler 			break;
1263091d81d1SSam Leffler 		}
1264c0341432SJohn Baldwin 		break;
1265c0341432SJohn Baldwin 	case CSP_MODE_DIGEST:
1266c0341432SJohn Baldwin 		if (!swcr_auth_supported(csp))
1267c0341432SJohn Baldwin 			return (EINVAL);
1268c0341432SJohn Baldwin 		break;
1269c0341432SJohn Baldwin 	case CSP_MODE_AEAD:
1270c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1271c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1272c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1273c0341432SJohn Baldwin 			break;
1274c0341432SJohn Baldwin 		default:
1275c0341432SJohn Baldwin 			return (EINVAL);
1276c0341432SJohn Baldwin 		}
1277c0341432SJohn Baldwin 		break;
1278c0341432SJohn Baldwin 	case CSP_MODE_ETA:
1279c0341432SJohn Baldwin 		/* AEAD algorithms cannot be used for EtA. */
1280c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1281c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1282c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1283c0341432SJohn Baldwin 			return (EINVAL);
1284c0341432SJohn Baldwin 		}
1285c0341432SJohn Baldwin 		switch (csp->csp_auth_alg) {
1286c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GMAC:
1287c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_CBC_MAC:
1288c0341432SJohn Baldwin 			return (EINVAL);
1289c0341432SJohn Baldwin 		}
1290c0341432SJohn Baldwin 
1291c0341432SJohn Baldwin 		if (!swcr_cipher_supported(csp) ||
1292c0341432SJohn Baldwin 		    !swcr_auth_supported(csp))
1293c0341432SJohn Baldwin 			return (EINVAL);
1294c0341432SJohn Baldwin 		break;
1295c0341432SJohn Baldwin 	default:
1296c0341432SJohn Baldwin 		return (EINVAL);
1297c0341432SJohn Baldwin 	}
1298c0341432SJohn Baldwin 
1299c0341432SJohn Baldwin 	return (CRYPTODEV_PROBE_SOFTWARE);
1300c0341432SJohn Baldwin }
1301c0341432SJohn Baldwin 
1302c0341432SJohn Baldwin /*
1303c0341432SJohn Baldwin  * Generate a new software session.
1304c0341432SJohn Baldwin  */
1305c0341432SJohn Baldwin static int
1306c0341432SJohn Baldwin swcr_newsession(device_t dev, crypto_session_t cses,
1307c0341432SJohn Baldwin     const struct crypto_session_params *csp)
1308c0341432SJohn Baldwin {
1309c0341432SJohn Baldwin 	struct swcr_session *ses;
1310c0341432SJohn Baldwin 	struct swcr_encdec *swe;
1311c0341432SJohn Baldwin 	struct swcr_auth *swa;
1312c0341432SJohn Baldwin 	struct comp_algo *cxf;
1313c0341432SJohn Baldwin 	int error;
1314c0341432SJohn Baldwin 
1315c0341432SJohn Baldwin 	ses = crypto_get_driver_session(cses);
1316c0341432SJohn Baldwin 	mtx_init(&ses->swcr_lock, "swcr session lock", NULL, MTX_DEF);
1317c0341432SJohn Baldwin 
1318c0341432SJohn Baldwin 	error = 0;
1319c0341432SJohn Baldwin 	swe = &ses->swcr_encdec;
1320c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
1321c0341432SJohn Baldwin 	switch (csp->csp_mode) {
1322c0341432SJohn Baldwin 	case CSP_MODE_COMPRESS:
1323c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1324c0341432SJohn Baldwin 		case CRYPTO_DEFLATE_COMP:
1325c0341432SJohn Baldwin 			cxf = &comp_algo_deflate;
1326c0341432SJohn Baldwin 			break;
1327c0341432SJohn Baldwin #ifdef INVARIANTS
1328c0341432SJohn Baldwin 		default:
1329c0341432SJohn Baldwin 			panic("bad compression algo");
1330c0341432SJohn Baldwin #endif
1331c0341432SJohn Baldwin 		}
1332c0341432SJohn Baldwin 		ses->swcr_compdec.sw_cxf = cxf;
1333c0341432SJohn Baldwin 		ses->swcr_process = swcr_compdec;
1334c0341432SJohn Baldwin 		break;
1335c0341432SJohn Baldwin 	case CSP_MODE_CIPHER:
1336c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1337c0341432SJohn Baldwin 		case CRYPTO_NULL_CBC:
1338c0341432SJohn Baldwin 			ses->swcr_process = swcr_null;
1339c0341432SJohn Baldwin 			break;
1340c0341432SJohn Baldwin #ifdef INVARIANTS
1341c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1342c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1343c0341432SJohn Baldwin 			panic("bad cipher algo");
1344c0341432SJohn Baldwin #endif
1345c0341432SJohn Baldwin 		default:
13463e947048SJohn Baldwin 			error = swcr_setup_cipher(ses, csp);
1347c0341432SJohn Baldwin 			if (error == 0)
1348c0341432SJohn Baldwin 				ses->swcr_process = swcr_encdec;
1349c0341432SJohn Baldwin 		}
1350c0341432SJohn Baldwin 		break;
1351c0341432SJohn Baldwin 	case CSP_MODE_DIGEST:
1352c0341432SJohn Baldwin 		error = swcr_setup_auth(ses, csp);
1353c0341432SJohn Baldwin 		break;
1354c0341432SJohn Baldwin 	case CSP_MODE_AEAD:
1355c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1356c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1357c0341432SJohn Baldwin 			error = swcr_setup_gcm(ses, csp);
1358c0341432SJohn Baldwin 			if (error == 0)
1359c0341432SJohn Baldwin 				ses->swcr_process = swcr_gcm;
1360c0341432SJohn Baldwin 			break;
1361c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1362c0341432SJohn Baldwin 			error = swcr_setup_ccm(ses, csp);
1363c0341432SJohn Baldwin 			if (error == 0)
1364c0341432SJohn Baldwin 				ses->swcr_process = swcr_ccm;
1365c0341432SJohn Baldwin 			break;
1366c0341432SJohn Baldwin #ifdef INVARIANTS
1367c0341432SJohn Baldwin 		default:
1368c0341432SJohn Baldwin 			panic("bad aead algo");
1369c0341432SJohn Baldwin #endif
1370c0341432SJohn Baldwin 		}
1371c0341432SJohn Baldwin 		break;
1372c0341432SJohn Baldwin 	case CSP_MODE_ETA:
1373c0341432SJohn Baldwin #ifdef INVARIANTS
1374c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1375c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1376c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1377c0341432SJohn Baldwin 			panic("bad eta cipher algo");
1378c0341432SJohn Baldwin 		}
1379c0341432SJohn Baldwin 		switch (csp->csp_auth_alg) {
1380c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GMAC:
1381c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_CBC_MAC:
1382c0341432SJohn Baldwin 			panic("bad eta auth algo");
1383c0341432SJohn Baldwin 		}
1384c0341432SJohn Baldwin #endif
1385c0341432SJohn Baldwin 
1386c0341432SJohn Baldwin 		error = swcr_setup_auth(ses, csp);
1387c0341432SJohn Baldwin 		if (error)
1388c0341432SJohn Baldwin 			break;
1389c0341432SJohn Baldwin 		if (csp->csp_cipher_alg == CRYPTO_NULL_CBC) {
1390c0341432SJohn Baldwin 			/* Effectively degrade to digest mode. */
1391c0341432SJohn Baldwin 			ses->swcr_process = swcr_authcompute;
1392c0341432SJohn Baldwin 			break;
1393c0341432SJohn Baldwin 		}
1394c0341432SJohn Baldwin 
13953e947048SJohn Baldwin 		error = swcr_setup_cipher(ses, csp);
1396c0341432SJohn Baldwin 		if (error == 0)
1397c0341432SJohn Baldwin 			ses->swcr_process = swcr_eta;
1398c0341432SJohn Baldwin 		break;
1399c0341432SJohn Baldwin 	default:
1400c0341432SJohn Baldwin 		error = EINVAL;
1401c0341432SJohn Baldwin 	}
1402c0341432SJohn Baldwin 
1403c0341432SJohn Baldwin 	if (error)
1404c0341432SJohn Baldwin 		swcr_freesession(dev, cses);
1405c0341432SJohn Baldwin 	return (error);
1406c0341432SJohn Baldwin }
1407c0341432SJohn Baldwin 
1408c0341432SJohn Baldwin static void
1409c0341432SJohn Baldwin swcr_freesession(device_t dev, crypto_session_t cses)
1410c0341432SJohn Baldwin {
1411c0341432SJohn Baldwin 	struct swcr_session *ses;
1412c0341432SJohn Baldwin 
1413c0341432SJohn Baldwin 	ses = crypto_get_driver_session(cses);
1414c0341432SJohn Baldwin 
1415c0341432SJohn Baldwin 	mtx_destroy(&ses->swcr_lock);
1416c0341432SJohn Baldwin 
14173e947048SJohn Baldwin 	zfree(ses->swcr_encdec.sw_kschedule, M_CRYPTO_DATA);
14184a711b8dSJohn Baldwin 	zfree(ses->swcr_auth.sw_ictx, M_CRYPTO_DATA);
14194a711b8dSJohn Baldwin 	zfree(ses->swcr_auth.sw_octx, M_CRYPTO_DATA);
1420091d81d1SSam Leffler }
1421091d81d1SSam Leffler 
1422091d81d1SSam Leffler /*
1423091d81d1SSam Leffler  * Process a software request.
1424091d81d1SSam Leffler  */
1425091d81d1SSam Leffler static int
14266810ad6fSSam Leffler swcr_process(device_t dev, struct cryptop *crp, int hint)
1427091d81d1SSam Leffler {
1428c0341432SJohn Baldwin 	struct swcr_session *ses;
1429091d81d1SSam Leffler 
14301b0909d5SConrad Meyer 	ses = crypto_get_driver_session(crp->crp_session);
1431a7fcb1afSSean Eric Fagan 	mtx_lock(&ses->swcr_lock);
1432091d81d1SSam Leffler 
1433c0341432SJohn Baldwin 	crp->crp_etype = ses->swcr_process(ses, crp);
1434091d81d1SSam Leffler 
1435a7fcb1afSSean Eric Fagan 	mtx_unlock(&ses->swcr_lock);
1436091d81d1SSam Leffler 	crypto_done(crp);
1437c0341432SJohn Baldwin 	return (0);
1438091d81d1SSam Leffler }
1439091d81d1SSam Leffler 
1440091d81d1SSam Leffler static void
14413f147ab2SWarner Losh swcr_identify(driver_t *drv, device_t parent)
1442091d81d1SSam Leffler {
14436810ad6fSSam Leffler 	/* NB: order 10 is so we get attached after h/w devices */
14446810ad6fSSam Leffler 	if (device_find_child(parent, "cryptosoft", -1) == NULL &&
144586c585d9SMarius Strobl 	    BUS_ADD_CHILD(parent, 10, "cryptosoft", 0) == 0)
14466810ad6fSSam Leffler 		panic("cryptosoft: could not attach");
14476810ad6fSSam Leffler }
1448f6c4bc3bSPawel Jakub Dawidek 
14496810ad6fSSam Leffler static int
14506810ad6fSSam Leffler swcr_probe(device_t dev)
14516810ad6fSSam Leffler {
14526810ad6fSSam Leffler 	device_set_desc(dev, "software crypto");
145386c585d9SMarius Strobl 	return (BUS_PROBE_NOWILDCARD);
14546810ad6fSSam Leffler }
1455f6c4bc3bSPawel Jakub Dawidek 
14566810ad6fSSam Leffler static int
14576810ad6fSSam Leffler swcr_attach(device_t dev)
14586810ad6fSSam Leffler {
14596810ad6fSSam Leffler 
14609ebbebe4SConrad Meyer 	swcr_id = crypto_get_driverid(dev, sizeof(struct swcr_session),
14616810ad6fSSam Leffler 			CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC);
14626810ad6fSSam Leffler 	if (swcr_id < 0) {
14636810ad6fSSam Leffler 		device_printf(dev, "cannot initialize!");
1464c0341432SJohn Baldwin 		return (ENXIO);
14656810ad6fSSam Leffler 	}
14666810ad6fSSam Leffler 
1467c0341432SJohn Baldwin 	return (0);
1468091d81d1SSam Leffler }
14694b465da2SPawel Jakub Dawidek 
14703f147ab2SWarner Losh static int
14716810ad6fSSam Leffler swcr_detach(device_t dev)
14724b465da2SPawel Jakub Dawidek {
14736810ad6fSSam Leffler 	crypto_unregister_all(swcr_id);
14743f147ab2SWarner Losh 	return 0;
14754b465da2SPawel Jakub Dawidek }
14766810ad6fSSam Leffler 
14776810ad6fSSam Leffler static device_method_t swcr_methods[] = {
14786810ad6fSSam Leffler 	DEVMETHOD(device_identify,	swcr_identify),
14796810ad6fSSam Leffler 	DEVMETHOD(device_probe,		swcr_probe),
14806810ad6fSSam Leffler 	DEVMETHOD(device_attach,	swcr_attach),
14816810ad6fSSam Leffler 	DEVMETHOD(device_detach,	swcr_detach),
14826810ad6fSSam Leffler 
1483c0341432SJohn Baldwin 	DEVMETHOD(cryptodev_probesession, swcr_probesession),
14846810ad6fSSam Leffler 	DEVMETHOD(cryptodev_newsession,	swcr_newsession),
14856810ad6fSSam Leffler 	DEVMETHOD(cryptodev_freesession,swcr_freesession),
14866810ad6fSSam Leffler 	DEVMETHOD(cryptodev_process,	swcr_process),
14876810ad6fSSam Leffler 
14886810ad6fSSam Leffler 	{0, 0},
14896810ad6fSSam Leffler };
14906810ad6fSSam Leffler 
14916810ad6fSSam Leffler static driver_t swcr_driver = {
14926810ad6fSSam Leffler 	"cryptosoft",
14936810ad6fSSam Leffler 	swcr_methods,
14946810ad6fSSam Leffler 	0,		/* NB: no softc */
14956810ad6fSSam Leffler };
14966810ad6fSSam Leffler static devclass_t swcr_devclass;
14976810ad6fSSam Leffler 
14986810ad6fSSam Leffler /*
14996810ad6fSSam Leffler  * NB: We explicitly reference the crypto module so we
15006810ad6fSSam Leffler  * get the necessary ordering when built as a loadable
15016810ad6fSSam Leffler  * module.  This is required because we bundle the crypto
15026810ad6fSSam Leffler  * module code together with the cryptosoft driver (otherwise
15036810ad6fSSam Leffler  * normal module dependencies would handle things).
15046810ad6fSSam Leffler  */
15056810ad6fSSam Leffler extern int crypto_modevent(struct module *, int, void *);
15066810ad6fSSam Leffler /* XXX where to attach */
15076810ad6fSSam Leffler DRIVER_MODULE(cryptosoft, nexus, swcr_driver, swcr_devclass, crypto_modevent,0);
15086810ad6fSSam Leffler MODULE_VERSION(cryptosoft, 1);
15096810ad6fSSam Leffler MODULE_DEPEND(cryptosoft, crypto, 1, 1, 1);
1510