xref: /freebsd/sys/opencrypto/cryptosoft.c (revision dc475c9bee02f1a480362450b3680f0e3bfee529)
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>
4708fca7a5SJohn-Mark Gurney #include <sys/endian.h>
4808fca7a5SJohn-Mark Gurney #include <sys/limits.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;
63d8787d4fSMark Johnston 	const struct auth_hash *sw_axf;
64c0341432SJohn Baldwin 	uint16_t	sw_mlen;
656113a08bSJohn Baldwin 	bool		sw_hmac;
66c0341432SJohn Baldwin };
67c0341432SJohn Baldwin 
68c0341432SJohn Baldwin struct swcr_encdec {
69f313909aSJohn Baldwin 	void		*sw_ctx;
70d8787d4fSMark Johnston 	const struct enc_xform *sw_exf;
71c0341432SJohn Baldwin };
72c0341432SJohn Baldwin 
73c0341432SJohn Baldwin struct swcr_compdec {
74d8787d4fSMark Johnston 	const struct comp_algo *sw_cxf;
75c0341432SJohn Baldwin };
76c0341432SJohn Baldwin 
77c0341432SJohn Baldwin struct swcr_session {
78*dc475c9bSJohn Baldwin 	int	(*swcr_process)(const 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
91*dc475c9bSJohn Baldwin swcr_null(const 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
101*dc475c9bSJohn Baldwin swcr_encdec(const 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;
106d8787d4fSMark Johnston 	const struct enc_xform *exf;
107b54d1284SJohn Baldwin 	const struct swcr_encdec *sw;
108b54d1284SJohn Baldwin 	void *ctx;
10986be314dSJohn Baldwin 	size_t inlen, outlen;
1101833d604SJohn Baldwin 	int i, blks, resid;
1119c0e3d3aSJohn Baldwin 	struct crypto_buffer_cursor cc_in, cc_out;
11226d292d3SJohn Baldwin 	const unsigned char *inblk;
11326d292d3SJohn Baldwin 	unsigned char *outblk;
11408fca7a5SJohn-Mark Gurney 	int error;
115c0341432SJohn Baldwin 	bool encrypting;
11608fca7a5SJohn-Mark Gurney 
11708fca7a5SJohn-Mark Gurney 	error = 0;
118091d81d1SSam Leffler 
119c0341432SJohn Baldwin 	sw = &ses->swcr_encdec;
120091d81d1SSam Leffler 	exf = sw->sw_exf;
1211833d604SJohn Baldwin 	csp = crypto_get_params(crp->crp_session);
122091d81d1SSam Leffler 
123723d8764SJohn Baldwin 	if (exf->native_blocksize == 0) {
124091d81d1SSam Leffler 		/* Check for non-padded data */
125723d8764SJohn Baldwin 		if ((crp->crp_payload_length % exf->blocksize) != 0)
126723d8764SJohn Baldwin 			return (EINVAL);
127723d8764SJohn Baldwin 
128723d8764SJohn Baldwin 		blks = exf->blocksize;
129723d8764SJohn Baldwin 	} else
130723d8764SJohn Baldwin 		blks = exf->native_blocksize;
131091d81d1SSam Leffler 
132c0341432SJohn Baldwin 	if (exf == &enc_xform_aes_icm &&
133c0341432SJohn Baldwin 	    (crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0)
13408fca7a5SJohn-Mark Gurney 		return (EINVAL);
13508fca7a5SJohn-Mark Gurney 
136b54d1284SJohn Baldwin 	ctx = __builtin_alloca(exf->ctxsize);
137c0341432SJohn Baldwin 	if (crp->crp_cipher_key != NULL) {
138b54d1284SJohn Baldwin 		error = exf->setkey(ctx, crp->crp_cipher_key,
139b54d1284SJohn Baldwin 		    csp->csp_cipher_klen);
140c740ae4bSPoul-Henning Kamp 		if (error)
141c740ae4bSPoul-Henning Kamp 			return (error);
142b54d1284SJohn Baldwin 	} else
143b54d1284SJohn Baldwin 		memcpy(ctx, sw->sw_ctx, exf->ctxsize);
144d295bdeeSPawel Jakub Dawidek 
14520c128daSJohn Baldwin 	crypto_read_iv(crp, iv);
14620c128daSJohn Baldwin 
14708fca7a5SJohn-Mark Gurney 	if (exf->reinit) {
148d295bdeeSPawel Jakub Dawidek 		/*
149d295bdeeSPawel Jakub Dawidek 		 * xforms that provide a reinit method perform all IV
150d295bdeeSPawel Jakub Dawidek 		 * handling themselves.
151d295bdeeSPawel Jakub Dawidek 		 */
152b54d1284SJohn Baldwin 		exf->reinit(ctx, iv, csp->csp_ivlen);
153091d81d1SSam Leffler 	}
154091d81d1SSam Leffler 
1559c0e3d3aSJohn Baldwin 	ivp = iv;
156091d81d1SSam Leffler 
1579c0e3d3aSJohn Baldwin 	crypto_cursor_init(&cc_in, &crp->crp_buf);
1589c0e3d3aSJohn Baldwin 	crypto_cursor_advance(&cc_in, crp->crp_payload_start);
15986be314dSJohn Baldwin 	inblk = crypto_cursor_segment(&cc_in, &inlen);
1609c0e3d3aSJohn Baldwin 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
1619c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_out, &crp->crp_obuf);
1629c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_out, crp->crp_payload_output_start);
1639c0e3d3aSJohn Baldwin 	} else
1649c0e3d3aSJohn Baldwin 		cc_out = cc_in;
16586be314dSJohn Baldwin 	outblk = crypto_cursor_segment(&cc_out, &outlen);
1669c0e3d3aSJohn Baldwin 
1679c0e3d3aSJohn Baldwin 	resid = crp->crp_payload_length;
168c0341432SJohn Baldwin 	encrypting = CRYPTO_OP_IS_ENCRYPT(crp->crp_op);
169091d81d1SSam Leffler 
170091d81d1SSam Leffler 	/*
1719c0e3d3aSJohn Baldwin 	 * Loop through encrypting blocks.  'inlen' is the remaining
1729c0e3d3aSJohn Baldwin 	 * length of the current segment in the input buffer.
1739c0e3d3aSJohn Baldwin 	 * 'outlen' is the remaining length of current segment in the
1749c0e3d3aSJohn Baldwin 	 * output buffer.
175091d81d1SSam Leffler 	 */
1769c0e3d3aSJohn Baldwin 	while (resid >= blks) {
1779c0e3d3aSJohn Baldwin 		/*
1789c0e3d3aSJohn Baldwin 		 * If the current block is not contained within the
1799c0e3d3aSJohn Baldwin 		 * current input/output segment, use 'blk' as a local
1809c0e3d3aSJohn Baldwin 		 * buffer.
1819c0e3d3aSJohn Baldwin 		 */
1829c0e3d3aSJohn Baldwin 		if (inlen < blks) {
1839c0e3d3aSJohn Baldwin 			crypto_cursor_copydata(&cc_in, blks, blk);
1849c0e3d3aSJohn Baldwin 			inblk = blk;
185d295bdeeSPawel Jakub Dawidek 		}
1869c0e3d3aSJohn Baldwin 		if (outlen < blks)
1879c0e3d3aSJohn Baldwin 			outblk = blk;
1889c0e3d3aSJohn Baldwin 
1899c0e3d3aSJohn Baldwin 		/*
1909c0e3d3aSJohn Baldwin 		 * Ciphers without a 'reinit' hook are assumed to be
1919c0e3d3aSJohn Baldwin 		 * used in CBC mode where the chaining is done here.
1929c0e3d3aSJohn Baldwin 		 */
1939c0e3d3aSJohn Baldwin 		if (exf->reinit != NULL) {
1949c0e3d3aSJohn Baldwin 			if (encrypting)
195b54d1284SJohn Baldwin 				exf->encrypt(ctx, inblk, outblk);
1969c0e3d3aSJohn Baldwin 			else
197b54d1284SJohn Baldwin 				exf->decrypt(ctx, inblk, outblk);
198c0341432SJohn Baldwin 		} else if (encrypting) {
199091d81d1SSam Leffler 			/* XOR with previous block */
2009c0e3d3aSJohn Baldwin 			for (i = 0; i < blks; i++)
2019c0e3d3aSJohn Baldwin 				outblk[i] = inblk[i] ^ ivp[i];
202091d81d1SSam Leffler 
203b54d1284SJohn Baldwin 			exf->encrypt(ctx, outblk, outblk);
204091d81d1SSam Leffler 
205091d81d1SSam Leffler 			/*
206091d81d1SSam Leffler 			 * Keep encrypted block for XOR'ing
207091d81d1SSam Leffler 			 * with next block
208091d81d1SSam Leffler 			 */
2099c0e3d3aSJohn Baldwin 			memcpy(iv, outblk, blks);
210091d81d1SSam Leffler 			ivp = iv;
211091d81d1SSam Leffler 		} else {	/* decrypt */
212091d81d1SSam Leffler 			/*
213091d81d1SSam Leffler 			 * Keep encrypted block for XOR'ing
214091d81d1SSam Leffler 			 * with next block
215091d81d1SSam Leffler 			 */
21608fca7a5SJohn-Mark Gurney 			nivp = (ivp == iv) ? iv2 : iv;
2179c0e3d3aSJohn Baldwin 			memcpy(nivp, inblk, blks);
218091d81d1SSam Leffler 
219b54d1284SJohn Baldwin 			exf->decrypt(ctx, inblk, outblk);
220091d81d1SSam Leffler 
221091d81d1SSam Leffler 			/* XOR with previous block */
2229c0e3d3aSJohn Baldwin 			for (i = 0; i < blks; i++)
2239c0e3d3aSJohn Baldwin 				outblk[i] ^= ivp[i];
224091d81d1SSam Leffler 
22508fca7a5SJohn-Mark Gurney 			ivp = nivp;
226091d81d1SSam Leffler 		}
227091d81d1SSam Leffler 
2289c0e3d3aSJohn Baldwin 		if (inlen < blks) {
22986be314dSJohn Baldwin 			inblk = crypto_cursor_segment(&cc_in, &inlen);
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);
23886be314dSJohn Baldwin 			outblk = crypto_cursor_segment(&cc_out, &outlen);
2399c0e3d3aSJohn Baldwin 		} else {
2409c0e3d3aSJohn Baldwin 			crypto_cursor_advance(&cc_out, blks);
2419c0e3d3aSJohn Baldwin 			outlen -= blks;
2429c0e3d3aSJohn Baldwin 			outblk += blks;
243091d81d1SSam Leffler 		}
244091d81d1SSam Leffler 
2459c0e3d3aSJohn Baldwin 		resid -= blks;
246f34a967bSPawel Jakub Dawidek 	}
247f34a967bSPawel Jakub Dawidek 
248723d8764SJohn Baldwin 	/* Handle trailing partial block for stream ciphers. */
2499c0e3d3aSJohn Baldwin 	if (resid > 0) {
250723d8764SJohn Baldwin 		KASSERT(exf->native_blocksize != 0,
251723d8764SJohn Baldwin 		    ("%s: partial block of %d bytes for cipher %s",
252723d8764SJohn Baldwin 		    __func__, i, exf->name));
253723d8764SJohn Baldwin 		KASSERT(exf->reinit != NULL,
254723d8764SJohn Baldwin 		    ("%s: partial block cipher %s without reinit hook",
255723d8764SJohn Baldwin 		    __func__, exf->name));
2569c0e3d3aSJohn Baldwin 		KASSERT(resid < blks, ("%s: partial block too big", __func__));
257723d8764SJohn Baldwin 
25886be314dSJohn Baldwin 		inblk = crypto_cursor_segment(&cc_in, &inlen);
25986be314dSJohn Baldwin 		outblk = crypto_cursor_segment(&cc_out, &outlen);
2609c0e3d3aSJohn Baldwin 		if (inlen < resid) {
2619c0e3d3aSJohn Baldwin 			crypto_cursor_copydata(&cc_in, resid, blk);
2629c0e3d3aSJohn Baldwin 			inblk = blk;
26386be314dSJohn Baldwin 		}
2649c0e3d3aSJohn Baldwin 		if (outlen < resid)
2659c0e3d3aSJohn Baldwin 			outblk = blk;
2669c0e3d3aSJohn Baldwin 		if (encrypting)
267b54d1284SJohn Baldwin 			exf->encrypt_last(ctx, inblk, outblk,
2689c0e3d3aSJohn Baldwin 			    resid);
2699c0e3d3aSJohn Baldwin 		else
270b54d1284SJohn Baldwin 			exf->decrypt_last(ctx, inblk, outblk,
2719c0e3d3aSJohn Baldwin 			    resid);
2729c0e3d3aSJohn Baldwin 		if (outlen < resid)
2739c0e3d3aSJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
274723d8764SJohn Baldwin 	}
275723d8764SJohn Baldwin 
276b54d1284SJohn Baldwin 	explicit_bzero(ctx, exf->ctxsize);
27720c128daSJohn Baldwin 	explicit_bzero(blk, sizeof(blk));
27820c128daSJohn Baldwin 	explicit_bzero(iv, sizeof(iv));
27920c128daSJohn Baldwin 	explicit_bzero(iv2, sizeof(iv2));
2809c0e3d3aSJohn Baldwin 	return (0);
281091d81d1SSam Leffler }
282091d81d1SSam Leffler 
283091d81d1SSam Leffler /*
284c0341432SJohn Baldwin  * Compute or verify hash.
285091d81d1SSam Leffler  */
286091d81d1SSam Leffler static int
287*dc475c9bSJohn Baldwin swcr_authcompute(const struct swcr_session *ses, struct cryptop *crp)
288091d81d1SSam Leffler {
289c0341432SJohn Baldwin 	u_char aalg[HASH_MAX_LEN];
290c0341432SJohn Baldwin 	const struct crypto_session_params *csp;
2916113a08bSJohn Baldwin 	const struct swcr_auth *sw;
292d8787d4fSMark Johnston 	const struct auth_hash *axf;
293091d81d1SSam Leffler 	union authctx ctx;
294091d81d1SSam Leffler 	int err;
295091d81d1SSam Leffler 
296c0341432SJohn Baldwin 	sw = &ses->swcr_auth;
297091d81d1SSam Leffler 
298091d81d1SSam Leffler 	axf = sw->sw_axf;
299091d81d1SSam Leffler 
300c0341432SJohn Baldwin 	csp = crypto_get_params(crp->crp_session);
3016038018aSMarcin Wojtas 	if (crp->crp_auth_key != NULL) {
3026113a08bSJohn Baldwin 		if (sw->sw_hmac) {
3036113a08bSJohn Baldwin 			hmac_init_ipad(axf, crp->crp_auth_key,
3046113a08bSJohn Baldwin 			    csp->csp_auth_klen, &ctx);
3056113a08bSJohn Baldwin 		} else {
3066113a08bSJohn Baldwin 			axf->Init(&ctx);
3076113a08bSJohn Baldwin 			axf->Setkey(&ctx, crp->crp_auth_key,
308c0341432SJohn Baldwin 			    csp->csp_auth_klen);
30925b7033bSConrad Meyer 		}
3106113a08bSJohn Baldwin 	} else
3116113a08bSJohn Baldwin 		memcpy(&ctx, sw->sw_ictx, axf->ctxsize);
312091d81d1SSam Leffler 
3139b774dc0SJohn Baldwin 	if (crp->crp_aad != NULL)
3149b774dc0SJohn Baldwin 		err = axf->Update(&ctx, crp->crp_aad, crp->crp_aad_length);
3159b774dc0SJohn Baldwin 	else
316c0341432SJohn Baldwin 		err = crypto_apply(crp, crp->crp_aad_start, crp->crp_aad_length,
3179b6b2f86SJohn Baldwin 		    axf->Update, &ctx);
318091d81d1SSam Leffler 	if (err)
319e0b155feSJohn Baldwin 		goto out;
320091d81d1SSam Leffler 
3219c0e3d3aSJohn Baldwin 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp) &&
3229c0e3d3aSJohn Baldwin 	    CRYPTO_OP_IS_ENCRYPT(crp->crp_op))
3239c0e3d3aSJohn Baldwin 		err = crypto_apply_buf(&crp->crp_obuf,
3249c0e3d3aSJohn Baldwin 		    crp->crp_payload_output_start, crp->crp_payload_length,
3259b6b2f86SJohn Baldwin 		    axf->Update, &ctx);
3269c0e3d3aSJohn Baldwin 	else
3279c0e3d3aSJohn Baldwin 		err = crypto_apply(crp, crp->crp_payload_start,
3289b6b2f86SJohn Baldwin 		    crp->crp_payload_length, axf->Update, &ctx);
329c0341432SJohn Baldwin 	if (err)
330e0b155feSJohn Baldwin 		goto out;
331091d81d1SSam Leffler 
3326038018aSMarcin Wojtas 	if (csp->csp_flags & CSP_F_ESN)
3336038018aSMarcin Wojtas 		axf->Update(&ctx, crp->crp_esn, 4);
3346038018aSMarcin Wojtas 
335091d81d1SSam Leffler 	axf->Final(aalg, &ctx);
3366113a08bSJohn Baldwin 	if (sw->sw_hmac) {
3376113a08bSJohn Baldwin 		if (crp->crp_auth_key != NULL)
3386113a08bSJohn Baldwin 			hmac_init_opad(axf, crp->crp_auth_key,
3396113a08bSJohn Baldwin 			    csp->csp_auth_klen, &ctx);
3406113a08bSJohn Baldwin 		else
3416113a08bSJohn Baldwin 			memcpy(&ctx, sw->sw_octx, axf->ctxsize);
342091d81d1SSam Leffler 		axf->Update(&ctx, aalg, axf->hashsize);
343091d81d1SSam Leffler 		axf->Final(aalg, &ctx);
344091d81d1SSam Leffler 	}
345091d81d1SSam Leffler 
346c0341432SJohn Baldwin 	if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
34720c128daSJohn Baldwin 		u_char uaalg[HASH_MAX_LEN];
34820c128daSJohn Baldwin 
349c0341432SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, sw->sw_mlen, uaalg);
350c0341432SJohn Baldwin 		if (timingsafe_bcmp(aalg, uaalg, sw->sw_mlen) != 0)
35120c128daSJohn Baldwin 			err = EBADMSG;
35220c128daSJohn Baldwin 		explicit_bzero(uaalg, sizeof(uaalg));
353c0341432SJohn Baldwin 	} else {
354091d81d1SSam Leffler 		/* Inject the authentication data */
355c0341432SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, sw->sw_mlen, aalg);
356c0341432SJohn Baldwin 	}
35720c128daSJohn Baldwin 	explicit_bzero(aalg, sizeof(aalg));
358e0b155feSJohn Baldwin out:
359e0b155feSJohn Baldwin 	explicit_bzero(&ctx, sizeof(ctx));
36020c128daSJohn Baldwin 	return (err);
361091d81d1SSam Leffler }
362091d81d1SSam Leffler 
36308fca7a5SJohn-Mark Gurney CTASSERT(INT_MAX <= (1ll<<39) - 256);	/* GCM: plain text < 2^39-256 */
36408fca7a5SJohn-Mark Gurney CTASSERT(INT_MAX <= (uint64_t)-1);	/* GCM: associated data <= 2^64-1 */
36508fca7a5SJohn-Mark Gurney 
36608fca7a5SJohn-Mark Gurney static int
367*dc475c9bSJohn Baldwin swcr_gmac(const struct swcr_session *ses, struct cryptop *crp)
36808fca7a5SJohn-Mark Gurney {
36926d292d3SJohn Baldwin 	uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))];
37008fca7a5SJohn-Mark Gurney 	u_char *blk = (u_char *)blkbuf;
37126d292d3SJohn Baldwin 	u_char tag[GMAC_DIGEST_LEN];
37226d292d3SJohn Baldwin 	u_char iv[AES_BLOCK_LEN];
3739c0e3d3aSJohn Baldwin 	struct crypto_buffer_cursor cc;
37426d292d3SJohn Baldwin 	const u_char *inblk;
37508fca7a5SJohn-Mark Gurney 	union authctx ctx;
3766113a08bSJohn Baldwin 	const struct swcr_auth *swa;
377d8787d4fSMark Johnston 	const struct auth_hash *axf;
37808fca7a5SJohn-Mark Gurney 	uint32_t *blkp;
37986be314dSJohn Baldwin 	size_t len;
38086be314dSJohn Baldwin 	int blksz, error, ivlen, resid;
38108fca7a5SJohn-Mark Gurney 
382c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
38308fca7a5SJohn-Mark Gurney 	axf = swa->sw_axf;
38426d292d3SJohn Baldwin 	blksz = GMAC_BLOCK_LEN;
38526d292d3SJohn Baldwin 	KASSERT(axf->blocksize == blksz, ("%s: axf block size mismatch",
38626d292d3SJohn Baldwin 	    __func__));
38708fca7a5SJohn-Mark Gurney 
3886113a08bSJohn Baldwin 	if (crp->crp_auth_key != NULL) {
3896113a08bSJohn Baldwin 		axf->Init(&ctx);
3906113a08bSJohn Baldwin 		axf->Setkey(&ctx, crp->crp_auth_key,
3916113a08bSJohn Baldwin 		    crypto_get_params(crp->crp_session)->csp_auth_klen);
3926113a08bSJohn Baldwin 	} else
3936113a08bSJohn Baldwin 		memcpy(&ctx, swa->sw_ictx, axf->ctxsize);
3946113a08bSJohn Baldwin 
39508fca7a5SJohn-Mark Gurney 	/* Initialize the IV */
396c0341432SJohn Baldwin 	ivlen = AES_GCM_IV_LEN;
39729fe41ddSJohn Baldwin 	crypto_read_iv(crp, iv);
39808fca7a5SJohn-Mark Gurney 
39908fca7a5SJohn-Mark Gurney 	axf->Reinit(&ctx, iv, ivlen);
4009c0e3d3aSJohn Baldwin 	crypto_cursor_init(&cc, &crp->crp_buf);
4019c0e3d3aSJohn Baldwin 	crypto_cursor_advance(&cc, crp->crp_payload_start);
40226d292d3SJohn Baldwin 	for (resid = crp->crp_payload_length; resid >= blksz; resid -= len) {
40386be314dSJohn Baldwin 		inblk = crypto_cursor_segment(&cc, &len);
40426d292d3SJohn Baldwin 		if (len >= blksz) {
40526d292d3SJohn Baldwin 			len = rounddown(MIN(len, resid), blksz);
40626d292d3SJohn Baldwin 			crypto_cursor_advance(&cc, len);
40726d292d3SJohn Baldwin 		} else {
40826d292d3SJohn Baldwin 			len = blksz;
4099c0e3d3aSJohn Baldwin 			crypto_cursor_copydata(&cc, len, blk);
41026d292d3SJohn Baldwin 			inblk = blk;
41126d292d3SJohn Baldwin 		}
41226d292d3SJohn Baldwin 		axf->Update(&ctx, inblk, len);
41326d292d3SJohn Baldwin 	}
41426d292d3SJohn Baldwin 	if (resid > 0) {
41526d292d3SJohn Baldwin 		memset(blk, 0, blksz);
41626d292d3SJohn Baldwin 		crypto_cursor_copydata(&cc, resid, blk);
41708fca7a5SJohn-Mark Gurney 		axf->Update(&ctx, blk, blksz);
41808fca7a5SJohn-Mark Gurney 	}
41908fca7a5SJohn-Mark Gurney 
42008fca7a5SJohn-Mark Gurney 	/* length block */
42126d292d3SJohn Baldwin 	memset(blk, 0, blksz);
42208fca7a5SJohn-Mark Gurney 	blkp = (uint32_t *)blk + 1;
423c0341432SJohn Baldwin 	*blkp = htobe32(crp->crp_payload_length * 8);
42408fca7a5SJohn-Mark Gurney 	axf->Update(&ctx, blk, blksz);
425c0341432SJohn Baldwin 
426c0341432SJohn Baldwin 	/* Finalize MAC */
42726d292d3SJohn Baldwin 	axf->Final(tag, &ctx);
428c0341432SJohn Baldwin 
42920c128daSJohn Baldwin 	error = 0;
430c0341432SJohn Baldwin 	if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
43126d292d3SJohn Baldwin 		u_char tag2[GMAC_DIGEST_LEN];
43220c128daSJohn Baldwin 
433c0341432SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen,
43426d292d3SJohn Baldwin 		    tag2);
43526d292d3SJohn Baldwin 		if (timingsafe_bcmp(tag, tag2, swa->sw_mlen) != 0)
43620c128daSJohn Baldwin 			error = EBADMSG;
43726d292d3SJohn Baldwin 		explicit_bzero(tag2, sizeof(tag2));
438c0341432SJohn Baldwin 	} else {
439c0341432SJohn Baldwin 		/* Inject the authentication data */
44026d292d3SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag);
441c0341432SJohn Baldwin 	}
44220c128daSJohn Baldwin 	explicit_bzero(blkbuf, sizeof(blkbuf));
44326d292d3SJohn Baldwin 	explicit_bzero(tag, sizeof(tag));
44420c128daSJohn Baldwin 	explicit_bzero(iv, sizeof(iv));
44520c128daSJohn Baldwin 	return (error);
446c0341432SJohn Baldwin }
447c0341432SJohn Baldwin 
448c0341432SJohn Baldwin static int
449*dc475c9bSJohn Baldwin swcr_gcm(const struct swcr_session *ses, struct cryptop *crp)
450c0341432SJohn Baldwin {
45126d292d3SJohn Baldwin 	uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))];
452c0341432SJohn Baldwin 	u_char *blk = (u_char *)blkbuf;
45326d292d3SJohn Baldwin 	u_char tag[GMAC_DIGEST_LEN];
4549c0e3d3aSJohn Baldwin 	struct crypto_buffer_cursor cc_in, cc_out;
45526d292d3SJohn Baldwin 	const u_char *inblk;
45626d292d3SJohn Baldwin 	u_char *outblk;
457b54d1284SJohn Baldwin 	const struct swcr_auth *swa;
458b54d1284SJohn Baldwin 	const struct swcr_encdec *swe;
459d8787d4fSMark Johnston 	const struct enc_xform *exf;
460b54d1284SJohn Baldwin 	void *ctx;
461c0341432SJohn Baldwin 	uint32_t *blkp;
46286be314dSJohn Baldwin 	size_t len;
46386be314dSJohn Baldwin 	int blksz, error, ivlen, r, resid;
464c0341432SJohn Baldwin 
465c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
466c0341432SJohn Baldwin 	swe = &ses->swcr_encdec;
467c0341432SJohn Baldwin 	exf = swe->sw_exf;
468ab91fb6cSJohn Baldwin 	blksz = GMAC_BLOCK_LEN;
469ab91fb6cSJohn Baldwin 	KASSERT(blksz == exf->native_blocksize,
470723d8764SJohn Baldwin 	    ("%s: blocksize mismatch", __func__));
471c0341432SJohn Baldwin 
472c0341432SJohn Baldwin 	if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0)
473c0341432SJohn Baldwin 		return (EINVAL);
474c0341432SJohn Baldwin 
475c0341432SJohn Baldwin 	ivlen = AES_GCM_IV_LEN;
476c0341432SJohn Baldwin 
477b54d1284SJohn Baldwin 	ctx = __builtin_alloca(exf->ctxsize);
478ab91fb6cSJohn Baldwin 	if (crp->crp_cipher_key != NULL)
479b54d1284SJohn Baldwin 		exf->setkey(ctx, crp->crp_cipher_key,
480ab91fb6cSJohn Baldwin 		    crypto_get_params(crp->crp_session)->csp_cipher_klen);
481b54d1284SJohn Baldwin 	else
482b54d1284SJohn Baldwin 		memcpy(ctx, swe->sw_ctx, exf->ctxsize);
483b54d1284SJohn Baldwin 	exf->reinit(ctx, crp->crp_iv, ivlen);
484c0341432SJohn Baldwin 
485c0341432SJohn Baldwin 	/* Supply MAC with AAD */
4869b774dc0SJohn Baldwin 	if (crp->crp_aad != NULL) {
4879b774dc0SJohn Baldwin 		len = rounddown(crp->crp_aad_length, blksz);
4889b774dc0SJohn Baldwin 		if (len != 0)
489b54d1284SJohn Baldwin 			exf->update(ctx, crp->crp_aad, len);
4909b774dc0SJohn Baldwin 		if (crp->crp_aad_length != len) {
4919b774dc0SJohn Baldwin 			memset(blk, 0, blksz);
4929b774dc0SJohn Baldwin 			memcpy(blk, (char *)crp->crp_aad + len,
4939b774dc0SJohn Baldwin 			    crp->crp_aad_length - len);
494b54d1284SJohn Baldwin 			exf->update(ctx, blk, blksz);
4959b774dc0SJohn Baldwin 		}
4969b774dc0SJohn Baldwin 	} else {
4979c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_in, &crp->crp_buf);
4989c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_in, crp->crp_aad_start);
4999b774dc0SJohn Baldwin 		for (resid = crp->crp_aad_length; resid >= blksz;
5009b774dc0SJohn Baldwin 		     resid -= len) {
50186be314dSJohn Baldwin 			inblk = crypto_cursor_segment(&cc_in, &len);
50226d292d3SJohn Baldwin 			if (len >= blksz) {
50326d292d3SJohn Baldwin 				len = rounddown(MIN(len, resid), blksz);
50426d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_in, len);
50526d292d3SJohn Baldwin 			} else {
50626d292d3SJohn Baldwin 				len = blksz;
5079c0e3d3aSJohn Baldwin 				crypto_cursor_copydata(&cc_in, len, blk);
50826d292d3SJohn Baldwin 				inblk = blk;
50926d292d3SJohn Baldwin 			}
510b54d1284SJohn Baldwin 			exf->update(ctx, inblk, len);
51126d292d3SJohn Baldwin 		}
51226d292d3SJohn Baldwin 		if (resid > 0) {
51326d292d3SJohn Baldwin 			memset(blk, 0, blksz);
51426d292d3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, resid, blk);
515b54d1284SJohn Baldwin 			exf->update(ctx, blk, blksz);
516c0341432SJohn Baldwin 		}
5179b774dc0SJohn Baldwin 	}
518c0341432SJohn Baldwin 
519c0341432SJohn Baldwin 	/* Do encryption with MAC */
5209c0e3d3aSJohn Baldwin 	crypto_cursor_init(&cc_in, &crp->crp_buf);
5219c0e3d3aSJohn Baldwin 	crypto_cursor_advance(&cc_in, crp->crp_payload_start);
5229c0e3d3aSJohn Baldwin 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
5239c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_out, &crp->crp_obuf);
5249c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_out, crp->crp_payload_output_start);
5259c0e3d3aSJohn Baldwin 	} else
5269c0e3d3aSJohn Baldwin 		cc_out = cc_in;
52726d292d3SJohn Baldwin 	for (resid = crp->crp_payload_length; resid >= blksz; resid -= blksz) {
52886be314dSJohn Baldwin 		inblk = crypto_cursor_segment(&cc_in, &len);
52986be314dSJohn Baldwin 		if (len < blksz) {
53026d292d3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, blksz, blk);
53126d292d3SJohn Baldwin 			inblk = blk;
532c0341432SJohn Baldwin 		} else {
53326d292d3SJohn Baldwin 			crypto_cursor_advance(&cc_in, blksz);
534c0341432SJohn Baldwin 		}
53526d292d3SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
53686be314dSJohn Baldwin 			outblk = crypto_cursor_segment(&cc_out, &len);
53786be314dSJohn Baldwin 			if (len < blksz)
53826d292d3SJohn Baldwin 				outblk = blk;
539b54d1284SJohn Baldwin 			exf->encrypt(ctx, inblk, outblk);
540b54d1284SJohn Baldwin 			exf->update(ctx, outblk, blksz);
54126d292d3SJohn Baldwin 			if (outblk == blk)
54226d292d3SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
54326d292d3SJohn Baldwin 			else
54426d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_out, blksz);
54526d292d3SJohn Baldwin 		} else {
546b54d1284SJohn Baldwin 			exf->update(ctx, inblk, blksz);
54726d292d3SJohn Baldwin 		}
54826d292d3SJohn Baldwin 	}
54926d292d3SJohn Baldwin 	if (resid > 0) {
55026d292d3SJohn Baldwin 		crypto_cursor_copydata(&cc_in, resid, blk);
55126d292d3SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
552b54d1284SJohn Baldwin 			exf->encrypt_last(ctx, blk, blk, resid);
55326d292d3SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
55426d292d3SJohn Baldwin 		}
555b54d1284SJohn Baldwin 		exf->update(ctx, blk, resid);
556c0341432SJohn Baldwin 	}
557c0341432SJohn Baldwin 
558c0341432SJohn Baldwin 	/* length block */
55926d292d3SJohn Baldwin 	memset(blk, 0, blksz);
560c0341432SJohn Baldwin 	blkp = (uint32_t *)blk + 1;
561c0341432SJohn Baldwin 	*blkp = htobe32(crp->crp_aad_length * 8);
562c0341432SJohn Baldwin 	blkp = (uint32_t *)blk + 3;
563c0341432SJohn Baldwin 	*blkp = htobe32(crp->crp_payload_length * 8);
564b54d1284SJohn Baldwin 	exf->update(ctx, blk, blksz);
565c0341432SJohn Baldwin 
566c0341432SJohn Baldwin 	/* Finalize MAC */
567b54d1284SJohn Baldwin 	exf->final(tag, ctx);
568c0341432SJohn Baldwin 
569c0341432SJohn Baldwin 	/* Validate tag */
57020c128daSJohn Baldwin 	error = 0;
571c0341432SJohn Baldwin 	if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
57226d292d3SJohn Baldwin 		u_char tag2[GMAC_DIGEST_LEN];
57320c128daSJohn Baldwin 
57426d292d3SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, tag2);
575c0341432SJohn Baldwin 
57626d292d3SJohn Baldwin 		r = timingsafe_bcmp(tag, tag2, swa->sw_mlen);
57726d292d3SJohn Baldwin 		explicit_bzero(tag2, sizeof(tag2));
57820c128daSJohn Baldwin 		if (r != 0) {
57920c128daSJohn Baldwin 			error = EBADMSG;
58020c128daSJohn Baldwin 			goto out;
58120c128daSJohn Baldwin 		}
582c0341432SJohn Baldwin 
583c0341432SJohn Baldwin 		/* tag matches, decrypt data */
5849c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_in, &crp->crp_buf);
5859c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_in, crp->crp_payload_start);
58626d292d3SJohn Baldwin 		for (resid = crp->crp_payload_length; resid > blksz;
58726d292d3SJohn Baldwin 		     resid -= blksz) {
58886be314dSJohn Baldwin 			inblk = crypto_cursor_segment(&cc_in, &len);
58986be314dSJohn Baldwin 			if (len < blksz) {
59026d292d3SJohn Baldwin 				crypto_cursor_copydata(&cc_in, blksz, blk);
59126d292d3SJohn Baldwin 				inblk = blk;
59286be314dSJohn Baldwin 			} else
59326d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_in, blksz);
59486be314dSJohn Baldwin 			outblk = crypto_cursor_segment(&cc_out, &len);
59586be314dSJohn Baldwin 			if (len < blksz)
59626d292d3SJohn Baldwin 				outblk = blk;
597b54d1284SJohn Baldwin 			exf->decrypt(ctx, inblk, outblk);
59826d292d3SJohn Baldwin 			if (outblk == blk)
59926d292d3SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
60026d292d3SJohn Baldwin 			else
60126d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_out, blksz);
60226d292d3SJohn Baldwin 		}
60326d292d3SJohn Baldwin 		if (resid > 0) {
60426d292d3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, resid, blk);
605b54d1284SJohn Baldwin 			exf->decrypt_last(ctx, blk, blk, resid);
60626d292d3SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
607c0341432SJohn Baldwin 		}
608c0341432SJohn Baldwin 	} else {
609c0341432SJohn Baldwin 		/* Inject the authentication data */
61026d292d3SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag);
611c0341432SJohn Baldwin 	}
612c0341432SJohn Baldwin 
61320c128daSJohn Baldwin out:
614b54d1284SJohn Baldwin 	explicit_bzero(ctx, exf->ctxsize);
61520c128daSJohn Baldwin 	explicit_bzero(blkbuf, sizeof(blkbuf));
61626d292d3SJohn Baldwin 	explicit_bzero(tag, sizeof(tag));
61720c128daSJohn Baldwin 
61820c128daSJohn Baldwin 	return (error);
619c0341432SJohn Baldwin }
620c0341432SJohn Baldwin 
6214361c4ebSJohn Baldwin static void
6224361c4ebSJohn Baldwin build_ccm_b0(const char *nonce, u_int nonce_length, u_int aad_length,
6234361c4ebSJohn Baldwin     u_int data_length, u_int tag_length, uint8_t *b0)
6244361c4ebSJohn Baldwin {
6254361c4ebSJohn Baldwin 	uint8_t *bp;
6264361c4ebSJohn Baldwin 	uint8_t flags, L;
6274361c4ebSJohn Baldwin 
6284361c4ebSJohn Baldwin 	KASSERT(nonce_length >= 7 && nonce_length <= 13,
6294361c4ebSJohn Baldwin 	    ("nonce_length must be between 7 and 13 bytes"));
6304361c4ebSJohn Baldwin 
6314361c4ebSJohn Baldwin 	/*
6324361c4ebSJohn Baldwin 	 * Need to determine the L field value.  This is the number of
6334361c4ebSJohn Baldwin 	 * bytes needed to specify the length of the message; the length
6344361c4ebSJohn Baldwin 	 * is whatever is left in the 16 bytes after specifying flags and
6354361c4ebSJohn Baldwin 	 * the nonce.
6364361c4ebSJohn Baldwin 	 */
6374361c4ebSJohn Baldwin 	L = 15 - nonce_length;
6384361c4ebSJohn Baldwin 
6394361c4ebSJohn Baldwin 	flags = ((aad_length > 0) << 6) +
6404361c4ebSJohn Baldwin 	    (((tag_length - 2) / 2) << 3) +
6414361c4ebSJohn Baldwin 	    L - 1;
6424361c4ebSJohn Baldwin 
6434361c4ebSJohn Baldwin 	/*
6444361c4ebSJohn Baldwin 	 * Now we need to set up the first block, which has flags, nonce,
6454361c4ebSJohn Baldwin 	 * and the message length.
6464361c4ebSJohn Baldwin 	 */
6474361c4ebSJohn Baldwin 	b0[0] = flags;
6484361c4ebSJohn Baldwin 	memcpy(b0 + 1, nonce, nonce_length);
6494361c4ebSJohn Baldwin 	bp = b0 + 1 + nonce_length;
6504361c4ebSJohn Baldwin 
6514361c4ebSJohn Baldwin 	/* Need to copy L' [aka L-1] bytes of data_length */
6524361c4ebSJohn Baldwin 	for (uint8_t *dst = b0 + CCM_CBC_BLOCK_LEN - 1; dst >= bp; dst--) {
6534361c4ebSJohn Baldwin 		*dst = data_length;
6544361c4ebSJohn Baldwin 		data_length >>= 8;
6554361c4ebSJohn Baldwin 	}
6564361c4ebSJohn Baldwin }
6574361c4ebSJohn Baldwin 
6584361c4ebSJohn Baldwin /* NB: OCF only supports AAD lengths < 2^32. */
6594361c4ebSJohn Baldwin static int
6604361c4ebSJohn Baldwin build_ccm_aad_length(u_int aad_length, uint8_t *blk)
6614361c4ebSJohn Baldwin {
6624361c4ebSJohn Baldwin 	if (aad_length < ((1 << 16) - (1 << 8))) {
6634361c4ebSJohn Baldwin 		be16enc(blk, aad_length);
6644361c4ebSJohn Baldwin 		return (sizeof(uint16_t));
6654361c4ebSJohn Baldwin 	} else {
6664361c4ebSJohn Baldwin 		blk[0] = 0xff;
6674361c4ebSJohn Baldwin 		blk[1] = 0xfe;
6684361c4ebSJohn Baldwin 		be32enc(blk + 2, aad_length);
6694361c4ebSJohn Baldwin 		return (2 + sizeof(uint32_t));
6704361c4ebSJohn Baldwin 	}
6714361c4ebSJohn Baldwin }
6724361c4ebSJohn Baldwin 
673c0341432SJohn Baldwin static int
674*dc475c9bSJohn Baldwin swcr_ccm_cbc_mac(const struct swcr_session *ses, struct cryptop *crp)
675c0341432SJohn Baldwin {
67626d292d3SJohn Baldwin 	u_char iv[AES_BLOCK_LEN];
6774361c4ebSJohn Baldwin 	u_char blk[CCM_CBC_BLOCK_LEN];
6784361c4ebSJohn Baldwin 	u_char tag[AES_CBC_MAC_HASH_LEN];
679c0341432SJohn Baldwin 	union authctx ctx;
680ae18720dSJohn Baldwin 	const struct crypto_session_params *csp;
6816113a08bSJohn Baldwin 	const struct swcr_auth *swa;
682d8787d4fSMark Johnston 	const struct auth_hash *axf;
6834361c4ebSJohn Baldwin 	int error, ivlen, len;
684c0341432SJohn Baldwin 
685ae18720dSJohn Baldwin 	csp = crypto_get_params(crp->crp_session);
686c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
687c0341432SJohn Baldwin 	axf = swa->sw_axf;
688c0341432SJohn Baldwin 
6896113a08bSJohn Baldwin 	if (crp->crp_auth_key != NULL) {
6906113a08bSJohn Baldwin 		axf->Init(&ctx);
6916113a08bSJohn Baldwin 		axf->Setkey(&ctx, crp->crp_auth_key, csp->csp_auth_klen);
6926113a08bSJohn Baldwin 	} else
6936113a08bSJohn Baldwin 		memcpy(&ctx, swa->sw_ictx, axf->ctxsize);
694c0341432SJohn Baldwin 
695c0341432SJohn Baldwin 	/* Initialize the IV */
696ae18720dSJohn Baldwin 	ivlen = csp->csp_ivlen;
69729fe41ddSJohn Baldwin 	crypto_read_iv(crp, iv);
698c0341432SJohn Baldwin 
6994361c4ebSJohn Baldwin 	/* Supply MAC with IV */
7004361c4ebSJohn Baldwin 	axf->Reinit(&ctx, crp->crp_iv, ivlen);
701c0341432SJohn Baldwin 
7024361c4ebSJohn Baldwin 	/* Supply MAC with b0. */
7034361c4ebSJohn Baldwin 	build_ccm_b0(crp->crp_iv, ivlen, crp->crp_payload_length, 0,
7044361c4ebSJohn Baldwin 	    swa->sw_mlen, blk);
7054361c4ebSJohn Baldwin 	axf->Update(&ctx, blk, CCM_CBC_BLOCK_LEN);
7064361c4ebSJohn Baldwin 
7074361c4ebSJohn Baldwin 	len = build_ccm_aad_length(crp->crp_payload_length, blk);
7084361c4ebSJohn Baldwin 	axf->Update(&ctx, blk, len);
7094361c4ebSJohn Baldwin 
7104361c4ebSJohn Baldwin 	crypto_apply(crp, crp->crp_payload_start, crp->crp_payload_length,
7114361c4ebSJohn Baldwin 	    axf->Update, &ctx);
712c0341432SJohn Baldwin 
713c0341432SJohn Baldwin 	/* Finalize MAC */
71426d292d3SJohn Baldwin 	axf->Final(tag, &ctx);
715c0341432SJohn Baldwin 
7164361c4ebSJohn Baldwin 	error = 0;
717c0341432SJohn Baldwin 	if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
71826d292d3SJohn Baldwin 		u_char tag2[AES_CBC_MAC_HASH_LEN];
71920c128daSJohn Baldwin 
720c0341432SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen,
72126d292d3SJohn Baldwin 		    tag2);
72226d292d3SJohn Baldwin 		if (timingsafe_bcmp(tag, tag2, swa->sw_mlen) != 0)
72320c128daSJohn Baldwin 			error = EBADMSG;
72426d292d3SJohn Baldwin 		explicit_bzero(tag2, sizeof(tag));
725c0341432SJohn Baldwin 	} else {
726c0341432SJohn Baldwin 		/* Inject the authentication data */
72726d292d3SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag);
728c0341432SJohn Baldwin 	}
72926d292d3SJohn Baldwin 	explicit_bzero(tag, sizeof(tag));
7304361c4ebSJohn Baldwin 	explicit_bzero(blk, sizeof(blk));
73120c128daSJohn Baldwin 	explicit_bzero(iv, sizeof(iv));
73220c128daSJohn Baldwin 	return (error);
733c0341432SJohn Baldwin }
734c0341432SJohn Baldwin 
735c0341432SJohn Baldwin static int
736*dc475c9bSJohn Baldwin swcr_ccm(const struct swcr_session *ses, struct cryptop *crp)
737c0341432SJohn Baldwin {
738ae18720dSJohn Baldwin 	const struct crypto_session_params *csp;
73926d292d3SJohn Baldwin 	uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))];
740c0341432SJohn Baldwin 	u_char *blk = (u_char *)blkbuf;
74126d292d3SJohn Baldwin 	u_char tag[AES_CBC_MAC_HASH_LEN];
7429c0e3d3aSJohn Baldwin 	struct crypto_buffer_cursor cc_in, cc_out;
74326d292d3SJohn Baldwin 	const u_char *inblk;
74426d292d3SJohn Baldwin 	u_char *outblk;
745b54d1284SJohn Baldwin 	const struct swcr_auth *swa;
746b54d1284SJohn Baldwin 	const struct swcr_encdec *swe;
747d8787d4fSMark Johnston 	const struct enc_xform *exf;
748b54d1284SJohn Baldwin 	void *ctx;
74986be314dSJohn Baldwin 	size_t len;
75026d292d3SJohn Baldwin 	int blksz, error, ivlen, r, resid;
751c0341432SJohn Baldwin 
752ae18720dSJohn Baldwin 	csp = crypto_get_params(crp->crp_session);
753c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
754c0341432SJohn Baldwin 	swe = &ses->swcr_encdec;
755c0341432SJohn Baldwin 	exf = swe->sw_exf;
756ab91fb6cSJohn Baldwin 	blksz = AES_BLOCK_LEN;
757ab91fb6cSJohn Baldwin 	KASSERT(blksz == exf->native_blocksize,
758723d8764SJohn Baldwin 	    ("%s: blocksize mismatch", __func__));
759c0341432SJohn Baldwin 
760ae18720dSJohn Baldwin 	if (crp->crp_payload_length > ccm_max_payload_length(csp))
761ae18720dSJohn Baldwin 		return (EMSGSIZE);
762ae18720dSJohn Baldwin 
763c0341432SJohn Baldwin 	if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0)
764c0341432SJohn Baldwin 		return (EINVAL);
765c0341432SJohn Baldwin 
766ae18720dSJohn Baldwin 	ivlen = csp->csp_ivlen;
767c0341432SJohn Baldwin 
768b54d1284SJohn Baldwin 	ctx = __builtin_alloca(exf->ctxsize);
769ab91fb6cSJohn Baldwin 	if (crp->crp_cipher_key != NULL)
770b54d1284SJohn Baldwin 		exf->setkey(ctx, crp->crp_cipher_key,
771ab91fb6cSJohn Baldwin 		    crypto_get_params(crp->crp_session)->csp_cipher_klen);
772b54d1284SJohn Baldwin 	else
773b54d1284SJohn Baldwin 		memcpy(ctx, swe->sw_ctx, exf->ctxsize);
774b54d1284SJohn Baldwin 	exf->reinit(ctx, crp->crp_iv, ivlen);
775c0341432SJohn Baldwin 
7764361c4ebSJohn Baldwin 	/* Supply MAC with b0. */
7774361c4ebSJohn Baldwin 	_Static_assert(sizeof(blkbuf) >= CCM_CBC_BLOCK_LEN,
7784361c4ebSJohn Baldwin 	    "blkbuf too small for b0");
7794361c4ebSJohn Baldwin 	build_ccm_b0(crp->crp_iv, ivlen, crp->crp_aad_length,
7804361c4ebSJohn Baldwin 	    crp->crp_payload_length, swa->sw_mlen, blk);
781b54d1284SJohn Baldwin 	exf->update(ctx, blk, CCM_CBC_BLOCK_LEN);
7824361c4ebSJohn Baldwin 
783c0341432SJohn Baldwin 	/* Supply MAC with AAD */
7844361c4ebSJohn Baldwin 	if (crp->crp_aad_length != 0) {
7854361c4ebSJohn Baldwin 		len = build_ccm_aad_length(crp->crp_aad_length, blk);
786b54d1284SJohn Baldwin 		exf->update(ctx, blk, len);
7879b774dc0SJohn Baldwin 		if (crp->crp_aad != NULL)
788b54d1284SJohn Baldwin 			exf->update(ctx, crp->crp_aad, crp->crp_aad_length);
7899b774dc0SJohn Baldwin 		else
7904361c4ebSJohn Baldwin 			crypto_apply(crp, crp->crp_aad_start,
791b54d1284SJohn Baldwin 			    crp->crp_aad_length, exf->update, ctx);
7924361c4ebSJohn Baldwin 
7934361c4ebSJohn Baldwin 		/* Pad the AAD (including length field) to a full block. */
7944361c4ebSJohn Baldwin 		len = (len + crp->crp_aad_length) % CCM_CBC_BLOCK_LEN;
7954361c4ebSJohn Baldwin 		if (len != 0) {
7964361c4ebSJohn Baldwin 			len = CCM_CBC_BLOCK_LEN - len;
7974361c4ebSJohn Baldwin 			memset(blk, 0, CCM_CBC_BLOCK_LEN);
798b54d1284SJohn Baldwin 			exf->update(ctx, blk, len);
7994361c4ebSJohn Baldwin 		}
8004361c4ebSJohn Baldwin 	}
801c0341432SJohn Baldwin 
802c0341432SJohn Baldwin 	/* Do encryption/decryption with MAC */
8039c0e3d3aSJohn Baldwin 	crypto_cursor_init(&cc_in, &crp->crp_buf);
8049c0e3d3aSJohn Baldwin 	crypto_cursor_advance(&cc_in, crp->crp_payload_start);
8059c0e3d3aSJohn Baldwin 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
8069c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_out, &crp->crp_obuf);
8079c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_out, crp->crp_payload_output_start);
8089c0e3d3aSJohn Baldwin 	} else
8099c0e3d3aSJohn Baldwin 		cc_out = cc_in;
81026d292d3SJohn Baldwin 	for (resid = crp->crp_payload_length; resid >= blksz; resid -= blksz) {
81186be314dSJohn Baldwin 		inblk = crypto_cursor_segment(&cc_in, &len);
81286be314dSJohn Baldwin 		if (len < blksz) {
81326d292d3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, blksz, blk);
81426d292d3SJohn Baldwin 			inblk = blk;
81586be314dSJohn Baldwin 		} else
81626d292d3SJohn Baldwin 			crypto_cursor_advance(&cc_in, blksz);
817c0341432SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
81886be314dSJohn Baldwin 			outblk = crypto_cursor_segment(&cc_out, &len);
81986be314dSJohn Baldwin 			if (len < blksz)
82026d292d3SJohn Baldwin 				outblk = blk;
821b54d1284SJohn Baldwin 			exf->update(ctx, inblk, blksz);
822b54d1284SJohn Baldwin 			exf->encrypt(ctx, inblk, outblk);
82326d292d3SJohn Baldwin 			if (outblk == blk)
82426d292d3SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
82526d292d3SJohn Baldwin 			else
82626d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_out, blksz);
827c0341432SJohn Baldwin 		} else {
828c0341432SJohn Baldwin 			/*
829c0341432SJohn Baldwin 			 * One of the problems with CCM+CBC is that
830c0341432SJohn Baldwin 			 * the authentication is done on the
83126d292d3SJohn Baldwin 			 * unencrypted data.  As a result, we have to
832c0341432SJohn Baldwin 			 * decrypt the data twice: once to generate
833c0341432SJohn Baldwin 			 * the tag and a second time after the tag is
834c0341432SJohn Baldwin 			 * verified.
835c0341432SJohn Baldwin 			 */
836b54d1284SJohn Baldwin 			exf->decrypt(ctx, inblk, blk);
837b54d1284SJohn Baldwin 			exf->update(ctx, blk, blksz);
83826d292d3SJohn Baldwin 		}
83926d292d3SJohn Baldwin 	}
84026d292d3SJohn Baldwin 	if (resid > 0) {
84126d292d3SJohn Baldwin 		crypto_cursor_copydata(&cc_in, resid, blk);
84226d292d3SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
843b54d1284SJohn Baldwin 			exf->update(ctx, blk, resid);
844b54d1284SJohn Baldwin 			exf->encrypt_last(ctx, blk, blk, resid);
84526d292d3SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
84626d292d3SJohn Baldwin 		} else {
847b54d1284SJohn Baldwin 			exf->decrypt_last(ctx, blk, blk, resid);
848b54d1284SJohn Baldwin 			exf->update(ctx, blk, resid);
849c0341432SJohn Baldwin 		}
85008fca7a5SJohn-Mark Gurney 	}
85108fca7a5SJohn-Mark Gurney 
85208fca7a5SJohn-Mark Gurney 	/* Finalize MAC */
853b54d1284SJohn Baldwin 	exf->final(tag, ctx);
85408fca7a5SJohn-Mark Gurney 
85508fca7a5SJohn-Mark Gurney 	/* Validate tag */
85620c128daSJohn Baldwin 	error = 0;
857c0341432SJohn Baldwin 	if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
85826d292d3SJohn Baldwin 		u_char tag2[AES_CBC_MAC_HASH_LEN];
85920c128daSJohn Baldwin 
860c0341432SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen,
86126d292d3SJohn Baldwin 		    tag2);
86208fca7a5SJohn-Mark Gurney 
86326d292d3SJohn Baldwin 		r = timingsafe_bcmp(tag, tag2, swa->sw_mlen);
86426d292d3SJohn Baldwin 		explicit_bzero(tag2, sizeof(tag2));
86520c128daSJohn Baldwin 		if (r != 0) {
86620c128daSJohn Baldwin 			error = EBADMSG;
86720c128daSJohn Baldwin 			goto out;
86820c128daSJohn Baldwin 		}
869c0341432SJohn Baldwin 
87008fca7a5SJohn-Mark Gurney 		/* tag matches, decrypt data */
871b54d1284SJohn Baldwin 		exf->reinit(ctx, crp->crp_iv, ivlen);
8729c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_in, &crp->crp_buf);
8739c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_in, crp->crp_payload_start);
87426d292d3SJohn Baldwin 		for (resid = crp->crp_payload_length; resid > blksz;
87526d292d3SJohn Baldwin 		     resid -= blksz) {
87686be314dSJohn Baldwin 			inblk = crypto_cursor_segment(&cc_in, &len);
87786be314dSJohn Baldwin 			if (len < blksz) {
87826d292d3SJohn Baldwin 				crypto_cursor_copydata(&cc_in, blksz, blk);
87926d292d3SJohn Baldwin 				inblk = blk;
88086be314dSJohn Baldwin 			} else
88126d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_in, blksz);
88286be314dSJohn Baldwin 			outblk = crypto_cursor_segment(&cc_out, &len);
88386be314dSJohn Baldwin 			if (len < blksz)
88426d292d3SJohn Baldwin 				outblk = blk;
885b54d1284SJohn Baldwin 			exf->decrypt(ctx, inblk, outblk);
88626d292d3SJohn Baldwin 			if (outblk == blk)
88726d292d3SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
88826d292d3SJohn Baldwin 			else
88926d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_out, blksz);
89026d292d3SJohn Baldwin 		}
89126d292d3SJohn Baldwin 		if (resid > 0) {
89226d292d3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, resid, blk);
893b54d1284SJohn Baldwin 			exf->decrypt_last(ctx, blk, blk, resid);
89426d292d3SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
89508fca7a5SJohn-Mark Gurney 		}
89608fca7a5SJohn-Mark Gurney 	} else {
89708fca7a5SJohn-Mark Gurney 		/* Inject the authentication data */
89826d292d3SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag);
89908fca7a5SJohn-Mark Gurney 	}
90008fca7a5SJohn-Mark Gurney 
90120c128daSJohn Baldwin out:
902b54d1284SJohn Baldwin 	explicit_bzero(ctx, exf->ctxsize);
90320c128daSJohn Baldwin 	explicit_bzero(blkbuf, sizeof(blkbuf));
90426d292d3SJohn Baldwin 	explicit_bzero(tag, sizeof(tag));
90520c128daSJohn Baldwin 	return (error);
90608fca7a5SJohn-Mark Gurney }
90708fca7a5SJohn-Mark Gurney 
908dd2e1352SJohn Baldwin static int
909*dc475c9bSJohn Baldwin swcr_chacha20_poly1305(const struct swcr_session *ses, struct cryptop *crp)
910dd2e1352SJohn Baldwin {
911dd2e1352SJohn Baldwin 	const struct crypto_session_params *csp;
912dd2e1352SJohn Baldwin 	uint64_t blkbuf[howmany(CHACHA20_NATIVE_BLOCK_LEN, sizeof(uint64_t))];
913dd2e1352SJohn Baldwin 	u_char *blk = (u_char *)blkbuf;
914dd2e1352SJohn Baldwin 	u_char tag[POLY1305_HASH_LEN];
915dd2e1352SJohn Baldwin 	struct crypto_buffer_cursor cc_in, cc_out;
916dd2e1352SJohn Baldwin 	const u_char *inblk;
917dd2e1352SJohn Baldwin 	u_char *outblk;
918dd2e1352SJohn Baldwin 	uint64_t *blkp;
919b54d1284SJohn Baldwin 	const struct swcr_auth *swa;
920b54d1284SJohn Baldwin 	const struct swcr_encdec *swe;
921d8787d4fSMark Johnston 	const struct enc_xform *exf;
922b54d1284SJohn Baldwin 	void *ctx;
92386be314dSJohn Baldwin 	size_t len;
924dd2e1352SJohn Baldwin 	int blksz, error, r, resid;
925dd2e1352SJohn Baldwin 
926dd2e1352SJohn Baldwin 	swa = &ses->swcr_auth;
927dd2e1352SJohn Baldwin 	swe = &ses->swcr_encdec;
928dd2e1352SJohn Baldwin 	exf = swe->sw_exf;
929dd2e1352SJohn Baldwin 	blksz = exf->native_blocksize;
930dd2e1352SJohn Baldwin 	KASSERT(blksz <= sizeof(blkbuf), ("%s: blocksize mismatch", __func__));
931dd2e1352SJohn Baldwin 
932dd2e1352SJohn Baldwin 	if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0)
933dd2e1352SJohn Baldwin 		return (EINVAL);
934dd2e1352SJohn Baldwin 
935dd2e1352SJohn Baldwin 	csp = crypto_get_params(crp->crp_session);
936dd2e1352SJohn Baldwin 
937b54d1284SJohn Baldwin 	ctx = __builtin_alloca(exf->ctxsize);
938dd2e1352SJohn Baldwin 	if (crp->crp_cipher_key != NULL)
939b54d1284SJohn Baldwin 		exf->setkey(ctx, crp->crp_cipher_key,
940dd2e1352SJohn Baldwin 		    csp->csp_cipher_klen);
941b54d1284SJohn Baldwin 	else
942b54d1284SJohn Baldwin 		memcpy(ctx, swe->sw_ctx, exf->ctxsize);
943b54d1284SJohn Baldwin 	exf->reinit(ctx, crp->crp_iv, csp->csp_ivlen);
944dd2e1352SJohn Baldwin 
945ab91fb6cSJohn Baldwin 	/* Supply MAC with AAD */
946ab91fb6cSJohn Baldwin 	if (crp->crp_aad != NULL)
947b54d1284SJohn Baldwin 		exf->update(ctx, crp->crp_aad, crp->crp_aad_length);
948ab91fb6cSJohn Baldwin 	else
949b54d1284SJohn Baldwin 		crypto_apply(crp, crp->crp_aad_start, crp->crp_aad_length,
950b54d1284SJohn Baldwin 		    exf->update, ctx);
951ab91fb6cSJohn Baldwin 	if (crp->crp_aad_length % 16 != 0) {
952ab91fb6cSJohn Baldwin 		/* padding1 */
953ab91fb6cSJohn Baldwin 		memset(blk, 0, 16);
954b54d1284SJohn Baldwin 		exf->update(ctx, blk, 16 - crp->crp_aad_length % 16);
955ab91fb6cSJohn Baldwin 	}
956ab91fb6cSJohn Baldwin 
957dd2e1352SJohn Baldwin 	/* Do encryption with MAC */
958dd2e1352SJohn Baldwin 	crypto_cursor_init(&cc_in, &crp->crp_buf);
959dd2e1352SJohn Baldwin 	crypto_cursor_advance(&cc_in, crp->crp_payload_start);
960dd2e1352SJohn Baldwin 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
961dd2e1352SJohn Baldwin 		crypto_cursor_init(&cc_out, &crp->crp_obuf);
962dd2e1352SJohn Baldwin 		crypto_cursor_advance(&cc_out, crp->crp_payload_output_start);
963dd2e1352SJohn Baldwin 	} else
964dd2e1352SJohn Baldwin 		cc_out = cc_in;
965dd2e1352SJohn Baldwin 	for (resid = crp->crp_payload_length; resid >= blksz; resid -= blksz) {
96686be314dSJohn Baldwin 		inblk = crypto_cursor_segment(&cc_in, &len);
96786be314dSJohn Baldwin 		if (len < blksz) {
968dd2e1352SJohn Baldwin 			crypto_cursor_copydata(&cc_in, blksz, blk);
969dd2e1352SJohn Baldwin 			inblk = blk;
97086be314dSJohn Baldwin 		} else
971dd2e1352SJohn Baldwin 			crypto_cursor_advance(&cc_in, blksz);
972dd2e1352SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
97386be314dSJohn Baldwin 			outblk = crypto_cursor_segment(&cc_out, &len);
97486be314dSJohn Baldwin 			if (len < blksz)
975dd2e1352SJohn Baldwin 				outblk = blk;
976b54d1284SJohn Baldwin 			exf->encrypt(ctx, inblk, outblk);
977b54d1284SJohn Baldwin 			exf->update(ctx, outblk, blksz);
978dd2e1352SJohn Baldwin 			if (outblk == blk)
979dd2e1352SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
980dd2e1352SJohn Baldwin 			else
981dd2e1352SJohn Baldwin 				crypto_cursor_advance(&cc_out, blksz);
982dd2e1352SJohn Baldwin 		} else {
983b54d1284SJohn Baldwin 			exf->update(ctx, inblk, blksz);
984dd2e1352SJohn Baldwin 		}
985dd2e1352SJohn Baldwin 	}
986dd2e1352SJohn Baldwin 	if (resid > 0) {
987dd2e1352SJohn Baldwin 		crypto_cursor_copydata(&cc_in, resid, blk);
988dd2e1352SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
989b54d1284SJohn Baldwin 			exf->encrypt_last(ctx, blk, blk, resid);
990dd2e1352SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
991dd2e1352SJohn Baldwin 		}
992b54d1284SJohn Baldwin 		exf->update(ctx, blk, resid);
993dd2e1352SJohn Baldwin 		if (resid % 16 != 0) {
994dd2e1352SJohn Baldwin 			/* padding2 */
995dd2e1352SJohn Baldwin 			memset(blk, 0, 16);
996b54d1284SJohn Baldwin 			exf->update(ctx, blk, 16 - resid % 16);
997dd2e1352SJohn Baldwin 		}
998dd2e1352SJohn Baldwin 	}
999dd2e1352SJohn Baldwin 
1000dd2e1352SJohn Baldwin 	/* lengths */
1001dd2e1352SJohn Baldwin 	blkp = (uint64_t *)blk;
1002dd2e1352SJohn Baldwin 	blkp[0] = htole64(crp->crp_aad_length);
1003dd2e1352SJohn Baldwin 	blkp[1] = htole64(crp->crp_payload_length);
1004b54d1284SJohn Baldwin 	exf->update(ctx, blk, sizeof(uint64_t) * 2);
1005dd2e1352SJohn Baldwin 
1006dd2e1352SJohn Baldwin 	/* Finalize MAC */
1007b54d1284SJohn Baldwin 	exf->final(tag, ctx);
1008dd2e1352SJohn Baldwin 
1009dd2e1352SJohn Baldwin 	/* Validate tag */
1010dd2e1352SJohn Baldwin 	error = 0;
1011dd2e1352SJohn Baldwin 	if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
1012dd2e1352SJohn Baldwin 		u_char tag2[POLY1305_HASH_LEN];
1013dd2e1352SJohn Baldwin 
1014dd2e1352SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, tag2);
1015dd2e1352SJohn Baldwin 
1016dd2e1352SJohn Baldwin 		r = timingsafe_bcmp(tag, tag2, swa->sw_mlen);
1017dd2e1352SJohn Baldwin 		explicit_bzero(tag2, sizeof(tag2));
1018dd2e1352SJohn Baldwin 		if (r != 0) {
1019dd2e1352SJohn Baldwin 			error = EBADMSG;
1020dd2e1352SJohn Baldwin 			goto out;
1021dd2e1352SJohn Baldwin 		}
1022dd2e1352SJohn Baldwin 
1023dd2e1352SJohn Baldwin 		/* tag matches, decrypt data */
1024dd2e1352SJohn Baldwin 		crypto_cursor_init(&cc_in, &crp->crp_buf);
1025dd2e1352SJohn Baldwin 		crypto_cursor_advance(&cc_in, crp->crp_payload_start);
1026dd2e1352SJohn Baldwin 		for (resid = crp->crp_payload_length; resid > blksz;
1027dd2e1352SJohn Baldwin 		     resid -= blksz) {
102886be314dSJohn Baldwin 			inblk = crypto_cursor_segment(&cc_in, &len);
102986be314dSJohn Baldwin 			if (len < blksz) {
1030dd2e1352SJohn Baldwin 				crypto_cursor_copydata(&cc_in, blksz, blk);
1031dd2e1352SJohn Baldwin 				inblk = blk;
103286be314dSJohn Baldwin 			} else
1033dd2e1352SJohn Baldwin 				crypto_cursor_advance(&cc_in, blksz);
103486be314dSJohn Baldwin 			outblk = crypto_cursor_segment(&cc_out, &len);
103586be314dSJohn Baldwin 			if (len < blksz)
1036dd2e1352SJohn Baldwin 				outblk = blk;
1037b54d1284SJohn Baldwin 			exf->decrypt(ctx, inblk, outblk);
1038dd2e1352SJohn Baldwin 			if (outblk == blk)
1039dd2e1352SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
1040dd2e1352SJohn Baldwin 			else
1041dd2e1352SJohn Baldwin 				crypto_cursor_advance(&cc_out, blksz);
1042dd2e1352SJohn Baldwin 		}
1043dd2e1352SJohn Baldwin 		if (resid > 0) {
1044dd2e1352SJohn Baldwin 			crypto_cursor_copydata(&cc_in, resid, blk);
1045b54d1284SJohn Baldwin 			exf->decrypt_last(ctx, blk, blk, resid);
1046dd2e1352SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
1047dd2e1352SJohn Baldwin 		}
1048dd2e1352SJohn Baldwin 	} else {
1049dd2e1352SJohn Baldwin 		/* Inject the authentication data */
1050dd2e1352SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag);
1051dd2e1352SJohn Baldwin 	}
1052dd2e1352SJohn Baldwin 
1053dd2e1352SJohn Baldwin out:
1054b54d1284SJohn Baldwin 	explicit_bzero(ctx, exf->ctxsize);
1055dd2e1352SJohn Baldwin 	explicit_bzero(blkbuf, sizeof(blkbuf));
1056dd2e1352SJohn Baldwin 	explicit_bzero(tag, sizeof(tag));
1057dd2e1352SJohn Baldwin 	return (error);
1058dd2e1352SJohn Baldwin }
1059dd2e1352SJohn Baldwin 
1060091d81d1SSam Leffler /*
1061c0341432SJohn Baldwin  * Apply a cipher and a digest to perform EtA.
1062c0341432SJohn Baldwin  */
1063c0341432SJohn Baldwin static int
1064*dc475c9bSJohn Baldwin swcr_eta(const struct swcr_session *ses, struct cryptop *crp)
1065c0341432SJohn Baldwin {
1066c0341432SJohn Baldwin 	int error;
1067c0341432SJohn Baldwin 
1068c0341432SJohn Baldwin 	if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
1069c0341432SJohn Baldwin 		error = swcr_encdec(ses, crp);
1070c0341432SJohn Baldwin 		if (error == 0)
1071c0341432SJohn Baldwin 			error = swcr_authcompute(ses, crp);
1072c0341432SJohn Baldwin 	} else {
1073c0341432SJohn Baldwin 		error = swcr_authcompute(ses, crp);
1074c0341432SJohn Baldwin 		if (error == 0)
1075c0341432SJohn Baldwin 			error = swcr_encdec(ses, crp);
1076c0341432SJohn Baldwin 	}
1077c0341432SJohn Baldwin 	return (error);
1078c0341432SJohn Baldwin }
1079c0341432SJohn Baldwin 
1080c0341432SJohn Baldwin /*
1081091d81d1SSam Leffler  * Apply a compression/decompression algorithm
1082091d81d1SSam Leffler  */
1083091d81d1SSam Leffler static int
1084*dc475c9bSJohn Baldwin swcr_compdec(const struct swcr_session *ses, struct cryptop *crp)
1085091d81d1SSam Leffler {
1086d8787d4fSMark Johnston 	const struct comp_algo *cxf;
1087d3d79e96SJohn Baldwin 	uint8_t *data, *out;
1088091d81d1SSam Leffler 	int adj;
1089d3d79e96SJohn Baldwin 	uint32_t result;
1090091d81d1SSam Leffler 
1091c0341432SJohn Baldwin 	cxf = ses->swcr_compdec.sw_cxf;
1092091d81d1SSam Leffler 
1093091d81d1SSam Leffler 	/* We must handle the whole buffer of data in one time
1094091d81d1SSam Leffler 	 * then if there is not all the data in the mbuf, we must
1095091d81d1SSam Leffler 	 * copy in a buffer.
1096091d81d1SSam Leffler 	 */
1097091d81d1SSam Leffler 
1098c0341432SJohn Baldwin 	data = malloc(crp->crp_payload_length, M_CRYPTO_DATA,  M_NOWAIT);
1099091d81d1SSam Leffler 	if (data == NULL)
1100091d81d1SSam Leffler 		return (EINVAL);
1101c0341432SJohn Baldwin 	crypto_copydata(crp, crp->crp_payload_start, crp->crp_payload_length,
1102c0341432SJohn Baldwin 	    data);
1103091d81d1SSam Leffler 
1104c0341432SJohn Baldwin 	if (CRYPTO_OP_IS_COMPRESS(crp->crp_op))
1105c0341432SJohn Baldwin 		result = cxf->compress(data, crp->crp_payload_length, &out);
1106091d81d1SSam Leffler 	else
1107c0341432SJohn Baldwin 		result = cxf->decompress(data, crp->crp_payload_length, &out);
1108091d81d1SSam Leffler 
11091ede983cSDag-Erling Smørgrav 	free(data, M_CRYPTO_DATA);
1110091d81d1SSam Leffler 	if (result == 0)
1111c0341432SJohn Baldwin 		return (EINVAL);
1112c0341432SJohn Baldwin 	crp->crp_olen = result;
1113c0341432SJohn Baldwin 
1114c0341432SJohn Baldwin 	/* Check the compressed size when doing compression */
1115c0341432SJohn Baldwin 	if (CRYPTO_OP_IS_COMPRESS(crp->crp_op)) {
1116c0341432SJohn Baldwin 		if (result >= crp->crp_payload_length) {
1117c0341432SJohn Baldwin 			/* Compression was useless, we lost time */
1118c0341432SJohn Baldwin 			free(out, M_CRYPTO_DATA);
1119c0341432SJohn Baldwin 			return (0);
1120c0341432SJohn Baldwin 		}
1121c0341432SJohn Baldwin 	}
1122091d81d1SSam Leffler 
1123091d81d1SSam Leffler 	/* Copy back the (de)compressed data. m_copyback is
1124091d81d1SSam Leffler 	 * extending the mbuf as necessary.
1125091d81d1SSam Leffler 	 */
1126c0341432SJohn Baldwin 	crypto_copyback(crp, crp->crp_payload_start, result, out);
1127c0341432SJohn Baldwin 	if (result < crp->crp_payload_length) {
11289c0e3d3aSJohn Baldwin 		switch (crp->crp_buf.cb_type) {
1129c0341432SJohn Baldwin 		case CRYPTO_BUF_MBUF:
1130883a0196SJohn Baldwin 		case CRYPTO_BUF_SINGLE_MBUF:
1131c0341432SJohn Baldwin 			adj = result - crp->crp_payload_length;
11329c0e3d3aSJohn Baldwin 			m_adj(crp->crp_buf.cb_mbuf, adj);
1133c0341432SJohn Baldwin 			break;
1134c0341432SJohn Baldwin 		case CRYPTO_BUF_UIO: {
11359c0e3d3aSJohn Baldwin 			struct uio *uio = crp->crp_buf.cb_uio;
1136091d81d1SSam Leffler 			int ind;
1137091d81d1SSam Leffler 
1138c0341432SJohn Baldwin 			adj = crp->crp_payload_length - result;
1139091d81d1SSam Leffler 			ind = uio->uio_iovcnt - 1;
1140091d81d1SSam Leffler 
1141091d81d1SSam Leffler 			while (adj > 0 && ind >= 0) {
1142091d81d1SSam Leffler 				if (adj < uio->uio_iov[ind].iov_len) {
1143091d81d1SSam Leffler 					uio->uio_iov[ind].iov_len -= adj;
1144091d81d1SSam Leffler 					break;
1145091d81d1SSam Leffler 				}
1146091d81d1SSam Leffler 
1147091d81d1SSam Leffler 				adj -= uio->uio_iov[ind].iov_len;
1148091d81d1SSam Leffler 				uio->uio_iov[ind].iov_len = 0;
1149091d81d1SSam Leffler 				ind--;
1150091d81d1SSam Leffler 				uio->uio_iovcnt--;
1151091d81d1SSam Leffler 			}
1152091d81d1SSam Leffler 			}
1153c0341432SJohn Baldwin 			break;
1154e6f6d0c9SAlan Somers 		case CRYPTO_BUF_VMPAGE:
1155e6f6d0c9SAlan Somers 			adj = crp->crp_payload_length - result;
1156e6f6d0c9SAlan Somers 			crp->crp_buf.cb_vm_page_len -= adj;
1157e6f6d0c9SAlan Somers 			break;
11589c0e3d3aSJohn Baldwin 		default:
11599c0e3d3aSJohn Baldwin 			break;
1160c0341432SJohn Baldwin 		}
1161091d81d1SSam Leffler 	}
11621ede983cSDag-Erling Smørgrav 	free(out, M_CRYPTO_DATA);
1163091d81d1SSam Leffler 	return 0;
1164091d81d1SSam Leffler }
1165091d81d1SSam Leffler 
1166091d81d1SSam Leffler static int
11673e947048SJohn Baldwin swcr_setup_cipher(struct swcr_session *ses,
1168c0341432SJohn Baldwin     const struct crypto_session_params *csp)
1169091d81d1SSam Leffler {
1170c0341432SJohn Baldwin 	struct swcr_encdec *swe;
1171d8787d4fSMark Johnston 	const struct enc_xform *txf;
1172f6c4bc3bSPawel Jakub Dawidek 	int error;
1173091d81d1SSam Leffler 
1174c0341432SJohn Baldwin 	swe = &ses->swcr_encdec;
1175c0341432SJohn Baldwin 	txf = crypto_cipher(csp);
1176b54d1284SJohn Baldwin 	if (csp->csp_cipher_key != NULL) {
11773e947048SJohn Baldwin 		if (txf->ctxsize != 0) {
1178f313909aSJohn Baldwin 			swe->sw_ctx = malloc(txf->ctxsize, M_CRYPTO_DATA,
11793e947048SJohn Baldwin 			    M_NOWAIT);
1180f313909aSJohn Baldwin 			if (swe->sw_ctx == NULL)
11813e947048SJohn Baldwin 				return (ENOMEM);
11823e947048SJohn Baldwin 		}
1183f313909aSJohn Baldwin 		error = txf->setkey(swe->sw_ctx,
1184c0341432SJohn Baldwin 		    csp->csp_cipher_key, csp->csp_cipher_klen);
1185c0341432SJohn Baldwin 		if (error)
1186c0341432SJohn Baldwin 			return (error);
1187091d81d1SSam Leffler 	}
1188c0341432SJohn Baldwin 	swe->sw_exf = txf;
1189c0341432SJohn Baldwin 	return (0);
1190f6c4bc3bSPawel Jakub Dawidek }
1191091d81d1SSam Leffler 
1192c0341432SJohn Baldwin static int
1193c0341432SJohn Baldwin swcr_setup_auth(struct swcr_session *ses,
1194c0341432SJohn Baldwin     const struct crypto_session_params *csp)
1195c0341432SJohn Baldwin {
1196c0341432SJohn Baldwin 	struct swcr_auth *swa;
1197d8787d4fSMark Johnston 	const struct auth_hash *axf;
1198c0341432SJohn Baldwin 
1199c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
1200c0341432SJohn Baldwin 
1201c0341432SJohn Baldwin 	axf = crypto_auth_hash(csp);
1202c0341432SJohn Baldwin 	swa->sw_axf = axf;
1203c0341432SJohn Baldwin 	if (csp->csp_auth_mlen < 0 || csp->csp_auth_mlen > axf->hashsize)
1204c0341432SJohn Baldwin 		return (EINVAL);
1205c0341432SJohn Baldwin 	if (csp->csp_auth_mlen == 0)
1206c0341432SJohn Baldwin 		swa->sw_mlen = axf->hashsize;
1207c0341432SJohn Baldwin 	else
1208c0341432SJohn Baldwin 		swa->sw_mlen = csp->csp_auth_mlen;
12096113a08bSJohn Baldwin 	if (csp->csp_auth_klen == 0 || csp->csp_auth_key != NULL) {
12106113a08bSJohn Baldwin 		swa->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
12116113a08bSJohn Baldwin 		    M_NOWAIT);
1212c0341432SJohn Baldwin 		if (swa->sw_ictx == NULL)
1213c0341432SJohn Baldwin 			return (ENOBUFS);
12146113a08bSJohn Baldwin 	}
1215c0341432SJohn Baldwin 
1216c0341432SJohn Baldwin 	switch (csp->csp_auth_alg) {
1217091d81d1SSam Leffler 	case CRYPTO_SHA1_HMAC:
1218c97f39ceSConrad Meyer 	case CRYPTO_SHA2_224_HMAC:
1219f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_256_HMAC:
1220f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_384_HMAC:
1221f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_512_HMAC:
1222091d81d1SSam Leffler 	case CRYPTO_NULL_HMAC:
1223091d81d1SSam Leffler 	case CRYPTO_RIPEMD160_HMAC:
12246113a08bSJohn Baldwin 		swa->sw_hmac = true;
12256113a08bSJohn Baldwin 		if (csp->csp_auth_key != NULL) {
12263a0b6a93SJohn Baldwin 			swa->sw_octx = malloc(axf->ctxsize, M_CRYPTO_DATA,
1227091d81d1SSam Leffler 			    M_NOWAIT);
1228c0341432SJohn Baldwin 			if (swa->sw_octx == NULL)
1229c0341432SJohn Baldwin 				return (ENOBUFS);
12306113a08bSJohn Baldwin 			hmac_init_ipad(axf, csp->csp_auth_key,
12316113a08bSJohn Baldwin 			    csp->csp_auth_klen, swa->sw_ictx);
12326113a08bSJohn Baldwin 			hmac_init_opad(axf, csp->csp_auth_key,
12336113a08bSJohn Baldwin 			    csp->csp_auth_klen, swa->sw_octx);
1234091d81d1SSam Leffler 		}
1235091d81d1SSam Leffler 		break;
1236091d81d1SSam Leffler 	case CRYPTO_SHA1:
1237c4729f6eSConrad Meyer 	case CRYPTO_SHA2_224:
1238c4729f6eSConrad Meyer 	case CRYPTO_SHA2_256:
1239c4729f6eSConrad Meyer 	case CRYPTO_SHA2_384:
1240c4729f6eSConrad Meyer 	case CRYPTO_SHA2_512:
1241c0341432SJohn Baldwin 		axf->Init(swa->sw_ictx);
1242c0341432SJohn Baldwin 		break;
1243c0341432SJohn Baldwin 	case CRYPTO_AES_NIST_GMAC:
12446113a08bSJohn Baldwin 	case CRYPTO_AES_CCM_CBC_MAC:
12456113a08bSJohn Baldwin 	case CRYPTO_POLY1305:
12466113a08bSJohn Baldwin 		if (csp->csp_auth_key != NULL) {
1247c0341432SJohn Baldwin 			axf->Init(swa->sw_ictx);
1248c0341432SJohn Baldwin 			axf->Setkey(swa->sw_ictx, csp->csp_auth_key,
1249c0341432SJohn Baldwin 			    csp->csp_auth_klen);
12506113a08bSJohn Baldwin 		}
1251c0341432SJohn Baldwin 		break;
1252c0341432SJohn Baldwin 	case CRYPTO_BLAKE2B:
1253c0341432SJohn Baldwin 	case CRYPTO_BLAKE2S:
1254c0341432SJohn Baldwin 		/*
1255c0341432SJohn Baldwin 		 * Blake2b and Blake2s support an optional key but do
1256c0341432SJohn Baldwin 		 * not require one.
1257c0341432SJohn Baldwin 		 */
12586113a08bSJohn Baldwin 		if (csp->csp_auth_klen == 0)
12596113a08bSJohn Baldwin 			axf->Init(swa->sw_ictx);
12606113a08bSJohn Baldwin 		else if (csp->csp_auth_key != NULL)
1261c0341432SJohn Baldwin 			axf->Setkey(swa->sw_ictx, csp->csp_auth_key,
1262c0341432SJohn Baldwin 			    csp->csp_auth_klen);
12636113a08bSJohn Baldwin 		break;
12646113a08bSJohn Baldwin 	}
12656113a08bSJohn Baldwin 
12666113a08bSJohn Baldwin 	if (csp->csp_mode == CSP_MODE_DIGEST) {
12676113a08bSJohn Baldwin 		switch (csp->csp_auth_alg) {
12686113a08bSJohn Baldwin 		case CRYPTO_AES_NIST_GMAC:
12696113a08bSJohn Baldwin 			ses->swcr_process = swcr_gmac;
1270c0341432SJohn Baldwin 			break;
1271c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_CBC_MAC:
1272c0341432SJohn Baldwin 			ses->swcr_process = swcr_ccm_cbc_mac;
1273c0341432SJohn Baldwin 			break;
12746113a08bSJohn Baldwin 		default:
12756113a08bSJohn Baldwin 			ses->swcr_process = swcr_authcompute;
12766113a08bSJohn Baldwin 		}
1277091d81d1SSam Leffler 	}
1278091d81d1SSam Leffler 
1279c0341432SJohn Baldwin 	return (0);
1280c0341432SJohn Baldwin }
128108fca7a5SJohn-Mark Gurney 
1282c0341432SJohn Baldwin static int
1283ab91fb6cSJohn Baldwin swcr_setup_aead(struct swcr_session *ses,
1284c0341432SJohn Baldwin     const struct crypto_session_params *csp)
1285c0341432SJohn Baldwin {
1286c0341432SJohn Baldwin 	struct swcr_auth *swa;
1287ab91fb6cSJohn Baldwin 	int error;
1288c0341432SJohn Baldwin 
1289ab91fb6cSJohn Baldwin 	error = swcr_setup_cipher(ses, csp);
1290ab91fb6cSJohn Baldwin 	if (error)
1291ab91fb6cSJohn Baldwin 		return (error);
1292ab91fb6cSJohn Baldwin 
1293c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
1294c0341432SJohn Baldwin 	if (csp->csp_auth_mlen == 0)
1295ab91fb6cSJohn Baldwin 		swa->sw_mlen = ses->swcr_encdec.sw_exf->macsize;
1296c0341432SJohn Baldwin 	else
1297c0341432SJohn Baldwin 		swa->sw_mlen = csp->csp_auth_mlen;
1298ab91fb6cSJohn Baldwin 	return (0);
1299dd2e1352SJohn Baldwin }
1300dd2e1352SJohn Baldwin 
1301c0341432SJohn Baldwin static bool
1302c0341432SJohn Baldwin swcr_auth_supported(const struct crypto_session_params *csp)
1303109919c6SBenno Rice {
1304d8787d4fSMark Johnston 	const struct auth_hash *axf;
1305091d81d1SSam Leffler 
1306c0341432SJohn Baldwin 	axf = crypto_auth_hash(csp);
1307c0341432SJohn Baldwin 	if (axf == NULL)
1308c0341432SJohn Baldwin 		return (false);
1309c0341432SJohn Baldwin 	switch (csp->csp_auth_alg) {
1310091d81d1SSam Leffler 	case CRYPTO_SHA1_HMAC:
1311c97f39ceSConrad Meyer 	case CRYPTO_SHA2_224_HMAC:
1312f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_256_HMAC:
1313f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_384_HMAC:
1314f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_512_HMAC:
1315091d81d1SSam Leffler 	case CRYPTO_NULL_HMAC:
1316c0341432SJohn Baldwin 	case CRYPTO_RIPEMD160_HMAC:
1317091d81d1SSam Leffler 		break;
1318c0341432SJohn Baldwin 	case CRYPTO_AES_NIST_GMAC:
1319c0341432SJohn Baldwin 		switch (csp->csp_auth_klen * 8) {
1320c0341432SJohn Baldwin 		case 128:
1321c0341432SJohn Baldwin 		case 192:
1322c0341432SJohn Baldwin 		case 256:
1323c0341432SJohn Baldwin 			break;
1324c0341432SJohn Baldwin 		default:
1325c0341432SJohn Baldwin 			return (false);
1326c0341432SJohn Baldwin 		}
1327c0341432SJohn Baldwin 		if (csp->csp_auth_key == NULL)
1328c0341432SJohn Baldwin 			return (false);
1329c0341432SJohn Baldwin 		if (csp->csp_ivlen != AES_GCM_IV_LEN)
1330c0341432SJohn Baldwin 			return (false);
1331c0341432SJohn Baldwin 		break;
133225b7033bSConrad Meyer 	case CRYPTO_POLY1305:
1333c0341432SJohn Baldwin 		if (csp->csp_auth_klen != POLY1305_KEY_LEN)
1334c0341432SJohn Baldwin 			return (false);
1335c0341432SJohn Baldwin 		break;
1336c0341432SJohn Baldwin 	case CRYPTO_AES_CCM_CBC_MAC:
1337c0341432SJohn Baldwin 		switch (csp->csp_auth_klen * 8) {
1338c0341432SJohn Baldwin 		case 128:
1339c0341432SJohn Baldwin 		case 192:
1340c0341432SJohn Baldwin 		case 256:
1341c0341432SJohn Baldwin 			break;
1342c0341432SJohn Baldwin 		default:
1343c0341432SJohn Baldwin 			return (false);
1344c0341432SJohn Baldwin 		}
1345c0341432SJohn Baldwin 		if (csp->csp_auth_key == NULL)
1346c0341432SJohn Baldwin 			return (false);
1347c0341432SJohn Baldwin 		break;
1348c0341432SJohn Baldwin 	}
1349c0341432SJohn Baldwin 	return (true);
1350c0341432SJohn Baldwin }
1351091d81d1SSam Leffler 
1352c0341432SJohn Baldwin static bool
1353c0341432SJohn Baldwin swcr_cipher_supported(const struct crypto_session_params *csp)
1354c0341432SJohn Baldwin {
1355d8787d4fSMark Johnston 	const struct enc_xform *txf;
1356c0341432SJohn Baldwin 
1357c0341432SJohn Baldwin 	txf = crypto_cipher(csp);
1358c0341432SJohn Baldwin 	if (txf == NULL)
1359c0341432SJohn Baldwin 		return (false);
1360c0341432SJohn Baldwin 	if (csp->csp_cipher_alg != CRYPTO_NULL_CBC &&
1361c0341432SJohn Baldwin 	    txf->ivsize != csp->csp_ivlen)
1362c0341432SJohn Baldwin 		return (false);
1363c0341432SJohn Baldwin 	return (true);
1364c0341432SJohn Baldwin }
1365c0341432SJohn Baldwin 
13666038018aSMarcin Wojtas #define SUPPORTED_SES (CSP_F_SEPARATE_OUTPUT | CSP_F_SEPARATE_AAD | CSP_F_ESN)
13676038018aSMarcin Wojtas 
1368c0341432SJohn Baldwin static int
1369c0341432SJohn Baldwin swcr_probesession(device_t dev, const struct crypto_session_params *csp)
1370c0341432SJohn Baldwin {
13716038018aSMarcin Wojtas 	if ((csp->csp_flags & ~(SUPPORTED_SES)) != 0)
1372c0341432SJohn Baldwin 		return (EINVAL);
1373c0341432SJohn Baldwin 	switch (csp->csp_mode) {
1374c0341432SJohn Baldwin 	case CSP_MODE_COMPRESS:
1375c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1376c0341432SJohn Baldwin 		case CRYPTO_DEFLATE_COMP:
1377c0341432SJohn Baldwin 			break;
1378c0341432SJohn Baldwin 		default:
1379c0341432SJohn Baldwin 			return (EINVAL);
13805fbc5b5aSConrad Meyer 		}
1381091d81d1SSam Leffler 		break;
1382c0341432SJohn Baldwin 	case CSP_MODE_CIPHER:
1383c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1384c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1385c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1386dd2e1352SJohn Baldwin 		case CRYPTO_CHACHA20_POLY1305:
1387c0341432SJohn Baldwin 			return (EINVAL);
1388c0341432SJohn Baldwin 		default:
1389c0341432SJohn Baldwin 			if (!swcr_cipher_supported(csp))
1390c0341432SJohn Baldwin 				return (EINVAL);
1391091d81d1SSam Leffler 			break;
1392091d81d1SSam Leffler 		}
1393c0341432SJohn Baldwin 		break;
1394c0341432SJohn Baldwin 	case CSP_MODE_DIGEST:
1395c0341432SJohn Baldwin 		if (!swcr_auth_supported(csp))
1396c0341432SJohn Baldwin 			return (EINVAL);
1397c0341432SJohn Baldwin 		break;
1398c0341432SJohn Baldwin 	case CSP_MODE_AEAD:
1399c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1400c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1401c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1402c172a407SJohn Baldwin 			switch (csp->csp_cipher_klen * 8) {
1403c172a407SJohn Baldwin 			case 128:
1404c172a407SJohn Baldwin 			case 192:
1405c172a407SJohn Baldwin 			case 256:
1406c172a407SJohn Baldwin 				break;
1407c172a407SJohn Baldwin 			default:
1408c172a407SJohn Baldwin 				return (EINVAL);
1409c172a407SJohn Baldwin 			}
1410c172a407SJohn Baldwin 			break;
1411dd2e1352SJohn Baldwin 		case CRYPTO_CHACHA20_POLY1305:
1412c0341432SJohn Baldwin 			break;
1413c0341432SJohn Baldwin 		default:
1414c0341432SJohn Baldwin 			return (EINVAL);
1415c0341432SJohn Baldwin 		}
1416c0341432SJohn Baldwin 		break;
1417c0341432SJohn Baldwin 	case CSP_MODE_ETA:
1418c0341432SJohn Baldwin 		/* AEAD algorithms cannot be used for EtA. */
1419c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1420c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1421c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1422dd2e1352SJohn Baldwin 		case CRYPTO_CHACHA20_POLY1305:
1423c0341432SJohn Baldwin 			return (EINVAL);
1424c0341432SJohn Baldwin 		}
1425c0341432SJohn Baldwin 		switch (csp->csp_auth_alg) {
1426c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GMAC:
1427c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_CBC_MAC:
1428c0341432SJohn Baldwin 			return (EINVAL);
1429c0341432SJohn Baldwin 		}
1430c0341432SJohn Baldwin 
1431c0341432SJohn Baldwin 		if (!swcr_cipher_supported(csp) ||
1432c0341432SJohn Baldwin 		    !swcr_auth_supported(csp))
1433c0341432SJohn Baldwin 			return (EINVAL);
1434c0341432SJohn Baldwin 		break;
1435c0341432SJohn Baldwin 	default:
1436c0341432SJohn Baldwin 		return (EINVAL);
1437c0341432SJohn Baldwin 	}
1438c0341432SJohn Baldwin 
1439c0341432SJohn Baldwin 	return (CRYPTODEV_PROBE_SOFTWARE);
1440c0341432SJohn Baldwin }
1441c0341432SJohn Baldwin 
1442c0341432SJohn Baldwin /*
1443c0341432SJohn Baldwin  * Generate a new software session.
1444c0341432SJohn Baldwin  */
1445c0341432SJohn Baldwin static int
1446c0341432SJohn Baldwin swcr_newsession(device_t dev, crypto_session_t cses,
1447c0341432SJohn Baldwin     const struct crypto_session_params *csp)
1448c0341432SJohn Baldwin {
1449c0341432SJohn Baldwin 	struct swcr_session *ses;
1450d8787d4fSMark Johnston 	const struct comp_algo *cxf;
1451c0341432SJohn Baldwin 	int error;
1452c0341432SJohn Baldwin 
1453c0341432SJohn Baldwin 	ses = crypto_get_driver_session(cses);
1454c0341432SJohn Baldwin 
1455c0341432SJohn Baldwin 	error = 0;
1456c0341432SJohn Baldwin 	switch (csp->csp_mode) {
1457c0341432SJohn Baldwin 	case CSP_MODE_COMPRESS:
1458c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1459c0341432SJohn Baldwin 		case CRYPTO_DEFLATE_COMP:
1460c0341432SJohn Baldwin 			cxf = &comp_algo_deflate;
1461c0341432SJohn Baldwin 			break;
1462c0341432SJohn Baldwin #ifdef INVARIANTS
1463c0341432SJohn Baldwin 		default:
1464c0341432SJohn Baldwin 			panic("bad compression algo");
1465c0341432SJohn Baldwin #endif
1466c0341432SJohn Baldwin 		}
1467c0341432SJohn Baldwin 		ses->swcr_compdec.sw_cxf = cxf;
1468c0341432SJohn Baldwin 		ses->swcr_process = swcr_compdec;
1469c0341432SJohn Baldwin 		break;
1470c0341432SJohn Baldwin 	case CSP_MODE_CIPHER:
1471c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1472c0341432SJohn Baldwin 		case CRYPTO_NULL_CBC:
1473c0341432SJohn Baldwin 			ses->swcr_process = swcr_null;
1474c0341432SJohn Baldwin 			break;
1475c0341432SJohn Baldwin #ifdef INVARIANTS
1476c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1477c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1478dd2e1352SJohn Baldwin 		case CRYPTO_CHACHA20_POLY1305:
1479c0341432SJohn Baldwin 			panic("bad cipher algo");
1480c0341432SJohn Baldwin #endif
1481c0341432SJohn Baldwin 		default:
14823e947048SJohn Baldwin 			error = swcr_setup_cipher(ses, csp);
1483c0341432SJohn Baldwin 			if (error == 0)
1484c0341432SJohn Baldwin 				ses->swcr_process = swcr_encdec;
1485c0341432SJohn Baldwin 		}
1486c0341432SJohn Baldwin 		break;
1487c0341432SJohn Baldwin 	case CSP_MODE_DIGEST:
1488c0341432SJohn Baldwin 		error = swcr_setup_auth(ses, csp);
1489c0341432SJohn Baldwin 		break;
1490c0341432SJohn Baldwin 	case CSP_MODE_AEAD:
1491c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1492c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1493ab91fb6cSJohn Baldwin 			error = swcr_setup_aead(ses, csp);
1494c0341432SJohn Baldwin 			if (error == 0)
1495c0341432SJohn Baldwin 				ses->swcr_process = swcr_gcm;
1496c0341432SJohn Baldwin 			break;
1497c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1498ab91fb6cSJohn Baldwin 			error = swcr_setup_aead(ses, csp);
1499c0341432SJohn Baldwin 			if (error == 0)
1500c0341432SJohn Baldwin 				ses->swcr_process = swcr_ccm;
1501c0341432SJohn Baldwin 			break;
1502dd2e1352SJohn Baldwin 		case CRYPTO_CHACHA20_POLY1305:
1503ab91fb6cSJohn Baldwin 			error = swcr_setup_aead(ses, csp);
1504dd2e1352SJohn Baldwin 			if (error == 0)
1505dd2e1352SJohn Baldwin 				ses->swcr_process = swcr_chacha20_poly1305;
1506dd2e1352SJohn Baldwin 			break;
1507c0341432SJohn Baldwin #ifdef INVARIANTS
1508c0341432SJohn Baldwin 		default:
1509c0341432SJohn Baldwin 			panic("bad aead algo");
1510c0341432SJohn Baldwin #endif
1511c0341432SJohn Baldwin 		}
1512c0341432SJohn Baldwin 		break;
1513c0341432SJohn Baldwin 	case CSP_MODE_ETA:
1514c0341432SJohn Baldwin #ifdef INVARIANTS
1515c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1516c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1517c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1518dd2e1352SJohn Baldwin 		case CRYPTO_CHACHA20_POLY1305:
1519c0341432SJohn Baldwin 			panic("bad eta cipher algo");
1520c0341432SJohn Baldwin 		}
1521c0341432SJohn Baldwin 		switch (csp->csp_auth_alg) {
1522c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GMAC:
1523c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_CBC_MAC:
1524c0341432SJohn Baldwin 			panic("bad eta auth algo");
1525c0341432SJohn Baldwin 		}
1526c0341432SJohn Baldwin #endif
1527c0341432SJohn Baldwin 
1528c0341432SJohn Baldwin 		error = swcr_setup_auth(ses, csp);
1529c0341432SJohn Baldwin 		if (error)
1530c0341432SJohn Baldwin 			break;
1531c0341432SJohn Baldwin 		if (csp->csp_cipher_alg == CRYPTO_NULL_CBC) {
1532c0341432SJohn Baldwin 			/* Effectively degrade to digest mode. */
1533c0341432SJohn Baldwin 			ses->swcr_process = swcr_authcompute;
1534c0341432SJohn Baldwin 			break;
1535c0341432SJohn Baldwin 		}
1536c0341432SJohn Baldwin 
15373e947048SJohn Baldwin 		error = swcr_setup_cipher(ses, csp);
1538c0341432SJohn Baldwin 		if (error == 0)
1539c0341432SJohn Baldwin 			ses->swcr_process = swcr_eta;
1540c0341432SJohn Baldwin 		break;
1541c0341432SJohn Baldwin 	default:
1542c0341432SJohn Baldwin 		error = EINVAL;
1543c0341432SJohn Baldwin 	}
1544c0341432SJohn Baldwin 
1545c0341432SJohn Baldwin 	if (error)
1546c0341432SJohn Baldwin 		swcr_freesession(dev, cses);
1547c0341432SJohn Baldwin 	return (error);
1548c0341432SJohn Baldwin }
1549c0341432SJohn Baldwin 
1550c0341432SJohn Baldwin static void
1551c0341432SJohn Baldwin swcr_freesession(device_t dev, crypto_session_t cses)
1552c0341432SJohn Baldwin {
1553c0341432SJohn Baldwin 	struct swcr_session *ses;
1554c0341432SJohn Baldwin 
1555c0341432SJohn Baldwin 	ses = crypto_get_driver_session(cses);
1556c0341432SJohn Baldwin 
1557f313909aSJohn Baldwin 	zfree(ses->swcr_encdec.sw_ctx, M_CRYPTO_DATA);
15584a711b8dSJohn Baldwin 	zfree(ses->swcr_auth.sw_ictx, M_CRYPTO_DATA);
15594a711b8dSJohn Baldwin 	zfree(ses->swcr_auth.sw_octx, M_CRYPTO_DATA);
1560091d81d1SSam Leffler }
1561091d81d1SSam Leffler 
1562091d81d1SSam Leffler /*
1563091d81d1SSam Leffler  * Process a software request.
1564091d81d1SSam Leffler  */
1565091d81d1SSam Leffler static int
15666810ad6fSSam Leffler swcr_process(device_t dev, struct cryptop *crp, int hint)
1567091d81d1SSam Leffler {
1568c0341432SJohn Baldwin 	struct swcr_session *ses;
1569091d81d1SSam Leffler 
15701b0909d5SConrad Meyer 	ses = crypto_get_driver_session(crp->crp_session);
1571091d81d1SSam Leffler 
1572c0341432SJohn Baldwin 	crp->crp_etype = ses->swcr_process(ses, crp);
1573091d81d1SSam Leffler 
1574091d81d1SSam Leffler 	crypto_done(crp);
1575c0341432SJohn Baldwin 	return (0);
1576091d81d1SSam Leffler }
1577091d81d1SSam Leffler 
1578091d81d1SSam Leffler static void
15793f147ab2SWarner Losh swcr_identify(driver_t *drv, device_t parent)
1580091d81d1SSam Leffler {
15816810ad6fSSam Leffler 	/* NB: order 10 is so we get attached after h/w devices */
15826810ad6fSSam Leffler 	if (device_find_child(parent, "cryptosoft", -1) == NULL &&
158386c585d9SMarius Strobl 	    BUS_ADD_CHILD(parent, 10, "cryptosoft", 0) == 0)
15846810ad6fSSam Leffler 		panic("cryptosoft: could not attach");
15856810ad6fSSam Leffler }
1586f6c4bc3bSPawel Jakub Dawidek 
15876810ad6fSSam Leffler static int
15886810ad6fSSam Leffler swcr_probe(device_t dev)
15896810ad6fSSam Leffler {
15906810ad6fSSam Leffler 	device_set_desc(dev, "software crypto");
15914fc60fa9SMark Johnston 	device_quiet(dev);
159286c585d9SMarius Strobl 	return (BUS_PROBE_NOWILDCARD);
15936810ad6fSSam Leffler }
1594f6c4bc3bSPawel Jakub Dawidek 
15956810ad6fSSam Leffler static int
15966810ad6fSSam Leffler swcr_attach(device_t dev)
15976810ad6fSSam Leffler {
15986810ad6fSSam Leffler 
15999ebbebe4SConrad Meyer 	swcr_id = crypto_get_driverid(dev, sizeof(struct swcr_session),
16006810ad6fSSam Leffler 			CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC);
16016810ad6fSSam Leffler 	if (swcr_id < 0) {
16026810ad6fSSam Leffler 		device_printf(dev, "cannot initialize!");
1603c0341432SJohn Baldwin 		return (ENXIO);
16046810ad6fSSam Leffler 	}
16056810ad6fSSam Leffler 
1606c0341432SJohn Baldwin 	return (0);
1607091d81d1SSam Leffler }
16084b465da2SPawel Jakub Dawidek 
16093f147ab2SWarner Losh static int
16106810ad6fSSam Leffler swcr_detach(device_t dev)
16114b465da2SPawel Jakub Dawidek {
16126810ad6fSSam Leffler 	crypto_unregister_all(swcr_id);
16133f147ab2SWarner Losh 	return 0;
16144b465da2SPawel Jakub Dawidek }
16156810ad6fSSam Leffler 
16166810ad6fSSam Leffler static device_method_t swcr_methods[] = {
16176810ad6fSSam Leffler 	DEVMETHOD(device_identify,	swcr_identify),
16186810ad6fSSam Leffler 	DEVMETHOD(device_probe,		swcr_probe),
16196810ad6fSSam Leffler 	DEVMETHOD(device_attach,	swcr_attach),
16206810ad6fSSam Leffler 	DEVMETHOD(device_detach,	swcr_detach),
16216810ad6fSSam Leffler 
1622c0341432SJohn Baldwin 	DEVMETHOD(cryptodev_probesession, swcr_probesession),
16236810ad6fSSam Leffler 	DEVMETHOD(cryptodev_newsession,	swcr_newsession),
16246810ad6fSSam Leffler 	DEVMETHOD(cryptodev_freesession,swcr_freesession),
16256810ad6fSSam Leffler 	DEVMETHOD(cryptodev_process,	swcr_process),
16266810ad6fSSam Leffler 
16276810ad6fSSam Leffler 	{0, 0},
16286810ad6fSSam Leffler };
16296810ad6fSSam Leffler 
16306810ad6fSSam Leffler static driver_t swcr_driver = {
16316810ad6fSSam Leffler 	"cryptosoft",
16326810ad6fSSam Leffler 	swcr_methods,
16336810ad6fSSam Leffler 	0,		/* NB: no softc */
16346810ad6fSSam Leffler };
16356810ad6fSSam Leffler static devclass_t swcr_devclass;
16366810ad6fSSam Leffler 
16376810ad6fSSam Leffler /*
16386810ad6fSSam Leffler  * NB: We explicitly reference the crypto module so we
16396810ad6fSSam Leffler  * get the necessary ordering when built as a loadable
16406810ad6fSSam Leffler  * module.  This is required because we bundle the crypto
16416810ad6fSSam Leffler  * module code together with the cryptosoft driver (otherwise
16426810ad6fSSam Leffler  * normal module dependencies would handle things).
16436810ad6fSSam Leffler  */
16446810ad6fSSam Leffler extern int crypto_modevent(struct module *, int, void *);
16456810ad6fSSam Leffler /* XXX where to attach */
16466810ad6fSSam Leffler DRIVER_MODULE(cryptosoft, nexus, swcr_driver, swcr_devclass, crypto_modevent,0);
16476810ad6fSSam Leffler MODULE_VERSION(cryptosoft, 1);
16486810ad6fSSam Leffler MODULE_DEPEND(cryptosoft, crypto, 1, 1, 1);
1649