xref: /freebsd/sys/opencrypto/cryptosoft.c (revision 6113a08b98e403de5b92cc0a30fdc60489eccc48)
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
121833d604SJohn Baldwin  * Copyright (c) 2014-2021 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  *
191833d604SJohn Baldwin  * Portions of this software were developed by Ararat River
201833d604SJohn Baldwin  * Consulting, LLC under sponsorship of the FreeBSD Foundation.
211833d604SJohn Baldwin  *
22091d81d1SSam Leffler  * Permission to use, copy, and modify this software with or without fee
23091d81d1SSam Leffler  * is hereby granted, provided that this entire notice is included in
24091d81d1SSam Leffler  * all source code copies of any software which is or includes a copy or
25091d81d1SSam Leffler  * modification of this software.
26091d81d1SSam Leffler  *
27091d81d1SSam Leffler  * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
28091d81d1SSam Leffler  * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
29091d81d1SSam Leffler  * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
30091d81d1SSam Leffler  * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
31091d81d1SSam Leffler  * PURPOSE.
32091d81d1SSam Leffler  */
33091d81d1SSam Leffler 
342c446514SDavid E. O'Brien #include <sys/cdefs.h>
352c446514SDavid E. O'Brien __FBSDID("$FreeBSD$");
362c446514SDavid E. O'Brien 
37091d81d1SSam Leffler #include <sys/param.h>
38091d81d1SSam Leffler #include <sys/systm.h>
39091d81d1SSam Leffler #include <sys/malloc.h>
40091d81d1SSam Leffler #include <sys/mbuf.h>
416810ad6fSSam Leffler #include <sys/module.h>
42091d81d1SSam Leffler #include <sys/sysctl.h>
43091d81d1SSam Leffler #include <sys/errno.h>
44091d81d1SSam Leffler #include <sys/random.h>
45091d81d1SSam Leffler #include <sys/kernel.h>
46091d81d1SSam Leffler #include <sys/uio.h>
47109919c6SBenno Rice #include <sys/lock.h>
48109919c6SBenno Rice #include <sys/rwlock.h>
4908fca7a5SJohn-Mark Gurney #include <sys/endian.h>
5008fca7a5SJohn-Mark Gurney #include <sys/limits.h>
51a7fcb1afSSean Eric Fagan #include <sys/mutex.h>
52091d81d1SSam Leffler 
53091d81d1SSam Leffler #include <crypto/sha1.h>
54091d81d1SSam Leffler #include <opencrypto/rmd160.h>
55091d81d1SSam Leffler 
56091d81d1SSam Leffler #include <opencrypto/cryptodev.h>
57091d81d1SSam Leffler #include <opencrypto/xform.h>
58091d81d1SSam Leffler 
596810ad6fSSam Leffler #include <sys/kobj.h>
606810ad6fSSam Leffler #include <sys/bus.h>
616810ad6fSSam Leffler #include "cryptodev_if.h"
62091d81d1SSam Leffler 
63c0341432SJohn Baldwin struct swcr_auth {
64c0341432SJohn Baldwin 	void		*sw_ictx;
65c0341432SJohn Baldwin 	void		*sw_octx;
66d8787d4fSMark Johnston 	const struct auth_hash *sw_axf;
67c0341432SJohn Baldwin 	uint16_t	sw_mlen;
68*6113a08bSJohn Baldwin 	bool		sw_hmac;
69c0341432SJohn Baldwin };
70c0341432SJohn Baldwin 
71c0341432SJohn Baldwin struct swcr_encdec {
72f313909aSJohn Baldwin 	void		*sw_ctx;
73d8787d4fSMark Johnston 	const struct enc_xform *sw_exf;
74c0341432SJohn Baldwin };
75c0341432SJohn Baldwin 
76c0341432SJohn Baldwin struct swcr_compdec {
77d8787d4fSMark Johnston 	const struct comp_algo *sw_cxf;
78c0341432SJohn Baldwin };
79c0341432SJohn Baldwin 
80c0341432SJohn Baldwin struct swcr_session {
81c0341432SJohn Baldwin 	struct mtx	swcr_lock;
82c0341432SJohn Baldwin 	int	(*swcr_process)(struct swcr_session *, struct cryptop *);
83c0341432SJohn Baldwin 
84c0341432SJohn Baldwin 	struct swcr_auth swcr_auth;
85c0341432SJohn Baldwin 	struct swcr_encdec swcr_encdec;
86c0341432SJohn Baldwin 	struct swcr_compdec swcr_compdec;
87c0341432SJohn Baldwin };
88507281e5SSean Eric Fagan 
896810ad6fSSam Leffler static	int32_t swcr_id;
906810ad6fSSam Leffler 
911b0909d5SConrad Meyer static	void swcr_freesession(device_t dev, crypto_session_t cses);
92091d81d1SSam Leffler 
93c0341432SJohn Baldwin /* Used for CRYPTO_NULL_CBC. */
94c0341432SJohn Baldwin static int
95c0341432SJohn Baldwin swcr_null(struct swcr_session *ses, struct cryptop *crp)
96c0341432SJohn Baldwin {
97c0341432SJohn Baldwin 
98c0341432SJohn Baldwin 	return (0);
99c0341432SJohn Baldwin }
100c0341432SJohn Baldwin 
101091d81d1SSam Leffler /*
102091d81d1SSam Leffler  * Apply a symmetric encryption/decryption algorithm.
103091d81d1SSam Leffler  */
104091d81d1SSam Leffler static int
105c0341432SJohn Baldwin swcr_encdec(struct swcr_session *ses, struct cryptop *crp)
106091d81d1SSam Leffler {
1075d7ae54aSConrad Meyer 	unsigned char iv[EALG_MAX_BLOCK_LEN], blk[EALG_MAX_BLOCK_LEN];
10808fca7a5SJohn-Mark Gurney 	unsigned char *ivp, *nivp, iv2[EALG_MAX_BLOCK_LEN];
109c0341432SJohn Baldwin 	const struct crypto_session_params *csp;
110d8787d4fSMark Johnston 	const struct enc_xform *exf;
111b54d1284SJohn Baldwin 	const struct swcr_encdec *sw;
112b54d1284SJohn Baldwin 	void *ctx;
11386be314dSJohn Baldwin 	size_t inlen, outlen;
1141833d604SJohn Baldwin 	int i, blks, resid;
1159c0e3d3aSJohn Baldwin 	struct crypto_buffer_cursor cc_in, cc_out;
11626d292d3SJohn Baldwin 	const unsigned char *inblk;
11726d292d3SJohn Baldwin 	unsigned char *outblk;
11808fca7a5SJohn-Mark Gurney 	int error;
119c0341432SJohn Baldwin 	bool encrypting;
12008fca7a5SJohn-Mark Gurney 
12108fca7a5SJohn-Mark Gurney 	error = 0;
122091d81d1SSam Leffler 
123c0341432SJohn Baldwin 	sw = &ses->swcr_encdec;
124091d81d1SSam Leffler 	exf = sw->sw_exf;
1251833d604SJohn Baldwin 	csp = crypto_get_params(crp->crp_session);
126091d81d1SSam Leffler 
127723d8764SJohn Baldwin 	if (exf->native_blocksize == 0) {
128091d81d1SSam Leffler 		/* Check for non-padded data */
129723d8764SJohn Baldwin 		if ((crp->crp_payload_length % exf->blocksize) != 0)
130723d8764SJohn Baldwin 			return (EINVAL);
131723d8764SJohn Baldwin 
132723d8764SJohn Baldwin 		blks = exf->blocksize;
133723d8764SJohn Baldwin 	} else
134723d8764SJohn Baldwin 		blks = exf->native_blocksize;
135091d81d1SSam Leffler 
136c0341432SJohn Baldwin 	if (exf == &enc_xform_aes_icm &&
137c0341432SJohn Baldwin 	    (crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0)
13808fca7a5SJohn-Mark Gurney 		return (EINVAL);
13908fca7a5SJohn-Mark Gurney 
140b54d1284SJohn Baldwin 	ctx = __builtin_alloca(exf->ctxsize);
141c0341432SJohn Baldwin 	if (crp->crp_cipher_key != NULL) {
142b54d1284SJohn Baldwin 		error = exf->setkey(ctx, crp->crp_cipher_key,
143b54d1284SJohn Baldwin 		    csp->csp_cipher_klen);
144c740ae4bSPoul-Henning Kamp 		if (error)
145c740ae4bSPoul-Henning Kamp 			return (error);
146b54d1284SJohn Baldwin 	} else
147b54d1284SJohn Baldwin 		memcpy(ctx, sw->sw_ctx, exf->ctxsize);
148d295bdeeSPawel Jakub Dawidek 
14920c128daSJohn Baldwin 	crypto_read_iv(crp, iv);
15020c128daSJohn Baldwin 
15108fca7a5SJohn-Mark Gurney 	if (exf->reinit) {
152d295bdeeSPawel Jakub Dawidek 		/*
153d295bdeeSPawel Jakub Dawidek 		 * xforms that provide a reinit method perform all IV
154d295bdeeSPawel Jakub Dawidek 		 * handling themselves.
155d295bdeeSPawel Jakub Dawidek 		 */
156b54d1284SJohn Baldwin 		exf->reinit(ctx, iv, csp->csp_ivlen);
157091d81d1SSam Leffler 	}
158091d81d1SSam Leffler 
1599c0e3d3aSJohn Baldwin 	ivp = iv;
160091d81d1SSam Leffler 
1619c0e3d3aSJohn Baldwin 	crypto_cursor_init(&cc_in, &crp->crp_buf);
1629c0e3d3aSJohn Baldwin 	crypto_cursor_advance(&cc_in, crp->crp_payload_start);
16386be314dSJohn Baldwin 	inblk = crypto_cursor_segment(&cc_in, &inlen);
1649c0e3d3aSJohn Baldwin 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
1659c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_out, &crp->crp_obuf);
1669c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_out, crp->crp_payload_output_start);
1679c0e3d3aSJohn Baldwin 	} else
1689c0e3d3aSJohn Baldwin 		cc_out = cc_in;
16986be314dSJohn Baldwin 	outblk = crypto_cursor_segment(&cc_out, &outlen);
1709c0e3d3aSJohn Baldwin 
1719c0e3d3aSJohn Baldwin 	resid = crp->crp_payload_length;
172c0341432SJohn Baldwin 	encrypting = CRYPTO_OP_IS_ENCRYPT(crp->crp_op);
173091d81d1SSam Leffler 
174091d81d1SSam Leffler 	/*
1759c0e3d3aSJohn Baldwin 	 * Loop through encrypting blocks.  'inlen' is the remaining
1769c0e3d3aSJohn Baldwin 	 * length of the current segment in the input buffer.
1779c0e3d3aSJohn Baldwin 	 * 'outlen' is the remaining length of current segment in the
1789c0e3d3aSJohn Baldwin 	 * output buffer.
179091d81d1SSam Leffler 	 */
1809c0e3d3aSJohn Baldwin 	while (resid >= blks) {
1819c0e3d3aSJohn Baldwin 		/*
1829c0e3d3aSJohn Baldwin 		 * If the current block is not contained within the
1839c0e3d3aSJohn Baldwin 		 * current input/output segment, use 'blk' as a local
1849c0e3d3aSJohn Baldwin 		 * buffer.
1859c0e3d3aSJohn Baldwin 		 */
1869c0e3d3aSJohn Baldwin 		if (inlen < blks) {
1879c0e3d3aSJohn Baldwin 			crypto_cursor_copydata(&cc_in, blks, blk);
1889c0e3d3aSJohn Baldwin 			inblk = blk;
189d295bdeeSPawel Jakub Dawidek 		}
1909c0e3d3aSJohn Baldwin 		if (outlen < blks)
1919c0e3d3aSJohn Baldwin 			outblk = blk;
1929c0e3d3aSJohn Baldwin 
1939c0e3d3aSJohn Baldwin 		/*
1949c0e3d3aSJohn Baldwin 		 * Ciphers without a 'reinit' hook are assumed to be
1959c0e3d3aSJohn Baldwin 		 * used in CBC mode where the chaining is done here.
1969c0e3d3aSJohn Baldwin 		 */
1979c0e3d3aSJohn Baldwin 		if (exf->reinit != NULL) {
1989c0e3d3aSJohn Baldwin 			if (encrypting)
199b54d1284SJohn Baldwin 				exf->encrypt(ctx, inblk, outblk);
2009c0e3d3aSJohn Baldwin 			else
201b54d1284SJohn Baldwin 				exf->decrypt(ctx, inblk, outblk);
202c0341432SJohn Baldwin 		} else if (encrypting) {
203091d81d1SSam Leffler 			/* XOR with previous block */
2049c0e3d3aSJohn Baldwin 			for (i = 0; i < blks; i++)
2059c0e3d3aSJohn Baldwin 				outblk[i] = inblk[i] ^ ivp[i];
206091d81d1SSam Leffler 
207b54d1284SJohn Baldwin 			exf->encrypt(ctx, outblk, outblk);
208091d81d1SSam Leffler 
209091d81d1SSam Leffler 			/*
210091d81d1SSam Leffler 			 * Keep encrypted block for XOR'ing
211091d81d1SSam Leffler 			 * with next block
212091d81d1SSam Leffler 			 */
2139c0e3d3aSJohn Baldwin 			memcpy(iv, outblk, blks);
214091d81d1SSam Leffler 			ivp = iv;
215091d81d1SSam Leffler 		} else {	/* decrypt */
216091d81d1SSam Leffler 			/*
217091d81d1SSam Leffler 			 * Keep encrypted block for XOR'ing
218091d81d1SSam Leffler 			 * with next block
219091d81d1SSam Leffler 			 */
22008fca7a5SJohn-Mark Gurney 			nivp = (ivp == iv) ? iv2 : iv;
2219c0e3d3aSJohn Baldwin 			memcpy(nivp, inblk, blks);
222091d81d1SSam Leffler 
223b54d1284SJohn Baldwin 			exf->decrypt(ctx, inblk, outblk);
224091d81d1SSam Leffler 
225091d81d1SSam Leffler 			/* XOR with previous block */
2269c0e3d3aSJohn Baldwin 			for (i = 0; i < blks; i++)
2279c0e3d3aSJohn Baldwin 				outblk[i] ^= ivp[i];
228091d81d1SSam Leffler 
22908fca7a5SJohn-Mark Gurney 			ivp = nivp;
230091d81d1SSam Leffler 		}
231091d81d1SSam Leffler 
2329c0e3d3aSJohn Baldwin 		if (inlen < blks) {
23386be314dSJohn Baldwin 			inblk = crypto_cursor_segment(&cc_in, &inlen);
2349c0e3d3aSJohn Baldwin 		} else {
2359c0e3d3aSJohn Baldwin 			crypto_cursor_advance(&cc_in, blks);
2369c0e3d3aSJohn Baldwin 			inlen -= blks;
2379c0e3d3aSJohn Baldwin 			inblk += blks;
23808fca7a5SJohn-Mark Gurney 		}
239091d81d1SSam Leffler 
2409c0e3d3aSJohn Baldwin 		if (outlen < blks) {
2419c0e3d3aSJohn Baldwin 			crypto_cursor_copyback(&cc_out, blks, blk);
24286be314dSJohn Baldwin 			outblk = crypto_cursor_segment(&cc_out, &outlen);
2439c0e3d3aSJohn Baldwin 		} else {
2449c0e3d3aSJohn Baldwin 			crypto_cursor_advance(&cc_out, blks);
2459c0e3d3aSJohn Baldwin 			outlen -= blks;
2469c0e3d3aSJohn Baldwin 			outblk += blks;
247091d81d1SSam Leffler 		}
248091d81d1SSam Leffler 
2499c0e3d3aSJohn Baldwin 		resid -= blks;
250f34a967bSPawel Jakub Dawidek 	}
251f34a967bSPawel Jakub Dawidek 
252723d8764SJohn Baldwin 	/* Handle trailing partial block for stream ciphers. */
2539c0e3d3aSJohn Baldwin 	if (resid > 0) {
254723d8764SJohn Baldwin 		KASSERT(exf->native_blocksize != 0,
255723d8764SJohn Baldwin 		    ("%s: partial block of %d bytes for cipher %s",
256723d8764SJohn Baldwin 		    __func__, i, exf->name));
257723d8764SJohn Baldwin 		KASSERT(exf->reinit != NULL,
258723d8764SJohn Baldwin 		    ("%s: partial block cipher %s without reinit hook",
259723d8764SJohn Baldwin 		    __func__, exf->name));
2609c0e3d3aSJohn Baldwin 		KASSERT(resid < blks, ("%s: partial block too big", __func__));
261723d8764SJohn Baldwin 
26286be314dSJohn Baldwin 		inblk = crypto_cursor_segment(&cc_in, &inlen);
26386be314dSJohn Baldwin 		outblk = crypto_cursor_segment(&cc_out, &outlen);
2649c0e3d3aSJohn Baldwin 		if (inlen < resid) {
2659c0e3d3aSJohn Baldwin 			crypto_cursor_copydata(&cc_in, resid, blk);
2669c0e3d3aSJohn Baldwin 			inblk = blk;
26786be314dSJohn Baldwin 		}
2689c0e3d3aSJohn Baldwin 		if (outlen < resid)
2699c0e3d3aSJohn Baldwin 			outblk = blk;
2709c0e3d3aSJohn Baldwin 		if (encrypting)
271b54d1284SJohn Baldwin 			exf->encrypt_last(ctx, inblk, outblk,
2729c0e3d3aSJohn Baldwin 			    resid);
2739c0e3d3aSJohn Baldwin 		else
274b54d1284SJohn Baldwin 			exf->decrypt_last(ctx, inblk, outblk,
2759c0e3d3aSJohn Baldwin 			    resid);
2769c0e3d3aSJohn Baldwin 		if (outlen < resid)
2779c0e3d3aSJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
278723d8764SJohn Baldwin 	}
279723d8764SJohn Baldwin 
280b54d1284SJohn Baldwin 	explicit_bzero(ctx, exf->ctxsize);
28120c128daSJohn Baldwin 	explicit_bzero(blk, sizeof(blk));
28220c128daSJohn Baldwin 	explicit_bzero(iv, sizeof(iv));
28320c128daSJohn Baldwin 	explicit_bzero(iv2, sizeof(iv2));
2849c0e3d3aSJohn Baldwin 	return (0);
285091d81d1SSam Leffler }
286091d81d1SSam Leffler 
287091d81d1SSam Leffler /*
288c0341432SJohn Baldwin  * Compute or verify hash.
289091d81d1SSam Leffler  */
290091d81d1SSam Leffler static int
291c0341432SJohn Baldwin swcr_authcompute(struct swcr_session *ses, struct cryptop *crp)
292091d81d1SSam Leffler {
293c0341432SJohn Baldwin 	u_char aalg[HASH_MAX_LEN];
294c0341432SJohn Baldwin 	const struct crypto_session_params *csp;
295*6113a08bSJohn Baldwin 	const struct swcr_auth *sw;
296d8787d4fSMark Johnston 	const struct auth_hash *axf;
297091d81d1SSam Leffler 	union authctx ctx;
298091d81d1SSam Leffler 	int err;
299091d81d1SSam Leffler 
300c0341432SJohn Baldwin 	sw = &ses->swcr_auth;
301091d81d1SSam Leffler 
302091d81d1SSam Leffler 	axf = sw->sw_axf;
303091d81d1SSam Leffler 
304c0341432SJohn Baldwin 	csp = crypto_get_params(crp->crp_session);
3056038018aSMarcin Wojtas 	if (crp->crp_auth_key != NULL) {
306*6113a08bSJohn Baldwin 		if (sw->sw_hmac) {
307*6113a08bSJohn Baldwin 			hmac_init_ipad(axf, crp->crp_auth_key,
308*6113a08bSJohn Baldwin 			    csp->csp_auth_klen, &ctx);
309*6113a08bSJohn Baldwin 		} else {
310*6113a08bSJohn Baldwin 			axf->Init(&ctx);
311*6113a08bSJohn Baldwin 			axf->Setkey(&ctx, crp->crp_auth_key,
312c0341432SJohn Baldwin 			    csp->csp_auth_klen);
31325b7033bSConrad Meyer 		}
314*6113a08bSJohn Baldwin 	} else
315*6113a08bSJohn Baldwin 		memcpy(&ctx, sw->sw_ictx, axf->ctxsize);
316091d81d1SSam Leffler 
3179b774dc0SJohn Baldwin 	if (crp->crp_aad != NULL)
3189b774dc0SJohn Baldwin 		err = axf->Update(&ctx, crp->crp_aad, crp->crp_aad_length);
3199b774dc0SJohn Baldwin 	else
320c0341432SJohn Baldwin 		err = crypto_apply(crp, crp->crp_aad_start, crp->crp_aad_length,
3219b6b2f86SJohn Baldwin 		    axf->Update, &ctx);
322091d81d1SSam Leffler 	if (err)
323e0b155feSJohn Baldwin 		goto out;
324091d81d1SSam Leffler 
3259c0e3d3aSJohn Baldwin 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp) &&
3269c0e3d3aSJohn Baldwin 	    CRYPTO_OP_IS_ENCRYPT(crp->crp_op))
3279c0e3d3aSJohn Baldwin 		err = crypto_apply_buf(&crp->crp_obuf,
3289c0e3d3aSJohn Baldwin 		    crp->crp_payload_output_start, crp->crp_payload_length,
3299b6b2f86SJohn Baldwin 		    axf->Update, &ctx);
3309c0e3d3aSJohn Baldwin 	else
3319c0e3d3aSJohn Baldwin 		err = crypto_apply(crp, crp->crp_payload_start,
3329b6b2f86SJohn Baldwin 		    crp->crp_payload_length, axf->Update, &ctx);
333c0341432SJohn Baldwin 	if (err)
334e0b155feSJohn Baldwin 		goto out;
335091d81d1SSam Leffler 
3366038018aSMarcin Wojtas 	if (csp->csp_flags & CSP_F_ESN)
3376038018aSMarcin Wojtas 		axf->Update(&ctx, crp->crp_esn, 4);
3386038018aSMarcin Wojtas 
339091d81d1SSam Leffler 	axf->Final(aalg, &ctx);
340*6113a08bSJohn Baldwin 	if (sw->sw_hmac) {
341*6113a08bSJohn Baldwin 		if (crp->crp_auth_key != NULL)
342*6113a08bSJohn Baldwin 			hmac_init_opad(axf, crp->crp_auth_key,
343*6113a08bSJohn Baldwin 			    csp->csp_auth_klen, &ctx);
344*6113a08bSJohn Baldwin 		else
345*6113a08bSJohn Baldwin 			memcpy(&ctx, sw->sw_octx, axf->ctxsize);
346091d81d1SSam Leffler 		axf->Update(&ctx, aalg, axf->hashsize);
347091d81d1SSam Leffler 		axf->Final(aalg, &ctx);
348091d81d1SSam Leffler 	}
349091d81d1SSam Leffler 
350c0341432SJohn Baldwin 	if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
35120c128daSJohn Baldwin 		u_char uaalg[HASH_MAX_LEN];
35220c128daSJohn Baldwin 
353c0341432SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, sw->sw_mlen, uaalg);
354c0341432SJohn Baldwin 		if (timingsafe_bcmp(aalg, uaalg, sw->sw_mlen) != 0)
35520c128daSJohn Baldwin 			err = EBADMSG;
35620c128daSJohn Baldwin 		explicit_bzero(uaalg, sizeof(uaalg));
357c0341432SJohn Baldwin 	} else {
358091d81d1SSam Leffler 		/* Inject the authentication data */
359c0341432SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, sw->sw_mlen, aalg);
360c0341432SJohn Baldwin 	}
36120c128daSJohn Baldwin 	explicit_bzero(aalg, sizeof(aalg));
362e0b155feSJohn Baldwin out:
363e0b155feSJohn Baldwin 	explicit_bzero(&ctx, sizeof(ctx));
36420c128daSJohn Baldwin 	return (err);
365091d81d1SSam Leffler }
366091d81d1SSam Leffler 
36708fca7a5SJohn-Mark Gurney CTASSERT(INT_MAX <= (1ll<<39) - 256);	/* GCM: plain text < 2^39-256 */
36808fca7a5SJohn-Mark Gurney CTASSERT(INT_MAX <= (uint64_t)-1);	/* GCM: associated data <= 2^64-1 */
36908fca7a5SJohn-Mark Gurney 
37008fca7a5SJohn-Mark Gurney static int
371c0341432SJohn Baldwin swcr_gmac(struct swcr_session *ses, struct cryptop *crp)
37208fca7a5SJohn-Mark Gurney {
37326d292d3SJohn Baldwin 	uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))];
37408fca7a5SJohn-Mark Gurney 	u_char *blk = (u_char *)blkbuf;
37526d292d3SJohn Baldwin 	u_char tag[GMAC_DIGEST_LEN];
37626d292d3SJohn Baldwin 	u_char iv[AES_BLOCK_LEN];
3779c0e3d3aSJohn Baldwin 	struct crypto_buffer_cursor cc;
37826d292d3SJohn Baldwin 	const u_char *inblk;
37908fca7a5SJohn-Mark Gurney 	union authctx ctx;
380*6113a08bSJohn Baldwin 	const struct swcr_auth *swa;
381d8787d4fSMark Johnston 	const struct auth_hash *axf;
38208fca7a5SJohn-Mark Gurney 	uint32_t *blkp;
38386be314dSJohn Baldwin 	size_t len;
38486be314dSJohn Baldwin 	int blksz, error, ivlen, resid;
38508fca7a5SJohn-Mark Gurney 
386c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
38708fca7a5SJohn-Mark Gurney 	axf = swa->sw_axf;
38826d292d3SJohn Baldwin 	blksz = GMAC_BLOCK_LEN;
38926d292d3SJohn Baldwin 	KASSERT(axf->blocksize == blksz, ("%s: axf block size mismatch",
39026d292d3SJohn Baldwin 	    __func__));
39108fca7a5SJohn-Mark Gurney 
392*6113a08bSJohn Baldwin 	if (crp->crp_auth_key != NULL) {
393*6113a08bSJohn Baldwin 		axf->Init(&ctx);
394*6113a08bSJohn Baldwin 		axf->Setkey(&ctx, crp->crp_auth_key,
395*6113a08bSJohn Baldwin 		    crypto_get_params(crp->crp_session)->csp_auth_klen);
396*6113a08bSJohn Baldwin 	} else
397*6113a08bSJohn Baldwin 		memcpy(&ctx, swa->sw_ictx, axf->ctxsize);
398*6113a08bSJohn Baldwin 
39908fca7a5SJohn-Mark Gurney 	/* Initialize the IV */
400c0341432SJohn Baldwin 	ivlen = AES_GCM_IV_LEN;
40129fe41ddSJohn Baldwin 	crypto_read_iv(crp, iv);
40208fca7a5SJohn-Mark Gurney 
40308fca7a5SJohn-Mark Gurney 	axf->Reinit(&ctx, iv, ivlen);
4049c0e3d3aSJohn Baldwin 	crypto_cursor_init(&cc, &crp->crp_buf);
4059c0e3d3aSJohn Baldwin 	crypto_cursor_advance(&cc, crp->crp_payload_start);
40626d292d3SJohn Baldwin 	for (resid = crp->crp_payload_length; resid >= blksz; resid -= len) {
40786be314dSJohn Baldwin 		inblk = crypto_cursor_segment(&cc, &len);
40826d292d3SJohn Baldwin 		if (len >= blksz) {
40926d292d3SJohn Baldwin 			len = rounddown(MIN(len, resid), blksz);
41026d292d3SJohn Baldwin 			crypto_cursor_advance(&cc, len);
41126d292d3SJohn Baldwin 		} else {
41226d292d3SJohn Baldwin 			len = blksz;
4139c0e3d3aSJohn Baldwin 			crypto_cursor_copydata(&cc, len, blk);
41426d292d3SJohn Baldwin 			inblk = blk;
41526d292d3SJohn Baldwin 		}
41626d292d3SJohn Baldwin 		axf->Update(&ctx, inblk, len);
41726d292d3SJohn Baldwin 	}
41826d292d3SJohn Baldwin 	if (resid > 0) {
41926d292d3SJohn Baldwin 		memset(blk, 0, blksz);
42026d292d3SJohn Baldwin 		crypto_cursor_copydata(&cc, resid, blk);
42108fca7a5SJohn-Mark Gurney 		axf->Update(&ctx, blk, blksz);
42208fca7a5SJohn-Mark Gurney 	}
42308fca7a5SJohn-Mark Gurney 
42408fca7a5SJohn-Mark Gurney 	/* length block */
42526d292d3SJohn Baldwin 	memset(blk, 0, blksz);
42608fca7a5SJohn-Mark Gurney 	blkp = (uint32_t *)blk + 1;
427c0341432SJohn Baldwin 	*blkp = htobe32(crp->crp_payload_length * 8);
42808fca7a5SJohn-Mark Gurney 	axf->Update(&ctx, blk, blksz);
429c0341432SJohn Baldwin 
430c0341432SJohn Baldwin 	/* Finalize MAC */
43126d292d3SJohn Baldwin 	axf->Final(tag, &ctx);
432c0341432SJohn Baldwin 
43320c128daSJohn Baldwin 	error = 0;
434c0341432SJohn Baldwin 	if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
43526d292d3SJohn Baldwin 		u_char tag2[GMAC_DIGEST_LEN];
43620c128daSJohn Baldwin 
437c0341432SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen,
43826d292d3SJohn Baldwin 		    tag2);
43926d292d3SJohn Baldwin 		if (timingsafe_bcmp(tag, tag2, swa->sw_mlen) != 0)
44020c128daSJohn Baldwin 			error = EBADMSG;
44126d292d3SJohn Baldwin 		explicit_bzero(tag2, sizeof(tag2));
442c0341432SJohn Baldwin 	} else {
443c0341432SJohn Baldwin 		/* Inject the authentication data */
44426d292d3SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag);
445c0341432SJohn Baldwin 	}
44620c128daSJohn Baldwin 	explicit_bzero(blkbuf, sizeof(blkbuf));
44726d292d3SJohn Baldwin 	explicit_bzero(tag, sizeof(tag));
44820c128daSJohn Baldwin 	explicit_bzero(iv, sizeof(iv));
44920c128daSJohn Baldwin 	return (error);
450c0341432SJohn Baldwin }
451c0341432SJohn Baldwin 
452c0341432SJohn Baldwin static int
453c0341432SJohn Baldwin swcr_gcm(struct swcr_session *ses, struct cryptop *crp)
454c0341432SJohn Baldwin {
45526d292d3SJohn Baldwin 	uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))];
456c0341432SJohn Baldwin 	u_char *blk = (u_char *)blkbuf;
45726d292d3SJohn Baldwin 	u_char tag[GMAC_DIGEST_LEN];
4589c0e3d3aSJohn Baldwin 	struct crypto_buffer_cursor cc_in, cc_out;
45926d292d3SJohn Baldwin 	const u_char *inblk;
46026d292d3SJohn Baldwin 	u_char *outblk;
461b54d1284SJohn Baldwin 	const struct swcr_auth *swa;
462b54d1284SJohn Baldwin 	const struct swcr_encdec *swe;
463d8787d4fSMark Johnston 	const struct enc_xform *exf;
464b54d1284SJohn Baldwin 	void *ctx;
465c0341432SJohn Baldwin 	uint32_t *blkp;
46686be314dSJohn Baldwin 	size_t len;
46786be314dSJohn Baldwin 	int blksz, error, ivlen, r, resid;
468c0341432SJohn Baldwin 
469c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
470c0341432SJohn Baldwin 	swe = &ses->swcr_encdec;
471c0341432SJohn Baldwin 	exf = swe->sw_exf;
472ab91fb6cSJohn Baldwin 	blksz = GMAC_BLOCK_LEN;
473ab91fb6cSJohn Baldwin 	KASSERT(blksz == exf->native_blocksize,
474723d8764SJohn Baldwin 	    ("%s: blocksize mismatch", __func__));
475c0341432SJohn Baldwin 
476c0341432SJohn Baldwin 	if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0)
477c0341432SJohn Baldwin 		return (EINVAL);
478c0341432SJohn Baldwin 
479c0341432SJohn Baldwin 	ivlen = AES_GCM_IV_LEN;
480c0341432SJohn Baldwin 
481b54d1284SJohn Baldwin 	ctx = __builtin_alloca(exf->ctxsize);
482ab91fb6cSJohn Baldwin 	if (crp->crp_cipher_key != NULL)
483b54d1284SJohn Baldwin 		exf->setkey(ctx, crp->crp_cipher_key,
484ab91fb6cSJohn Baldwin 		    crypto_get_params(crp->crp_session)->csp_cipher_klen);
485b54d1284SJohn Baldwin 	else
486b54d1284SJohn Baldwin 		memcpy(ctx, swe->sw_ctx, exf->ctxsize);
487b54d1284SJohn Baldwin 	exf->reinit(ctx, crp->crp_iv, ivlen);
488c0341432SJohn Baldwin 
489c0341432SJohn Baldwin 	/* Supply MAC with AAD */
4909b774dc0SJohn Baldwin 	if (crp->crp_aad != NULL) {
4919b774dc0SJohn Baldwin 		len = rounddown(crp->crp_aad_length, blksz);
4929b774dc0SJohn Baldwin 		if (len != 0)
493b54d1284SJohn Baldwin 			exf->update(ctx, crp->crp_aad, len);
4949b774dc0SJohn Baldwin 		if (crp->crp_aad_length != len) {
4959b774dc0SJohn Baldwin 			memset(blk, 0, blksz);
4969b774dc0SJohn Baldwin 			memcpy(blk, (char *)crp->crp_aad + len,
4979b774dc0SJohn Baldwin 			    crp->crp_aad_length - len);
498b54d1284SJohn Baldwin 			exf->update(ctx, blk, blksz);
4999b774dc0SJohn Baldwin 		}
5009b774dc0SJohn Baldwin 	} else {
5019c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_in, &crp->crp_buf);
5029c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_in, crp->crp_aad_start);
5039b774dc0SJohn Baldwin 		for (resid = crp->crp_aad_length; resid >= blksz;
5049b774dc0SJohn Baldwin 		     resid -= len) {
50586be314dSJohn Baldwin 			inblk = crypto_cursor_segment(&cc_in, &len);
50626d292d3SJohn Baldwin 			if (len >= blksz) {
50726d292d3SJohn Baldwin 				len = rounddown(MIN(len, resid), blksz);
50826d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_in, len);
50926d292d3SJohn Baldwin 			} else {
51026d292d3SJohn Baldwin 				len = blksz;
5119c0e3d3aSJohn Baldwin 				crypto_cursor_copydata(&cc_in, len, blk);
51226d292d3SJohn Baldwin 				inblk = blk;
51326d292d3SJohn Baldwin 			}
514b54d1284SJohn Baldwin 			exf->update(ctx, inblk, len);
51526d292d3SJohn Baldwin 		}
51626d292d3SJohn Baldwin 		if (resid > 0) {
51726d292d3SJohn Baldwin 			memset(blk, 0, blksz);
51826d292d3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, resid, blk);
519b54d1284SJohn Baldwin 			exf->update(ctx, blk, blksz);
520c0341432SJohn Baldwin 		}
5219b774dc0SJohn Baldwin 	}
522c0341432SJohn Baldwin 
523c0341432SJohn Baldwin 	/* Do encryption with MAC */
5249c0e3d3aSJohn Baldwin 	crypto_cursor_init(&cc_in, &crp->crp_buf);
5259c0e3d3aSJohn Baldwin 	crypto_cursor_advance(&cc_in, crp->crp_payload_start);
5269c0e3d3aSJohn Baldwin 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
5279c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_out, &crp->crp_obuf);
5289c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_out, crp->crp_payload_output_start);
5299c0e3d3aSJohn Baldwin 	} else
5309c0e3d3aSJohn Baldwin 		cc_out = cc_in;
53126d292d3SJohn Baldwin 	for (resid = crp->crp_payload_length; resid >= blksz; resid -= blksz) {
53286be314dSJohn Baldwin 		inblk = crypto_cursor_segment(&cc_in, &len);
53386be314dSJohn Baldwin 		if (len < blksz) {
53426d292d3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, blksz, blk);
53526d292d3SJohn Baldwin 			inblk = blk;
536c0341432SJohn Baldwin 		} else {
53726d292d3SJohn Baldwin 			crypto_cursor_advance(&cc_in, blksz);
538c0341432SJohn Baldwin 		}
53926d292d3SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
54086be314dSJohn Baldwin 			outblk = crypto_cursor_segment(&cc_out, &len);
54186be314dSJohn Baldwin 			if (len < blksz)
54226d292d3SJohn Baldwin 				outblk = blk;
543b54d1284SJohn Baldwin 			exf->encrypt(ctx, inblk, outblk);
544b54d1284SJohn Baldwin 			exf->update(ctx, outblk, blksz);
54526d292d3SJohn Baldwin 			if (outblk == blk)
54626d292d3SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
54726d292d3SJohn Baldwin 			else
54826d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_out, blksz);
54926d292d3SJohn Baldwin 		} else {
550b54d1284SJohn Baldwin 			exf->update(ctx, inblk, blksz);
55126d292d3SJohn Baldwin 		}
55226d292d3SJohn Baldwin 	}
55326d292d3SJohn Baldwin 	if (resid > 0) {
55426d292d3SJohn Baldwin 		crypto_cursor_copydata(&cc_in, resid, blk);
55526d292d3SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
556b54d1284SJohn Baldwin 			exf->encrypt_last(ctx, blk, blk, resid);
55726d292d3SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
55826d292d3SJohn Baldwin 		}
559b54d1284SJohn Baldwin 		exf->update(ctx, blk, resid);
560c0341432SJohn Baldwin 	}
561c0341432SJohn Baldwin 
562c0341432SJohn Baldwin 	/* length block */
56326d292d3SJohn Baldwin 	memset(blk, 0, blksz);
564c0341432SJohn Baldwin 	blkp = (uint32_t *)blk + 1;
565c0341432SJohn Baldwin 	*blkp = htobe32(crp->crp_aad_length * 8);
566c0341432SJohn Baldwin 	blkp = (uint32_t *)blk + 3;
567c0341432SJohn Baldwin 	*blkp = htobe32(crp->crp_payload_length * 8);
568b54d1284SJohn Baldwin 	exf->update(ctx, blk, blksz);
569c0341432SJohn Baldwin 
570c0341432SJohn Baldwin 	/* Finalize MAC */
571b54d1284SJohn Baldwin 	exf->final(tag, ctx);
572c0341432SJohn Baldwin 
573c0341432SJohn Baldwin 	/* Validate tag */
57420c128daSJohn Baldwin 	error = 0;
575c0341432SJohn Baldwin 	if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
57626d292d3SJohn Baldwin 		u_char tag2[GMAC_DIGEST_LEN];
57720c128daSJohn Baldwin 
57826d292d3SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, tag2);
579c0341432SJohn Baldwin 
58026d292d3SJohn Baldwin 		r = timingsafe_bcmp(tag, tag2, swa->sw_mlen);
58126d292d3SJohn Baldwin 		explicit_bzero(tag2, sizeof(tag2));
58220c128daSJohn Baldwin 		if (r != 0) {
58320c128daSJohn Baldwin 			error = EBADMSG;
58420c128daSJohn Baldwin 			goto out;
58520c128daSJohn Baldwin 		}
586c0341432SJohn Baldwin 
587c0341432SJohn Baldwin 		/* tag matches, decrypt data */
5889c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_in, &crp->crp_buf);
5899c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_in, crp->crp_payload_start);
59026d292d3SJohn Baldwin 		for (resid = crp->crp_payload_length; resid > blksz;
59126d292d3SJohn Baldwin 		     resid -= blksz) {
59286be314dSJohn Baldwin 			inblk = crypto_cursor_segment(&cc_in, &len);
59386be314dSJohn Baldwin 			if (len < blksz) {
59426d292d3SJohn Baldwin 				crypto_cursor_copydata(&cc_in, blksz, blk);
59526d292d3SJohn Baldwin 				inblk = blk;
59686be314dSJohn Baldwin 			} else
59726d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_in, blksz);
59886be314dSJohn Baldwin 			outblk = crypto_cursor_segment(&cc_out, &len);
59986be314dSJohn Baldwin 			if (len < blksz)
60026d292d3SJohn Baldwin 				outblk = blk;
601b54d1284SJohn Baldwin 			exf->decrypt(ctx, inblk, outblk);
60226d292d3SJohn Baldwin 			if (outblk == blk)
60326d292d3SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
60426d292d3SJohn Baldwin 			else
60526d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_out, blksz);
60626d292d3SJohn Baldwin 		}
60726d292d3SJohn Baldwin 		if (resid > 0) {
60826d292d3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, resid, blk);
609b54d1284SJohn Baldwin 			exf->decrypt_last(ctx, blk, blk, resid);
61026d292d3SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
611c0341432SJohn Baldwin 		}
612c0341432SJohn Baldwin 	} else {
613c0341432SJohn Baldwin 		/* Inject the authentication data */
61426d292d3SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag);
615c0341432SJohn Baldwin 	}
616c0341432SJohn Baldwin 
61720c128daSJohn Baldwin out:
618b54d1284SJohn Baldwin 	explicit_bzero(ctx, exf->ctxsize);
61920c128daSJohn Baldwin 	explicit_bzero(blkbuf, sizeof(blkbuf));
62026d292d3SJohn Baldwin 	explicit_bzero(tag, sizeof(tag));
62120c128daSJohn Baldwin 
62220c128daSJohn Baldwin 	return (error);
623c0341432SJohn Baldwin }
624c0341432SJohn Baldwin 
6254361c4ebSJohn Baldwin static void
6264361c4ebSJohn Baldwin build_ccm_b0(const char *nonce, u_int nonce_length, u_int aad_length,
6274361c4ebSJohn Baldwin     u_int data_length, u_int tag_length, uint8_t *b0)
6284361c4ebSJohn Baldwin {
6294361c4ebSJohn Baldwin 	uint8_t *bp;
6304361c4ebSJohn Baldwin 	uint8_t flags, L;
6314361c4ebSJohn Baldwin 
6324361c4ebSJohn Baldwin 	KASSERT(nonce_length >= 7 && nonce_length <= 13,
6334361c4ebSJohn Baldwin 	    ("nonce_length must be between 7 and 13 bytes"));
6344361c4ebSJohn Baldwin 
6354361c4ebSJohn Baldwin 	/*
6364361c4ebSJohn Baldwin 	 * Need to determine the L field value.  This is the number of
6374361c4ebSJohn Baldwin 	 * bytes needed to specify the length of the message; the length
6384361c4ebSJohn Baldwin 	 * is whatever is left in the 16 bytes after specifying flags and
6394361c4ebSJohn Baldwin 	 * the nonce.
6404361c4ebSJohn Baldwin 	 */
6414361c4ebSJohn Baldwin 	L = 15 - nonce_length;
6424361c4ebSJohn Baldwin 
6434361c4ebSJohn Baldwin 	flags = ((aad_length > 0) << 6) +
6444361c4ebSJohn Baldwin 	    (((tag_length - 2) / 2) << 3) +
6454361c4ebSJohn Baldwin 	    L - 1;
6464361c4ebSJohn Baldwin 
6474361c4ebSJohn Baldwin 	/*
6484361c4ebSJohn Baldwin 	 * Now we need to set up the first block, which has flags, nonce,
6494361c4ebSJohn Baldwin 	 * and the message length.
6504361c4ebSJohn Baldwin 	 */
6514361c4ebSJohn Baldwin 	b0[0] = flags;
6524361c4ebSJohn Baldwin 	memcpy(b0 + 1, nonce, nonce_length);
6534361c4ebSJohn Baldwin 	bp = b0 + 1 + nonce_length;
6544361c4ebSJohn Baldwin 
6554361c4ebSJohn Baldwin 	/* Need to copy L' [aka L-1] bytes of data_length */
6564361c4ebSJohn Baldwin 	for (uint8_t *dst = b0 + CCM_CBC_BLOCK_LEN - 1; dst >= bp; dst--) {
6574361c4ebSJohn Baldwin 		*dst = data_length;
6584361c4ebSJohn Baldwin 		data_length >>= 8;
6594361c4ebSJohn Baldwin 	}
6604361c4ebSJohn Baldwin }
6614361c4ebSJohn Baldwin 
6624361c4ebSJohn Baldwin /* NB: OCF only supports AAD lengths < 2^32. */
6634361c4ebSJohn Baldwin static int
6644361c4ebSJohn Baldwin build_ccm_aad_length(u_int aad_length, uint8_t *blk)
6654361c4ebSJohn Baldwin {
6664361c4ebSJohn Baldwin 	if (aad_length < ((1 << 16) - (1 << 8))) {
6674361c4ebSJohn Baldwin 		be16enc(blk, aad_length);
6684361c4ebSJohn Baldwin 		return (sizeof(uint16_t));
6694361c4ebSJohn Baldwin 	} else {
6704361c4ebSJohn Baldwin 		blk[0] = 0xff;
6714361c4ebSJohn Baldwin 		blk[1] = 0xfe;
6724361c4ebSJohn Baldwin 		be32enc(blk + 2, aad_length);
6734361c4ebSJohn Baldwin 		return (2 + sizeof(uint32_t));
6744361c4ebSJohn Baldwin 	}
6754361c4ebSJohn Baldwin }
6764361c4ebSJohn Baldwin 
677c0341432SJohn Baldwin static int
678c0341432SJohn Baldwin swcr_ccm_cbc_mac(struct swcr_session *ses, struct cryptop *crp)
679c0341432SJohn Baldwin {
68026d292d3SJohn Baldwin 	u_char iv[AES_BLOCK_LEN];
6814361c4ebSJohn Baldwin 	u_char blk[CCM_CBC_BLOCK_LEN];
6824361c4ebSJohn Baldwin 	u_char tag[AES_CBC_MAC_HASH_LEN];
683c0341432SJohn Baldwin 	union authctx ctx;
684ae18720dSJohn Baldwin 	const struct crypto_session_params *csp;
685*6113a08bSJohn Baldwin 	const struct swcr_auth *swa;
686d8787d4fSMark Johnston 	const struct auth_hash *axf;
6874361c4ebSJohn Baldwin 	int error, ivlen, len;
688c0341432SJohn Baldwin 
689ae18720dSJohn Baldwin 	csp = crypto_get_params(crp->crp_session);
690c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
691c0341432SJohn Baldwin 	axf = swa->sw_axf;
692c0341432SJohn Baldwin 
693*6113a08bSJohn Baldwin 	if (crp->crp_auth_key != NULL) {
694*6113a08bSJohn Baldwin 		axf->Init(&ctx);
695*6113a08bSJohn Baldwin 		axf->Setkey(&ctx, crp->crp_auth_key, csp->csp_auth_klen);
696*6113a08bSJohn Baldwin 	} else
697*6113a08bSJohn Baldwin 		memcpy(&ctx, swa->sw_ictx, axf->ctxsize);
698c0341432SJohn Baldwin 
699c0341432SJohn Baldwin 	/* Initialize the IV */
700ae18720dSJohn Baldwin 	ivlen = csp->csp_ivlen;
70129fe41ddSJohn Baldwin 	crypto_read_iv(crp, iv);
702c0341432SJohn Baldwin 
7034361c4ebSJohn Baldwin 	/* Supply MAC with IV */
7044361c4ebSJohn Baldwin 	axf->Reinit(&ctx, crp->crp_iv, ivlen);
705c0341432SJohn Baldwin 
7064361c4ebSJohn Baldwin 	/* Supply MAC with b0. */
7074361c4ebSJohn Baldwin 	build_ccm_b0(crp->crp_iv, ivlen, crp->crp_payload_length, 0,
7084361c4ebSJohn Baldwin 	    swa->sw_mlen, blk);
7094361c4ebSJohn Baldwin 	axf->Update(&ctx, blk, CCM_CBC_BLOCK_LEN);
7104361c4ebSJohn Baldwin 
7114361c4ebSJohn Baldwin 	len = build_ccm_aad_length(crp->crp_payload_length, blk);
7124361c4ebSJohn Baldwin 	axf->Update(&ctx, blk, len);
7134361c4ebSJohn Baldwin 
7144361c4ebSJohn Baldwin 	crypto_apply(crp, crp->crp_payload_start, crp->crp_payload_length,
7154361c4ebSJohn Baldwin 	    axf->Update, &ctx);
716c0341432SJohn Baldwin 
717c0341432SJohn Baldwin 	/* Finalize MAC */
71826d292d3SJohn Baldwin 	axf->Final(tag, &ctx);
719c0341432SJohn Baldwin 
7204361c4ebSJohn Baldwin 	error = 0;
721c0341432SJohn Baldwin 	if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
72226d292d3SJohn Baldwin 		u_char tag2[AES_CBC_MAC_HASH_LEN];
72320c128daSJohn Baldwin 
724c0341432SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen,
72526d292d3SJohn Baldwin 		    tag2);
72626d292d3SJohn Baldwin 		if (timingsafe_bcmp(tag, tag2, swa->sw_mlen) != 0)
72720c128daSJohn Baldwin 			error = EBADMSG;
72826d292d3SJohn Baldwin 		explicit_bzero(tag2, sizeof(tag));
729c0341432SJohn Baldwin 	} else {
730c0341432SJohn Baldwin 		/* Inject the authentication data */
73126d292d3SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag);
732c0341432SJohn Baldwin 	}
73326d292d3SJohn Baldwin 	explicit_bzero(tag, sizeof(tag));
7344361c4ebSJohn Baldwin 	explicit_bzero(blk, sizeof(blk));
73520c128daSJohn Baldwin 	explicit_bzero(iv, sizeof(iv));
73620c128daSJohn Baldwin 	return (error);
737c0341432SJohn Baldwin }
738c0341432SJohn Baldwin 
739c0341432SJohn Baldwin static int
740c0341432SJohn Baldwin swcr_ccm(struct swcr_session *ses, struct cryptop *crp)
741c0341432SJohn Baldwin {
742ae18720dSJohn Baldwin 	const struct crypto_session_params *csp;
74326d292d3SJohn Baldwin 	uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))];
744c0341432SJohn Baldwin 	u_char *blk = (u_char *)blkbuf;
74526d292d3SJohn Baldwin 	u_char tag[AES_CBC_MAC_HASH_LEN];
7469c0e3d3aSJohn Baldwin 	struct crypto_buffer_cursor cc_in, cc_out;
74726d292d3SJohn Baldwin 	const u_char *inblk;
74826d292d3SJohn Baldwin 	u_char *outblk;
749b54d1284SJohn Baldwin 	const struct swcr_auth *swa;
750b54d1284SJohn Baldwin 	const struct swcr_encdec *swe;
751d8787d4fSMark Johnston 	const struct enc_xform *exf;
752b54d1284SJohn Baldwin 	void *ctx;
75386be314dSJohn Baldwin 	size_t len;
75426d292d3SJohn Baldwin 	int blksz, error, ivlen, r, resid;
755c0341432SJohn Baldwin 
756ae18720dSJohn Baldwin 	csp = crypto_get_params(crp->crp_session);
757c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
758c0341432SJohn Baldwin 	swe = &ses->swcr_encdec;
759c0341432SJohn Baldwin 	exf = swe->sw_exf;
760ab91fb6cSJohn Baldwin 	blksz = AES_BLOCK_LEN;
761ab91fb6cSJohn Baldwin 	KASSERT(blksz == exf->native_blocksize,
762723d8764SJohn Baldwin 	    ("%s: blocksize mismatch", __func__));
763c0341432SJohn Baldwin 
764ae18720dSJohn Baldwin 	if (crp->crp_payload_length > ccm_max_payload_length(csp))
765ae18720dSJohn Baldwin 		return (EMSGSIZE);
766ae18720dSJohn Baldwin 
767c0341432SJohn Baldwin 	if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0)
768c0341432SJohn Baldwin 		return (EINVAL);
769c0341432SJohn Baldwin 
770ae18720dSJohn Baldwin 	ivlen = csp->csp_ivlen;
771c0341432SJohn Baldwin 
772b54d1284SJohn Baldwin 	ctx = __builtin_alloca(exf->ctxsize);
773ab91fb6cSJohn Baldwin 	if (crp->crp_cipher_key != NULL)
774b54d1284SJohn Baldwin 		exf->setkey(ctx, crp->crp_cipher_key,
775ab91fb6cSJohn Baldwin 		    crypto_get_params(crp->crp_session)->csp_cipher_klen);
776b54d1284SJohn Baldwin 	else
777b54d1284SJohn Baldwin 		memcpy(ctx, swe->sw_ctx, exf->ctxsize);
778b54d1284SJohn Baldwin 	exf->reinit(ctx, crp->crp_iv, ivlen);
779c0341432SJohn Baldwin 
7804361c4ebSJohn Baldwin 	/* Supply MAC with b0. */
7814361c4ebSJohn Baldwin 	_Static_assert(sizeof(blkbuf) >= CCM_CBC_BLOCK_LEN,
7824361c4ebSJohn Baldwin 	    "blkbuf too small for b0");
7834361c4ebSJohn Baldwin 	build_ccm_b0(crp->crp_iv, ivlen, crp->crp_aad_length,
7844361c4ebSJohn Baldwin 	    crp->crp_payload_length, swa->sw_mlen, blk);
785b54d1284SJohn Baldwin 	exf->update(ctx, blk, CCM_CBC_BLOCK_LEN);
7864361c4ebSJohn Baldwin 
787c0341432SJohn Baldwin 	/* Supply MAC with AAD */
7884361c4ebSJohn Baldwin 	if (crp->crp_aad_length != 0) {
7894361c4ebSJohn Baldwin 		len = build_ccm_aad_length(crp->crp_aad_length, blk);
790b54d1284SJohn Baldwin 		exf->update(ctx, blk, len);
7919b774dc0SJohn Baldwin 		if (crp->crp_aad != NULL)
792b54d1284SJohn Baldwin 			exf->update(ctx, crp->crp_aad, crp->crp_aad_length);
7939b774dc0SJohn Baldwin 		else
7944361c4ebSJohn Baldwin 			crypto_apply(crp, crp->crp_aad_start,
795b54d1284SJohn Baldwin 			    crp->crp_aad_length, exf->update, ctx);
7964361c4ebSJohn Baldwin 
7974361c4ebSJohn Baldwin 		/* Pad the AAD (including length field) to a full block. */
7984361c4ebSJohn Baldwin 		len = (len + crp->crp_aad_length) % CCM_CBC_BLOCK_LEN;
7994361c4ebSJohn Baldwin 		if (len != 0) {
8004361c4ebSJohn Baldwin 			len = CCM_CBC_BLOCK_LEN - len;
8014361c4ebSJohn Baldwin 			memset(blk, 0, CCM_CBC_BLOCK_LEN);
802b54d1284SJohn Baldwin 			exf->update(ctx, blk, len);
8034361c4ebSJohn Baldwin 		}
8044361c4ebSJohn Baldwin 	}
805c0341432SJohn Baldwin 
806c0341432SJohn Baldwin 	/* Do encryption/decryption with MAC */
8079c0e3d3aSJohn Baldwin 	crypto_cursor_init(&cc_in, &crp->crp_buf);
8089c0e3d3aSJohn Baldwin 	crypto_cursor_advance(&cc_in, crp->crp_payload_start);
8099c0e3d3aSJohn Baldwin 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
8109c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_out, &crp->crp_obuf);
8119c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_out, crp->crp_payload_output_start);
8129c0e3d3aSJohn Baldwin 	} else
8139c0e3d3aSJohn Baldwin 		cc_out = cc_in;
81426d292d3SJohn Baldwin 	for (resid = crp->crp_payload_length; resid >= blksz; resid -= blksz) {
81586be314dSJohn Baldwin 		inblk = crypto_cursor_segment(&cc_in, &len);
81686be314dSJohn Baldwin 		if (len < blksz) {
81726d292d3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, blksz, blk);
81826d292d3SJohn Baldwin 			inblk = blk;
81986be314dSJohn Baldwin 		} else
82026d292d3SJohn Baldwin 			crypto_cursor_advance(&cc_in, blksz);
821c0341432SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
82286be314dSJohn Baldwin 			outblk = crypto_cursor_segment(&cc_out, &len);
82386be314dSJohn Baldwin 			if (len < blksz)
82426d292d3SJohn Baldwin 				outblk = blk;
825b54d1284SJohn Baldwin 			exf->update(ctx, inblk, blksz);
826b54d1284SJohn Baldwin 			exf->encrypt(ctx, inblk, outblk);
82726d292d3SJohn Baldwin 			if (outblk == blk)
82826d292d3SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
82926d292d3SJohn Baldwin 			else
83026d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_out, blksz);
831c0341432SJohn Baldwin 		} else {
832c0341432SJohn Baldwin 			/*
833c0341432SJohn Baldwin 			 * One of the problems with CCM+CBC is that
834c0341432SJohn Baldwin 			 * the authentication is done on the
83526d292d3SJohn Baldwin 			 * unencrypted data.  As a result, we have to
836c0341432SJohn Baldwin 			 * decrypt the data twice: once to generate
837c0341432SJohn Baldwin 			 * the tag and a second time after the tag is
838c0341432SJohn Baldwin 			 * verified.
839c0341432SJohn Baldwin 			 */
840b54d1284SJohn Baldwin 			exf->decrypt(ctx, inblk, blk);
841b54d1284SJohn Baldwin 			exf->update(ctx, blk, blksz);
84226d292d3SJohn Baldwin 		}
84326d292d3SJohn Baldwin 	}
84426d292d3SJohn Baldwin 	if (resid > 0) {
84526d292d3SJohn Baldwin 		crypto_cursor_copydata(&cc_in, resid, blk);
84626d292d3SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
847b54d1284SJohn Baldwin 			exf->update(ctx, blk, resid);
848b54d1284SJohn Baldwin 			exf->encrypt_last(ctx, blk, blk, resid);
84926d292d3SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
85026d292d3SJohn Baldwin 		} else {
851b54d1284SJohn Baldwin 			exf->decrypt_last(ctx, blk, blk, resid);
852b54d1284SJohn Baldwin 			exf->update(ctx, blk, resid);
853c0341432SJohn Baldwin 		}
85408fca7a5SJohn-Mark Gurney 	}
85508fca7a5SJohn-Mark Gurney 
85608fca7a5SJohn-Mark Gurney 	/* Finalize MAC */
857b54d1284SJohn Baldwin 	exf->final(tag, ctx);
85808fca7a5SJohn-Mark Gurney 
85908fca7a5SJohn-Mark Gurney 	/* Validate tag */
86020c128daSJohn Baldwin 	error = 0;
861c0341432SJohn Baldwin 	if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
86226d292d3SJohn Baldwin 		u_char tag2[AES_CBC_MAC_HASH_LEN];
86320c128daSJohn Baldwin 
864c0341432SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen,
86526d292d3SJohn Baldwin 		    tag2);
86608fca7a5SJohn-Mark Gurney 
86726d292d3SJohn Baldwin 		r = timingsafe_bcmp(tag, tag2, swa->sw_mlen);
86826d292d3SJohn Baldwin 		explicit_bzero(tag2, sizeof(tag2));
86920c128daSJohn Baldwin 		if (r != 0) {
87020c128daSJohn Baldwin 			error = EBADMSG;
87120c128daSJohn Baldwin 			goto out;
87220c128daSJohn Baldwin 		}
873c0341432SJohn Baldwin 
87408fca7a5SJohn-Mark Gurney 		/* tag matches, decrypt data */
875b54d1284SJohn Baldwin 		exf->reinit(ctx, crp->crp_iv, ivlen);
8769c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_in, &crp->crp_buf);
8779c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_in, crp->crp_payload_start);
87826d292d3SJohn Baldwin 		for (resid = crp->crp_payload_length; resid > blksz;
87926d292d3SJohn Baldwin 		     resid -= blksz) {
88086be314dSJohn Baldwin 			inblk = crypto_cursor_segment(&cc_in, &len);
88186be314dSJohn Baldwin 			if (len < blksz) {
88226d292d3SJohn Baldwin 				crypto_cursor_copydata(&cc_in, blksz, blk);
88326d292d3SJohn Baldwin 				inblk = blk;
88486be314dSJohn Baldwin 			} else
88526d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_in, blksz);
88686be314dSJohn Baldwin 			outblk = crypto_cursor_segment(&cc_out, &len);
88786be314dSJohn Baldwin 			if (len < blksz)
88826d292d3SJohn Baldwin 				outblk = blk;
889b54d1284SJohn Baldwin 			exf->decrypt(ctx, inblk, outblk);
89026d292d3SJohn Baldwin 			if (outblk == blk)
89126d292d3SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
89226d292d3SJohn Baldwin 			else
89326d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_out, blksz);
89426d292d3SJohn Baldwin 		}
89526d292d3SJohn Baldwin 		if (resid > 0) {
89626d292d3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, resid, blk);
897b54d1284SJohn Baldwin 			exf->decrypt_last(ctx, blk, blk, resid);
89826d292d3SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
89908fca7a5SJohn-Mark Gurney 		}
90008fca7a5SJohn-Mark Gurney 	} else {
90108fca7a5SJohn-Mark Gurney 		/* Inject the authentication data */
90226d292d3SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag);
90308fca7a5SJohn-Mark Gurney 	}
90408fca7a5SJohn-Mark Gurney 
90520c128daSJohn Baldwin out:
906b54d1284SJohn Baldwin 	explicit_bzero(ctx, exf->ctxsize);
90720c128daSJohn Baldwin 	explicit_bzero(blkbuf, sizeof(blkbuf));
90826d292d3SJohn Baldwin 	explicit_bzero(tag, sizeof(tag));
90920c128daSJohn Baldwin 	return (error);
91008fca7a5SJohn-Mark Gurney }
91108fca7a5SJohn-Mark Gurney 
912dd2e1352SJohn Baldwin static int
913dd2e1352SJohn Baldwin swcr_chacha20_poly1305(struct swcr_session *ses, struct cryptop *crp)
914dd2e1352SJohn Baldwin {
915dd2e1352SJohn Baldwin 	const struct crypto_session_params *csp;
916dd2e1352SJohn Baldwin 	uint64_t blkbuf[howmany(CHACHA20_NATIVE_BLOCK_LEN, sizeof(uint64_t))];
917dd2e1352SJohn Baldwin 	u_char *blk = (u_char *)blkbuf;
918dd2e1352SJohn Baldwin 	u_char tag[POLY1305_HASH_LEN];
919dd2e1352SJohn Baldwin 	struct crypto_buffer_cursor cc_in, cc_out;
920dd2e1352SJohn Baldwin 	const u_char *inblk;
921dd2e1352SJohn Baldwin 	u_char *outblk;
922dd2e1352SJohn Baldwin 	uint64_t *blkp;
923b54d1284SJohn Baldwin 	const struct swcr_auth *swa;
924b54d1284SJohn Baldwin 	const struct swcr_encdec *swe;
925d8787d4fSMark Johnston 	const struct enc_xform *exf;
926b54d1284SJohn Baldwin 	void *ctx;
92786be314dSJohn Baldwin 	size_t len;
928dd2e1352SJohn Baldwin 	int blksz, error, r, resid;
929dd2e1352SJohn Baldwin 
930dd2e1352SJohn Baldwin 	swa = &ses->swcr_auth;
931dd2e1352SJohn Baldwin 	swe = &ses->swcr_encdec;
932dd2e1352SJohn Baldwin 	exf = swe->sw_exf;
933dd2e1352SJohn Baldwin 	blksz = exf->native_blocksize;
934dd2e1352SJohn Baldwin 	KASSERT(blksz <= sizeof(blkbuf), ("%s: blocksize mismatch", __func__));
935dd2e1352SJohn Baldwin 
936dd2e1352SJohn Baldwin 	if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0)
937dd2e1352SJohn Baldwin 		return (EINVAL);
938dd2e1352SJohn Baldwin 
939dd2e1352SJohn Baldwin 	csp = crypto_get_params(crp->crp_session);
940dd2e1352SJohn Baldwin 
941b54d1284SJohn Baldwin 	ctx = __builtin_alloca(exf->ctxsize);
942dd2e1352SJohn Baldwin 	if (crp->crp_cipher_key != NULL)
943b54d1284SJohn Baldwin 		exf->setkey(ctx, crp->crp_cipher_key,
944dd2e1352SJohn Baldwin 		    csp->csp_cipher_klen);
945b54d1284SJohn Baldwin 	else
946b54d1284SJohn Baldwin 		memcpy(ctx, swe->sw_ctx, exf->ctxsize);
947b54d1284SJohn Baldwin 	exf->reinit(ctx, crp->crp_iv, csp->csp_ivlen);
948dd2e1352SJohn Baldwin 
949ab91fb6cSJohn Baldwin 	/* Supply MAC with AAD */
950ab91fb6cSJohn Baldwin 	if (crp->crp_aad != NULL)
951b54d1284SJohn Baldwin 		exf->update(ctx, crp->crp_aad, crp->crp_aad_length);
952ab91fb6cSJohn Baldwin 	else
953b54d1284SJohn Baldwin 		crypto_apply(crp, crp->crp_aad_start, crp->crp_aad_length,
954b54d1284SJohn Baldwin 		    exf->update, ctx);
955ab91fb6cSJohn Baldwin 	if (crp->crp_aad_length % 16 != 0) {
956ab91fb6cSJohn Baldwin 		/* padding1 */
957ab91fb6cSJohn Baldwin 		memset(blk, 0, 16);
958b54d1284SJohn Baldwin 		exf->update(ctx, blk, 16 - crp->crp_aad_length % 16);
959ab91fb6cSJohn Baldwin 	}
960ab91fb6cSJohn Baldwin 
961dd2e1352SJohn Baldwin 	/* Do encryption with MAC */
962dd2e1352SJohn Baldwin 	crypto_cursor_init(&cc_in, &crp->crp_buf);
963dd2e1352SJohn Baldwin 	crypto_cursor_advance(&cc_in, crp->crp_payload_start);
964dd2e1352SJohn Baldwin 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
965dd2e1352SJohn Baldwin 		crypto_cursor_init(&cc_out, &crp->crp_obuf);
966dd2e1352SJohn Baldwin 		crypto_cursor_advance(&cc_out, crp->crp_payload_output_start);
967dd2e1352SJohn Baldwin 	} else
968dd2e1352SJohn Baldwin 		cc_out = cc_in;
969dd2e1352SJohn Baldwin 	for (resid = crp->crp_payload_length; resid >= blksz; resid -= blksz) {
97086be314dSJohn Baldwin 		inblk = crypto_cursor_segment(&cc_in, &len);
97186be314dSJohn Baldwin 		if (len < blksz) {
972dd2e1352SJohn Baldwin 			crypto_cursor_copydata(&cc_in, blksz, blk);
973dd2e1352SJohn Baldwin 			inblk = blk;
97486be314dSJohn Baldwin 		} else
975dd2e1352SJohn Baldwin 			crypto_cursor_advance(&cc_in, blksz);
976dd2e1352SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
97786be314dSJohn Baldwin 			outblk = crypto_cursor_segment(&cc_out, &len);
97886be314dSJohn Baldwin 			if (len < blksz)
979dd2e1352SJohn Baldwin 				outblk = blk;
980b54d1284SJohn Baldwin 			exf->encrypt(ctx, inblk, outblk);
981b54d1284SJohn Baldwin 			exf->update(ctx, outblk, blksz);
982dd2e1352SJohn Baldwin 			if (outblk == blk)
983dd2e1352SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
984dd2e1352SJohn Baldwin 			else
985dd2e1352SJohn Baldwin 				crypto_cursor_advance(&cc_out, blksz);
986dd2e1352SJohn Baldwin 		} else {
987b54d1284SJohn Baldwin 			exf->update(ctx, inblk, blksz);
988dd2e1352SJohn Baldwin 		}
989dd2e1352SJohn Baldwin 	}
990dd2e1352SJohn Baldwin 	if (resid > 0) {
991dd2e1352SJohn Baldwin 		crypto_cursor_copydata(&cc_in, resid, blk);
992dd2e1352SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
993b54d1284SJohn Baldwin 			exf->encrypt_last(ctx, blk, blk, resid);
994dd2e1352SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
995dd2e1352SJohn Baldwin 		}
996b54d1284SJohn Baldwin 		exf->update(ctx, blk, resid);
997dd2e1352SJohn Baldwin 		if (resid % 16 != 0) {
998dd2e1352SJohn Baldwin 			/* padding2 */
999dd2e1352SJohn Baldwin 			memset(blk, 0, 16);
1000b54d1284SJohn Baldwin 			exf->update(ctx, blk, 16 - resid % 16);
1001dd2e1352SJohn Baldwin 		}
1002dd2e1352SJohn Baldwin 	}
1003dd2e1352SJohn Baldwin 
1004dd2e1352SJohn Baldwin 	/* lengths */
1005dd2e1352SJohn Baldwin 	blkp = (uint64_t *)blk;
1006dd2e1352SJohn Baldwin 	blkp[0] = htole64(crp->crp_aad_length);
1007dd2e1352SJohn Baldwin 	blkp[1] = htole64(crp->crp_payload_length);
1008b54d1284SJohn Baldwin 	exf->update(ctx, blk, sizeof(uint64_t) * 2);
1009dd2e1352SJohn Baldwin 
1010dd2e1352SJohn Baldwin 	/* Finalize MAC */
1011b54d1284SJohn Baldwin 	exf->final(tag, ctx);
1012dd2e1352SJohn Baldwin 
1013dd2e1352SJohn Baldwin 	/* Validate tag */
1014dd2e1352SJohn Baldwin 	error = 0;
1015dd2e1352SJohn Baldwin 	if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
1016dd2e1352SJohn Baldwin 		u_char tag2[POLY1305_HASH_LEN];
1017dd2e1352SJohn Baldwin 
1018dd2e1352SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, tag2);
1019dd2e1352SJohn Baldwin 
1020dd2e1352SJohn Baldwin 		r = timingsafe_bcmp(tag, tag2, swa->sw_mlen);
1021dd2e1352SJohn Baldwin 		explicit_bzero(tag2, sizeof(tag2));
1022dd2e1352SJohn Baldwin 		if (r != 0) {
1023dd2e1352SJohn Baldwin 			error = EBADMSG;
1024dd2e1352SJohn Baldwin 			goto out;
1025dd2e1352SJohn Baldwin 		}
1026dd2e1352SJohn Baldwin 
1027dd2e1352SJohn Baldwin 		/* tag matches, decrypt data */
1028dd2e1352SJohn Baldwin 		crypto_cursor_init(&cc_in, &crp->crp_buf);
1029dd2e1352SJohn Baldwin 		crypto_cursor_advance(&cc_in, crp->crp_payload_start);
1030dd2e1352SJohn Baldwin 		for (resid = crp->crp_payload_length; resid > blksz;
1031dd2e1352SJohn Baldwin 		     resid -= blksz) {
103286be314dSJohn Baldwin 			inblk = crypto_cursor_segment(&cc_in, &len);
103386be314dSJohn Baldwin 			if (len < blksz) {
1034dd2e1352SJohn Baldwin 				crypto_cursor_copydata(&cc_in, blksz, blk);
1035dd2e1352SJohn Baldwin 				inblk = blk;
103686be314dSJohn Baldwin 			} else
1037dd2e1352SJohn Baldwin 				crypto_cursor_advance(&cc_in, blksz);
103886be314dSJohn Baldwin 			outblk = crypto_cursor_segment(&cc_out, &len);
103986be314dSJohn Baldwin 			if (len < blksz)
1040dd2e1352SJohn Baldwin 				outblk = blk;
1041b54d1284SJohn Baldwin 			exf->decrypt(ctx, inblk, outblk);
1042dd2e1352SJohn Baldwin 			if (outblk == blk)
1043dd2e1352SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
1044dd2e1352SJohn Baldwin 			else
1045dd2e1352SJohn Baldwin 				crypto_cursor_advance(&cc_out, blksz);
1046dd2e1352SJohn Baldwin 		}
1047dd2e1352SJohn Baldwin 		if (resid > 0) {
1048dd2e1352SJohn Baldwin 			crypto_cursor_copydata(&cc_in, resid, blk);
1049b54d1284SJohn Baldwin 			exf->decrypt_last(ctx, blk, blk, resid);
1050dd2e1352SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
1051dd2e1352SJohn Baldwin 		}
1052dd2e1352SJohn Baldwin 	} else {
1053dd2e1352SJohn Baldwin 		/* Inject the authentication data */
1054dd2e1352SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag);
1055dd2e1352SJohn Baldwin 	}
1056dd2e1352SJohn Baldwin 
1057dd2e1352SJohn Baldwin out:
1058b54d1284SJohn Baldwin 	explicit_bzero(ctx, exf->ctxsize);
1059dd2e1352SJohn Baldwin 	explicit_bzero(blkbuf, sizeof(blkbuf));
1060dd2e1352SJohn Baldwin 	explicit_bzero(tag, sizeof(tag));
1061dd2e1352SJohn Baldwin 	return (error);
1062dd2e1352SJohn Baldwin }
1063dd2e1352SJohn Baldwin 
1064091d81d1SSam Leffler /*
1065c0341432SJohn Baldwin  * Apply a cipher and a digest to perform EtA.
1066c0341432SJohn Baldwin  */
1067c0341432SJohn Baldwin static int
1068c0341432SJohn Baldwin swcr_eta(struct swcr_session *ses, struct cryptop *crp)
1069c0341432SJohn Baldwin {
1070c0341432SJohn Baldwin 	int error;
1071c0341432SJohn Baldwin 
1072c0341432SJohn Baldwin 	if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
1073c0341432SJohn Baldwin 		error = swcr_encdec(ses, crp);
1074c0341432SJohn Baldwin 		if (error == 0)
1075c0341432SJohn Baldwin 			error = swcr_authcompute(ses, crp);
1076c0341432SJohn Baldwin 	} else {
1077c0341432SJohn Baldwin 		error = swcr_authcompute(ses, crp);
1078c0341432SJohn Baldwin 		if (error == 0)
1079c0341432SJohn Baldwin 			error = swcr_encdec(ses, crp);
1080c0341432SJohn Baldwin 	}
1081c0341432SJohn Baldwin 	return (error);
1082c0341432SJohn Baldwin }
1083c0341432SJohn Baldwin 
1084c0341432SJohn Baldwin /*
1085091d81d1SSam Leffler  * Apply a compression/decompression algorithm
1086091d81d1SSam Leffler  */
1087091d81d1SSam Leffler static int
1088c0341432SJohn Baldwin swcr_compdec(struct swcr_session *ses, struct cryptop *crp)
1089091d81d1SSam Leffler {
1090d8787d4fSMark Johnston 	const struct comp_algo *cxf;
1091d3d79e96SJohn Baldwin 	uint8_t *data, *out;
1092091d81d1SSam Leffler 	int adj;
1093d3d79e96SJohn Baldwin 	uint32_t result;
1094091d81d1SSam Leffler 
1095c0341432SJohn Baldwin 	cxf = ses->swcr_compdec.sw_cxf;
1096091d81d1SSam Leffler 
1097091d81d1SSam Leffler 	/* We must handle the whole buffer of data in one time
1098091d81d1SSam Leffler 	 * then if there is not all the data in the mbuf, we must
1099091d81d1SSam Leffler 	 * copy in a buffer.
1100091d81d1SSam Leffler 	 */
1101091d81d1SSam Leffler 
1102c0341432SJohn Baldwin 	data = malloc(crp->crp_payload_length, M_CRYPTO_DATA,  M_NOWAIT);
1103091d81d1SSam Leffler 	if (data == NULL)
1104091d81d1SSam Leffler 		return (EINVAL);
1105c0341432SJohn Baldwin 	crypto_copydata(crp, crp->crp_payload_start, crp->crp_payload_length,
1106c0341432SJohn Baldwin 	    data);
1107091d81d1SSam Leffler 
1108c0341432SJohn Baldwin 	if (CRYPTO_OP_IS_COMPRESS(crp->crp_op))
1109c0341432SJohn Baldwin 		result = cxf->compress(data, crp->crp_payload_length, &out);
1110091d81d1SSam Leffler 	else
1111c0341432SJohn Baldwin 		result = cxf->decompress(data, crp->crp_payload_length, &out);
1112091d81d1SSam Leffler 
11131ede983cSDag-Erling Smørgrav 	free(data, M_CRYPTO_DATA);
1114091d81d1SSam Leffler 	if (result == 0)
1115c0341432SJohn Baldwin 		return (EINVAL);
1116c0341432SJohn Baldwin 	crp->crp_olen = result;
1117c0341432SJohn Baldwin 
1118c0341432SJohn Baldwin 	/* Check the compressed size when doing compression */
1119c0341432SJohn Baldwin 	if (CRYPTO_OP_IS_COMPRESS(crp->crp_op)) {
1120c0341432SJohn Baldwin 		if (result >= crp->crp_payload_length) {
1121c0341432SJohn Baldwin 			/* Compression was useless, we lost time */
1122c0341432SJohn Baldwin 			free(out, M_CRYPTO_DATA);
1123c0341432SJohn Baldwin 			return (0);
1124c0341432SJohn Baldwin 		}
1125c0341432SJohn Baldwin 	}
1126091d81d1SSam Leffler 
1127091d81d1SSam Leffler 	/* Copy back the (de)compressed data. m_copyback is
1128091d81d1SSam Leffler 	 * extending the mbuf as necessary.
1129091d81d1SSam Leffler 	 */
1130c0341432SJohn Baldwin 	crypto_copyback(crp, crp->crp_payload_start, result, out);
1131c0341432SJohn Baldwin 	if (result < crp->crp_payload_length) {
11329c0e3d3aSJohn Baldwin 		switch (crp->crp_buf.cb_type) {
1133c0341432SJohn Baldwin 		case CRYPTO_BUF_MBUF:
1134883a0196SJohn Baldwin 		case CRYPTO_BUF_SINGLE_MBUF:
1135c0341432SJohn Baldwin 			adj = result - crp->crp_payload_length;
11369c0e3d3aSJohn Baldwin 			m_adj(crp->crp_buf.cb_mbuf, adj);
1137c0341432SJohn Baldwin 			break;
1138c0341432SJohn Baldwin 		case CRYPTO_BUF_UIO: {
11399c0e3d3aSJohn Baldwin 			struct uio *uio = crp->crp_buf.cb_uio;
1140091d81d1SSam Leffler 			int ind;
1141091d81d1SSam Leffler 
1142c0341432SJohn Baldwin 			adj = crp->crp_payload_length - result;
1143091d81d1SSam Leffler 			ind = uio->uio_iovcnt - 1;
1144091d81d1SSam Leffler 
1145091d81d1SSam Leffler 			while (adj > 0 && ind >= 0) {
1146091d81d1SSam Leffler 				if (adj < uio->uio_iov[ind].iov_len) {
1147091d81d1SSam Leffler 					uio->uio_iov[ind].iov_len -= adj;
1148091d81d1SSam Leffler 					break;
1149091d81d1SSam Leffler 				}
1150091d81d1SSam Leffler 
1151091d81d1SSam Leffler 				adj -= uio->uio_iov[ind].iov_len;
1152091d81d1SSam Leffler 				uio->uio_iov[ind].iov_len = 0;
1153091d81d1SSam Leffler 				ind--;
1154091d81d1SSam Leffler 				uio->uio_iovcnt--;
1155091d81d1SSam Leffler 			}
1156091d81d1SSam Leffler 			}
1157c0341432SJohn Baldwin 			break;
1158e6f6d0c9SAlan Somers 		case CRYPTO_BUF_VMPAGE:
1159e6f6d0c9SAlan Somers 			adj = crp->crp_payload_length - result;
1160e6f6d0c9SAlan Somers 			crp->crp_buf.cb_vm_page_len -= adj;
1161e6f6d0c9SAlan Somers 			break;
11629c0e3d3aSJohn Baldwin 		default:
11639c0e3d3aSJohn Baldwin 			break;
1164c0341432SJohn Baldwin 		}
1165091d81d1SSam Leffler 	}
11661ede983cSDag-Erling Smørgrav 	free(out, M_CRYPTO_DATA);
1167091d81d1SSam Leffler 	return 0;
1168091d81d1SSam Leffler }
1169091d81d1SSam Leffler 
1170091d81d1SSam Leffler static int
11713e947048SJohn Baldwin swcr_setup_cipher(struct swcr_session *ses,
1172c0341432SJohn Baldwin     const struct crypto_session_params *csp)
1173091d81d1SSam Leffler {
1174c0341432SJohn Baldwin 	struct swcr_encdec *swe;
1175d8787d4fSMark Johnston 	const struct enc_xform *txf;
1176f6c4bc3bSPawel Jakub Dawidek 	int error;
1177091d81d1SSam Leffler 
1178c0341432SJohn Baldwin 	swe = &ses->swcr_encdec;
1179c0341432SJohn Baldwin 	txf = crypto_cipher(csp);
1180b54d1284SJohn Baldwin 	if (csp->csp_cipher_key != NULL) {
11813e947048SJohn Baldwin 		if (txf->ctxsize != 0) {
1182f313909aSJohn Baldwin 			swe->sw_ctx = malloc(txf->ctxsize, M_CRYPTO_DATA,
11833e947048SJohn Baldwin 			    M_NOWAIT);
1184f313909aSJohn Baldwin 			if (swe->sw_ctx == NULL)
11853e947048SJohn Baldwin 				return (ENOMEM);
11863e947048SJohn Baldwin 		}
1187f313909aSJohn Baldwin 		error = txf->setkey(swe->sw_ctx,
1188c0341432SJohn Baldwin 		    csp->csp_cipher_key, csp->csp_cipher_klen);
1189c0341432SJohn Baldwin 		if (error)
1190c0341432SJohn Baldwin 			return (error);
1191091d81d1SSam Leffler 	}
1192c0341432SJohn Baldwin 	swe->sw_exf = txf;
1193c0341432SJohn Baldwin 	return (0);
1194f6c4bc3bSPawel Jakub Dawidek }
1195091d81d1SSam Leffler 
1196c0341432SJohn Baldwin static int
1197c0341432SJohn Baldwin swcr_setup_auth(struct swcr_session *ses,
1198c0341432SJohn Baldwin     const struct crypto_session_params *csp)
1199c0341432SJohn Baldwin {
1200c0341432SJohn Baldwin 	struct swcr_auth *swa;
1201d8787d4fSMark Johnston 	const struct auth_hash *axf;
1202c0341432SJohn Baldwin 
1203c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
1204c0341432SJohn Baldwin 
1205c0341432SJohn Baldwin 	axf = crypto_auth_hash(csp);
1206c0341432SJohn Baldwin 	swa->sw_axf = axf;
1207c0341432SJohn Baldwin 	if (csp->csp_auth_mlen < 0 || csp->csp_auth_mlen > axf->hashsize)
1208c0341432SJohn Baldwin 		return (EINVAL);
1209c0341432SJohn Baldwin 	if (csp->csp_auth_mlen == 0)
1210c0341432SJohn Baldwin 		swa->sw_mlen = axf->hashsize;
1211c0341432SJohn Baldwin 	else
1212c0341432SJohn Baldwin 		swa->sw_mlen = csp->csp_auth_mlen;
1213*6113a08bSJohn Baldwin 	if (csp->csp_auth_klen == 0 || csp->csp_auth_key != NULL) {
1214*6113a08bSJohn Baldwin 		swa->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
1215*6113a08bSJohn Baldwin 		    M_NOWAIT);
1216c0341432SJohn Baldwin 		if (swa->sw_ictx == NULL)
1217c0341432SJohn Baldwin 			return (ENOBUFS);
1218*6113a08bSJohn Baldwin 	}
1219c0341432SJohn Baldwin 
1220c0341432SJohn Baldwin 	switch (csp->csp_auth_alg) {
1221091d81d1SSam Leffler 	case CRYPTO_SHA1_HMAC:
1222c97f39ceSConrad Meyer 	case CRYPTO_SHA2_224_HMAC:
1223f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_256_HMAC:
1224f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_384_HMAC:
1225f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_512_HMAC:
1226091d81d1SSam Leffler 	case CRYPTO_NULL_HMAC:
1227091d81d1SSam Leffler 	case CRYPTO_RIPEMD160_HMAC:
1228*6113a08bSJohn Baldwin 		swa->sw_hmac = true;
1229*6113a08bSJohn Baldwin 		if (csp->csp_auth_key != NULL) {
12303a0b6a93SJohn Baldwin 			swa->sw_octx = malloc(axf->ctxsize, M_CRYPTO_DATA,
1231091d81d1SSam Leffler 			    M_NOWAIT);
1232c0341432SJohn Baldwin 			if (swa->sw_octx == NULL)
1233c0341432SJohn Baldwin 				return (ENOBUFS);
1234*6113a08bSJohn Baldwin 			hmac_init_ipad(axf, csp->csp_auth_key,
1235*6113a08bSJohn Baldwin 			    csp->csp_auth_klen, swa->sw_ictx);
1236*6113a08bSJohn Baldwin 			hmac_init_opad(axf, csp->csp_auth_key,
1237*6113a08bSJohn Baldwin 			    csp->csp_auth_klen, swa->sw_octx);
1238091d81d1SSam Leffler 		}
1239091d81d1SSam Leffler 		break;
1240091d81d1SSam Leffler 	case CRYPTO_SHA1:
1241c4729f6eSConrad Meyer 	case CRYPTO_SHA2_224:
1242c4729f6eSConrad Meyer 	case CRYPTO_SHA2_256:
1243c4729f6eSConrad Meyer 	case CRYPTO_SHA2_384:
1244c4729f6eSConrad Meyer 	case CRYPTO_SHA2_512:
1245c0341432SJohn Baldwin 		axf->Init(swa->sw_ictx);
1246c0341432SJohn Baldwin 		break;
1247c0341432SJohn Baldwin 	case CRYPTO_AES_NIST_GMAC:
1248*6113a08bSJohn Baldwin 	case CRYPTO_AES_CCM_CBC_MAC:
1249*6113a08bSJohn Baldwin 	case CRYPTO_POLY1305:
1250*6113a08bSJohn Baldwin 		if (csp->csp_auth_key != NULL) {
1251c0341432SJohn Baldwin 			axf->Init(swa->sw_ictx);
1252c0341432SJohn Baldwin 			axf->Setkey(swa->sw_ictx, csp->csp_auth_key,
1253c0341432SJohn Baldwin 			    csp->csp_auth_klen);
1254*6113a08bSJohn Baldwin 		}
1255c0341432SJohn Baldwin 		break;
1256c0341432SJohn Baldwin 	case CRYPTO_BLAKE2B:
1257c0341432SJohn Baldwin 	case CRYPTO_BLAKE2S:
1258c0341432SJohn Baldwin 		/*
1259c0341432SJohn Baldwin 		 * Blake2b and Blake2s support an optional key but do
1260c0341432SJohn Baldwin 		 * not require one.
1261c0341432SJohn Baldwin 		 */
1262*6113a08bSJohn Baldwin 		if (csp->csp_auth_klen == 0)
1263*6113a08bSJohn Baldwin 			axf->Init(swa->sw_ictx);
1264*6113a08bSJohn Baldwin 		else if (csp->csp_auth_key != NULL)
1265c0341432SJohn Baldwin 			axf->Setkey(swa->sw_ictx, csp->csp_auth_key,
1266c0341432SJohn Baldwin 			    csp->csp_auth_klen);
1267*6113a08bSJohn Baldwin 		break;
1268*6113a08bSJohn Baldwin 	}
1269*6113a08bSJohn Baldwin 
1270*6113a08bSJohn Baldwin 	if (csp->csp_mode == CSP_MODE_DIGEST) {
1271*6113a08bSJohn Baldwin 		switch (csp->csp_auth_alg) {
1272*6113a08bSJohn Baldwin 		case CRYPTO_AES_NIST_GMAC:
1273*6113a08bSJohn Baldwin 			ses->swcr_process = swcr_gmac;
1274c0341432SJohn Baldwin 			break;
1275c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_CBC_MAC:
1276c0341432SJohn Baldwin 			ses->swcr_process = swcr_ccm_cbc_mac;
1277c0341432SJohn Baldwin 			break;
1278*6113a08bSJohn Baldwin 		default:
1279*6113a08bSJohn Baldwin 			ses->swcr_process = swcr_authcompute;
1280*6113a08bSJohn Baldwin 		}
1281091d81d1SSam Leffler 	}
1282091d81d1SSam Leffler 
1283c0341432SJohn Baldwin 	return (0);
1284c0341432SJohn Baldwin }
128508fca7a5SJohn-Mark Gurney 
1286c0341432SJohn Baldwin static int
1287ab91fb6cSJohn Baldwin swcr_setup_aead(struct swcr_session *ses,
1288c0341432SJohn Baldwin     const struct crypto_session_params *csp)
1289c0341432SJohn Baldwin {
1290c0341432SJohn Baldwin 	struct swcr_auth *swa;
1291ab91fb6cSJohn Baldwin 	int error;
1292c0341432SJohn Baldwin 
1293ab91fb6cSJohn Baldwin 	error = swcr_setup_cipher(ses, csp);
1294ab91fb6cSJohn Baldwin 	if (error)
1295ab91fb6cSJohn Baldwin 		return (error);
1296ab91fb6cSJohn Baldwin 
1297c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
1298c0341432SJohn Baldwin 	if (csp->csp_auth_mlen == 0)
1299ab91fb6cSJohn Baldwin 		swa->sw_mlen = ses->swcr_encdec.sw_exf->macsize;
1300c0341432SJohn Baldwin 	else
1301c0341432SJohn Baldwin 		swa->sw_mlen = csp->csp_auth_mlen;
1302ab91fb6cSJohn Baldwin 	return (0);
1303dd2e1352SJohn Baldwin }
1304dd2e1352SJohn Baldwin 
1305c0341432SJohn Baldwin static bool
1306c0341432SJohn Baldwin swcr_auth_supported(const struct crypto_session_params *csp)
1307109919c6SBenno Rice {
1308d8787d4fSMark Johnston 	const struct auth_hash *axf;
1309091d81d1SSam Leffler 
1310c0341432SJohn Baldwin 	axf = crypto_auth_hash(csp);
1311c0341432SJohn Baldwin 	if (axf == NULL)
1312c0341432SJohn Baldwin 		return (false);
1313c0341432SJohn Baldwin 	switch (csp->csp_auth_alg) {
1314091d81d1SSam Leffler 	case CRYPTO_SHA1_HMAC:
1315c97f39ceSConrad Meyer 	case CRYPTO_SHA2_224_HMAC:
1316f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_256_HMAC:
1317f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_384_HMAC:
1318f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_512_HMAC:
1319091d81d1SSam Leffler 	case CRYPTO_NULL_HMAC:
1320c0341432SJohn Baldwin 	case CRYPTO_RIPEMD160_HMAC:
1321091d81d1SSam Leffler 		break;
1322c0341432SJohn Baldwin 	case CRYPTO_AES_NIST_GMAC:
1323c0341432SJohn Baldwin 		switch (csp->csp_auth_klen * 8) {
1324c0341432SJohn Baldwin 		case 128:
1325c0341432SJohn Baldwin 		case 192:
1326c0341432SJohn Baldwin 		case 256:
1327c0341432SJohn Baldwin 			break;
1328c0341432SJohn Baldwin 		default:
1329c0341432SJohn Baldwin 			return (false);
1330c0341432SJohn Baldwin 		}
1331c0341432SJohn Baldwin 		if (csp->csp_auth_key == NULL)
1332c0341432SJohn Baldwin 			return (false);
1333c0341432SJohn Baldwin 		if (csp->csp_ivlen != AES_GCM_IV_LEN)
1334c0341432SJohn Baldwin 			return (false);
1335c0341432SJohn Baldwin 		break;
133625b7033bSConrad Meyer 	case CRYPTO_POLY1305:
1337c0341432SJohn Baldwin 		if (csp->csp_auth_klen != POLY1305_KEY_LEN)
1338c0341432SJohn Baldwin 			return (false);
1339c0341432SJohn Baldwin 		break;
1340c0341432SJohn Baldwin 	case CRYPTO_AES_CCM_CBC_MAC:
1341c0341432SJohn Baldwin 		switch (csp->csp_auth_klen * 8) {
1342c0341432SJohn Baldwin 		case 128:
1343c0341432SJohn Baldwin 		case 192:
1344c0341432SJohn Baldwin 		case 256:
1345c0341432SJohn Baldwin 			break;
1346c0341432SJohn Baldwin 		default:
1347c0341432SJohn Baldwin 			return (false);
1348c0341432SJohn Baldwin 		}
1349c0341432SJohn Baldwin 		if (csp->csp_auth_key == NULL)
1350c0341432SJohn Baldwin 			return (false);
1351c0341432SJohn Baldwin 		break;
1352c0341432SJohn Baldwin 	}
1353c0341432SJohn Baldwin 	return (true);
1354c0341432SJohn Baldwin }
1355091d81d1SSam Leffler 
1356c0341432SJohn Baldwin static bool
1357c0341432SJohn Baldwin swcr_cipher_supported(const struct crypto_session_params *csp)
1358c0341432SJohn Baldwin {
1359d8787d4fSMark Johnston 	const struct enc_xform *txf;
1360c0341432SJohn Baldwin 
1361c0341432SJohn Baldwin 	txf = crypto_cipher(csp);
1362c0341432SJohn Baldwin 	if (txf == NULL)
1363c0341432SJohn Baldwin 		return (false);
1364c0341432SJohn Baldwin 	if (csp->csp_cipher_alg != CRYPTO_NULL_CBC &&
1365c0341432SJohn Baldwin 	    txf->ivsize != csp->csp_ivlen)
1366c0341432SJohn Baldwin 		return (false);
1367c0341432SJohn Baldwin 	return (true);
1368c0341432SJohn Baldwin }
1369c0341432SJohn Baldwin 
13706038018aSMarcin Wojtas #define SUPPORTED_SES (CSP_F_SEPARATE_OUTPUT | CSP_F_SEPARATE_AAD | CSP_F_ESN)
13716038018aSMarcin Wojtas 
1372c0341432SJohn Baldwin static int
1373c0341432SJohn Baldwin swcr_probesession(device_t dev, const struct crypto_session_params *csp)
1374c0341432SJohn Baldwin {
13756038018aSMarcin Wojtas 	if ((csp->csp_flags & ~(SUPPORTED_SES)) != 0)
1376c0341432SJohn Baldwin 		return (EINVAL);
1377c0341432SJohn Baldwin 	switch (csp->csp_mode) {
1378c0341432SJohn Baldwin 	case CSP_MODE_COMPRESS:
1379c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1380c0341432SJohn Baldwin 		case CRYPTO_DEFLATE_COMP:
1381c0341432SJohn Baldwin 			break;
1382c0341432SJohn Baldwin 		default:
1383c0341432SJohn Baldwin 			return (EINVAL);
13845fbc5b5aSConrad Meyer 		}
1385091d81d1SSam Leffler 		break;
1386c0341432SJohn Baldwin 	case CSP_MODE_CIPHER:
1387c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1388c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1389c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1390dd2e1352SJohn Baldwin 		case CRYPTO_CHACHA20_POLY1305:
1391c0341432SJohn Baldwin 			return (EINVAL);
1392c0341432SJohn Baldwin 		default:
1393c0341432SJohn Baldwin 			if (!swcr_cipher_supported(csp))
1394c0341432SJohn Baldwin 				return (EINVAL);
1395091d81d1SSam Leffler 			break;
1396091d81d1SSam Leffler 		}
1397c0341432SJohn Baldwin 		break;
1398c0341432SJohn Baldwin 	case CSP_MODE_DIGEST:
1399c0341432SJohn Baldwin 		if (!swcr_auth_supported(csp))
1400c0341432SJohn Baldwin 			return (EINVAL);
1401c0341432SJohn Baldwin 		break;
1402c0341432SJohn Baldwin 	case CSP_MODE_AEAD:
1403c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1404c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1405c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1406c172a407SJohn Baldwin 			switch (csp->csp_cipher_klen * 8) {
1407c172a407SJohn Baldwin 			case 128:
1408c172a407SJohn Baldwin 			case 192:
1409c172a407SJohn Baldwin 			case 256:
1410c172a407SJohn Baldwin 				break;
1411c172a407SJohn Baldwin 			default:
1412c172a407SJohn Baldwin 				return (EINVAL);
1413c172a407SJohn Baldwin 			}
1414c172a407SJohn Baldwin 			break;
1415dd2e1352SJohn Baldwin 		case CRYPTO_CHACHA20_POLY1305:
1416c0341432SJohn Baldwin 			break;
1417c0341432SJohn Baldwin 		default:
1418c0341432SJohn Baldwin 			return (EINVAL);
1419c0341432SJohn Baldwin 		}
1420c0341432SJohn Baldwin 		break;
1421c0341432SJohn Baldwin 	case CSP_MODE_ETA:
1422c0341432SJohn Baldwin 		/* AEAD algorithms cannot be used for EtA. */
1423c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1424c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1425c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1426dd2e1352SJohn Baldwin 		case CRYPTO_CHACHA20_POLY1305:
1427c0341432SJohn Baldwin 			return (EINVAL);
1428c0341432SJohn Baldwin 		}
1429c0341432SJohn Baldwin 		switch (csp->csp_auth_alg) {
1430c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GMAC:
1431c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_CBC_MAC:
1432c0341432SJohn Baldwin 			return (EINVAL);
1433c0341432SJohn Baldwin 		}
1434c0341432SJohn Baldwin 
1435c0341432SJohn Baldwin 		if (!swcr_cipher_supported(csp) ||
1436c0341432SJohn Baldwin 		    !swcr_auth_supported(csp))
1437c0341432SJohn Baldwin 			return (EINVAL);
1438c0341432SJohn Baldwin 		break;
1439c0341432SJohn Baldwin 	default:
1440c0341432SJohn Baldwin 		return (EINVAL);
1441c0341432SJohn Baldwin 	}
1442c0341432SJohn Baldwin 
1443c0341432SJohn Baldwin 	return (CRYPTODEV_PROBE_SOFTWARE);
1444c0341432SJohn Baldwin }
1445c0341432SJohn Baldwin 
1446c0341432SJohn Baldwin /*
1447c0341432SJohn Baldwin  * Generate a new software session.
1448c0341432SJohn Baldwin  */
1449c0341432SJohn Baldwin static int
1450c0341432SJohn Baldwin swcr_newsession(device_t dev, crypto_session_t cses,
1451c0341432SJohn Baldwin     const struct crypto_session_params *csp)
1452c0341432SJohn Baldwin {
1453c0341432SJohn Baldwin 	struct swcr_session *ses;
1454d8787d4fSMark Johnston 	const struct comp_algo *cxf;
1455c0341432SJohn Baldwin 	int error;
1456c0341432SJohn Baldwin 
1457c0341432SJohn Baldwin 	ses = crypto_get_driver_session(cses);
1458c0341432SJohn Baldwin 	mtx_init(&ses->swcr_lock, "swcr session lock", NULL, MTX_DEF);
1459c0341432SJohn Baldwin 
1460c0341432SJohn Baldwin 	error = 0;
1461c0341432SJohn Baldwin 	switch (csp->csp_mode) {
1462c0341432SJohn Baldwin 	case CSP_MODE_COMPRESS:
1463c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1464c0341432SJohn Baldwin 		case CRYPTO_DEFLATE_COMP:
1465c0341432SJohn Baldwin 			cxf = &comp_algo_deflate;
1466c0341432SJohn Baldwin 			break;
1467c0341432SJohn Baldwin #ifdef INVARIANTS
1468c0341432SJohn Baldwin 		default:
1469c0341432SJohn Baldwin 			panic("bad compression algo");
1470c0341432SJohn Baldwin #endif
1471c0341432SJohn Baldwin 		}
1472c0341432SJohn Baldwin 		ses->swcr_compdec.sw_cxf = cxf;
1473c0341432SJohn Baldwin 		ses->swcr_process = swcr_compdec;
1474c0341432SJohn Baldwin 		break;
1475c0341432SJohn Baldwin 	case CSP_MODE_CIPHER:
1476c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1477c0341432SJohn Baldwin 		case CRYPTO_NULL_CBC:
1478c0341432SJohn Baldwin 			ses->swcr_process = swcr_null;
1479c0341432SJohn Baldwin 			break;
1480c0341432SJohn Baldwin #ifdef INVARIANTS
1481c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1482c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1483dd2e1352SJohn Baldwin 		case CRYPTO_CHACHA20_POLY1305:
1484c0341432SJohn Baldwin 			panic("bad cipher algo");
1485c0341432SJohn Baldwin #endif
1486c0341432SJohn Baldwin 		default:
14873e947048SJohn Baldwin 			error = swcr_setup_cipher(ses, csp);
1488c0341432SJohn Baldwin 			if (error == 0)
1489c0341432SJohn Baldwin 				ses->swcr_process = swcr_encdec;
1490c0341432SJohn Baldwin 		}
1491c0341432SJohn Baldwin 		break;
1492c0341432SJohn Baldwin 	case CSP_MODE_DIGEST:
1493c0341432SJohn Baldwin 		error = swcr_setup_auth(ses, csp);
1494c0341432SJohn Baldwin 		break;
1495c0341432SJohn Baldwin 	case CSP_MODE_AEAD:
1496c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1497c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1498ab91fb6cSJohn Baldwin 			error = swcr_setup_aead(ses, csp);
1499c0341432SJohn Baldwin 			if (error == 0)
1500c0341432SJohn Baldwin 				ses->swcr_process = swcr_gcm;
1501c0341432SJohn Baldwin 			break;
1502c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1503ab91fb6cSJohn Baldwin 			error = swcr_setup_aead(ses, csp);
1504c0341432SJohn Baldwin 			if (error == 0)
1505c0341432SJohn Baldwin 				ses->swcr_process = swcr_ccm;
1506c0341432SJohn Baldwin 			break;
1507dd2e1352SJohn Baldwin 		case CRYPTO_CHACHA20_POLY1305:
1508ab91fb6cSJohn Baldwin 			error = swcr_setup_aead(ses, csp);
1509dd2e1352SJohn Baldwin 			if (error == 0)
1510dd2e1352SJohn Baldwin 				ses->swcr_process = swcr_chacha20_poly1305;
1511dd2e1352SJohn Baldwin 			break;
1512c0341432SJohn Baldwin #ifdef INVARIANTS
1513c0341432SJohn Baldwin 		default:
1514c0341432SJohn Baldwin 			panic("bad aead algo");
1515c0341432SJohn Baldwin #endif
1516c0341432SJohn Baldwin 		}
1517c0341432SJohn Baldwin 		break;
1518c0341432SJohn Baldwin 	case CSP_MODE_ETA:
1519c0341432SJohn Baldwin #ifdef INVARIANTS
1520c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1521c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1522c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1523dd2e1352SJohn Baldwin 		case CRYPTO_CHACHA20_POLY1305:
1524c0341432SJohn Baldwin 			panic("bad eta cipher algo");
1525c0341432SJohn Baldwin 		}
1526c0341432SJohn Baldwin 		switch (csp->csp_auth_alg) {
1527c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GMAC:
1528c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_CBC_MAC:
1529c0341432SJohn Baldwin 			panic("bad eta auth algo");
1530c0341432SJohn Baldwin 		}
1531c0341432SJohn Baldwin #endif
1532c0341432SJohn Baldwin 
1533c0341432SJohn Baldwin 		error = swcr_setup_auth(ses, csp);
1534c0341432SJohn Baldwin 		if (error)
1535c0341432SJohn Baldwin 			break;
1536c0341432SJohn Baldwin 		if (csp->csp_cipher_alg == CRYPTO_NULL_CBC) {
1537c0341432SJohn Baldwin 			/* Effectively degrade to digest mode. */
1538c0341432SJohn Baldwin 			ses->swcr_process = swcr_authcompute;
1539c0341432SJohn Baldwin 			break;
1540c0341432SJohn Baldwin 		}
1541c0341432SJohn Baldwin 
15423e947048SJohn Baldwin 		error = swcr_setup_cipher(ses, csp);
1543c0341432SJohn Baldwin 		if (error == 0)
1544c0341432SJohn Baldwin 			ses->swcr_process = swcr_eta;
1545c0341432SJohn Baldwin 		break;
1546c0341432SJohn Baldwin 	default:
1547c0341432SJohn Baldwin 		error = EINVAL;
1548c0341432SJohn Baldwin 	}
1549c0341432SJohn Baldwin 
1550c0341432SJohn Baldwin 	if (error)
1551c0341432SJohn Baldwin 		swcr_freesession(dev, cses);
1552c0341432SJohn Baldwin 	return (error);
1553c0341432SJohn Baldwin }
1554c0341432SJohn Baldwin 
1555c0341432SJohn Baldwin static void
1556c0341432SJohn Baldwin swcr_freesession(device_t dev, crypto_session_t cses)
1557c0341432SJohn Baldwin {
1558c0341432SJohn Baldwin 	struct swcr_session *ses;
1559c0341432SJohn Baldwin 
1560c0341432SJohn Baldwin 	ses = crypto_get_driver_session(cses);
1561c0341432SJohn Baldwin 
1562c0341432SJohn Baldwin 	mtx_destroy(&ses->swcr_lock);
1563c0341432SJohn Baldwin 
1564f313909aSJohn Baldwin 	zfree(ses->swcr_encdec.sw_ctx, M_CRYPTO_DATA);
15654a711b8dSJohn Baldwin 	zfree(ses->swcr_auth.sw_ictx, M_CRYPTO_DATA);
15664a711b8dSJohn Baldwin 	zfree(ses->swcr_auth.sw_octx, M_CRYPTO_DATA);
1567091d81d1SSam Leffler }
1568091d81d1SSam Leffler 
1569091d81d1SSam Leffler /*
1570091d81d1SSam Leffler  * Process a software request.
1571091d81d1SSam Leffler  */
1572091d81d1SSam Leffler static int
15736810ad6fSSam Leffler swcr_process(device_t dev, struct cryptop *crp, int hint)
1574091d81d1SSam Leffler {
1575c0341432SJohn Baldwin 	struct swcr_session *ses;
1576091d81d1SSam Leffler 
15771b0909d5SConrad Meyer 	ses = crypto_get_driver_session(crp->crp_session);
1578a7fcb1afSSean Eric Fagan 	mtx_lock(&ses->swcr_lock);
1579091d81d1SSam Leffler 
1580c0341432SJohn Baldwin 	crp->crp_etype = ses->swcr_process(ses, crp);
1581091d81d1SSam Leffler 
1582a7fcb1afSSean Eric Fagan 	mtx_unlock(&ses->swcr_lock);
1583091d81d1SSam Leffler 	crypto_done(crp);
1584c0341432SJohn Baldwin 	return (0);
1585091d81d1SSam Leffler }
1586091d81d1SSam Leffler 
1587091d81d1SSam Leffler static void
15883f147ab2SWarner Losh swcr_identify(driver_t *drv, device_t parent)
1589091d81d1SSam Leffler {
15906810ad6fSSam Leffler 	/* NB: order 10 is so we get attached after h/w devices */
15916810ad6fSSam Leffler 	if (device_find_child(parent, "cryptosoft", -1) == NULL &&
159286c585d9SMarius Strobl 	    BUS_ADD_CHILD(parent, 10, "cryptosoft", 0) == 0)
15936810ad6fSSam Leffler 		panic("cryptosoft: could not attach");
15946810ad6fSSam Leffler }
1595f6c4bc3bSPawel Jakub Dawidek 
15966810ad6fSSam Leffler static int
15976810ad6fSSam Leffler swcr_probe(device_t dev)
15986810ad6fSSam Leffler {
15996810ad6fSSam Leffler 	device_set_desc(dev, "software crypto");
16004fc60fa9SMark Johnston 	device_quiet(dev);
160186c585d9SMarius Strobl 	return (BUS_PROBE_NOWILDCARD);
16026810ad6fSSam Leffler }
1603f6c4bc3bSPawel Jakub Dawidek 
16046810ad6fSSam Leffler static int
16056810ad6fSSam Leffler swcr_attach(device_t dev)
16066810ad6fSSam Leffler {
16076810ad6fSSam Leffler 
16089ebbebe4SConrad Meyer 	swcr_id = crypto_get_driverid(dev, sizeof(struct swcr_session),
16096810ad6fSSam Leffler 			CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC);
16106810ad6fSSam Leffler 	if (swcr_id < 0) {
16116810ad6fSSam Leffler 		device_printf(dev, "cannot initialize!");
1612c0341432SJohn Baldwin 		return (ENXIO);
16136810ad6fSSam Leffler 	}
16146810ad6fSSam Leffler 
1615c0341432SJohn Baldwin 	return (0);
1616091d81d1SSam Leffler }
16174b465da2SPawel Jakub Dawidek 
16183f147ab2SWarner Losh static int
16196810ad6fSSam Leffler swcr_detach(device_t dev)
16204b465da2SPawel Jakub Dawidek {
16216810ad6fSSam Leffler 	crypto_unregister_all(swcr_id);
16223f147ab2SWarner Losh 	return 0;
16234b465da2SPawel Jakub Dawidek }
16246810ad6fSSam Leffler 
16256810ad6fSSam Leffler static device_method_t swcr_methods[] = {
16266810ad6fSSam Leffler 	DEVMETHOD(device_identify,	swcr_identify),
16276810ad6fSSam Leffler 	DEVMETHOD(device_probe,		swcr_probe),
16286810ad6fSSam Leffler 	DEVMETHOD(device_attach,	swcr_attach),
16296810ad6fSSam Leffler 	DEVMETHOD(device_detach,	swcr_detach),
16306810ad6fSSam Leffler 
1631c0341432SJohn Baldwin 	DEVMETHOD(cryptodev_probesession, swcr_probesession),
16326810ad6fSSam Leffler 	DEVMETHOD(cryptodev_newsession,	swcr_newsession),
16336810ad6fSSam Leffler 	DEVMETHOD(cryptodev_freesession,swcr_freesession),
16346810ad6fSSam Leffler 	DEVMETHOD(cryptodev_process,	swcr_process),
16356810ad6fSSam Leffler 
16366810ad6fSSam Leffler 	{0, 0},
16376810ad6fSSam Leffler };
16386810ad6fSSam Leffler 
16396810ad6fSSam Leffler static driver_t swcr_driver = {
16406810ad6fSSam Leffler 	"cryptosoft",
16416810ad6fSSam Leffler 	swcr_methods,
16426810ad6fSSam Leffler 	0,		/* NB: no softc */
16436810ad6fSSam Leffler };
16446810ad6fSSam Leffler static devclass_t swcr_devclass;
16456810ad6fSSam Leffler 
16466810ad6fSSam Leffler /*
16476810ad6fSSam Leffler  * NB: We explicitly reference the crypto module so we
16486810ad6fSSam Leffler  * get the necessary ordering when built as a loadable
16496810ad6fSSam Leffler  * module.  This is required because we bundle the crypto
16506810ad6fSSam Leffler  * module code together with the cryptosoft driver (otherwise
16516810ad6fSSam Leffler  * normal module dependencies would handle things).
16526810ad6fSSam Leffler  */
16536810ad6fSSam Leffler extern int crypto_modevent(struct module *, int, void *);
16546810ad6fSSam Leffler /* XXX where to attach */
16556810ad6fSSam Leffler DRIVER_MODULE(cryptosoft, nexus, swcr_driver, swcr_devclass, crypto_modevent,0);
16566810ad6fSSam Leffler MODULE_VERSION(cryptosoft, 1);
16576810ad6fSSam Leffler MODULE_DEPEND(cryptosoft, crypto, 1, 1, 1);
1658