xref: /freebsd/sys/opencrypto/cryptosoft.c (revision fdafd315)
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 
34091d81d1SSam Leffler #include <sys/param.h>
35091d81d1SSam Leffler #include <sys/systm.h>
36091d81d1SSam Leffler #include <sys/malloc.h>
37091d81d1SSam Leffler #include <sys/mbuf.h>
386810ad6fSSam Leffler #include <sys/module.h>
39091d81d1SSam Leffler #include <sys/sysctl.h>
40091d81d1SSam Leffler #include <sys/errno.h>
41091d81d1SSam Leffler #include <sys/random.h>
42091d81d1SSam Leffler #include <sys/kernel.h>
43091d81d1SSam Leffler #include <sys/uio.h>
4408fca7a5SJohn-Mark Gurney #include <sys/endian.h>
4508fca7a5SJohn-Mark Gurney #include <sys/limits.h>
46091d81d1SSam Leffler 
47091d81d1SSam Leffler #include <crypto/sha1.h>
48091d81d1SSam Leffler #include <opencrypto/rmd160.h>
49091d81d1SSam Leffler 
50091d81d1SSam Leffler #include <opencrypto/cryptodev.h>
51091d81d1SSam Leffler #include <opencrypto/xform.h>
52091d81d1SSam Leffler 
536810ad6fSSam Leffler #include <sys/kobj.h>
546810ad6fSSam Leffler #include <sys/bus.h>
556810ad6fSSam Leffler #include "cryptodev_if.h"
56091d81d1SSam Leffler 
57c0341432SJohn Baldwin struct swcr_auth {
58c0341432SJohn Baldwin 	void		*sw_ictx;
59c0341432SJohn Baldwin 	void		*sw_octx;
60d8787d4fSMark Johnston 	const struct auth_hash *sw_axf;
61c0341432SJohn Baldwin 	uint16_t	sw_mlen;
626113a08bSJohn Baldwin 	bool		sw_hmac;
63c0341432SJohn Baldwin };
64c0341432SJohn Baldwin 
65c0341432SJohn Baldwin struct swcr_encdec {
66f313909aSJohn Baldwin 	void		*sw_ctx;
67d8787d4fSMark Johnston 	const struct enc_xform *sw_exf;
68c0341432SJohn Baldwin };
69c0341432SJohn Baldwin 
70c0341432SJohn Baldwin struct swcr_compdec {
71d8787d4fSMark Johnston 	const struct comp_algo *sw_cxf;
72c0341432SJohn Baldwin };
73c0341432SJohn Baldwin 
74c0341432SJohn Baldwin struct swcr_session {
75dc475c9bSJohn Baldwin 	int	(*swcr_process)(const struct swcr_session *, struct cryptop *);
76c0341432SJohn Baldwin 
77c0341432SJohn Baldwin 	struct swcr_auth swcr_auth;
78c0341432SJohn Baldwin 	struct swcr_encdec swcr_encdec;
79c0341432SJohn Baldwin 	struct swcr_compdec swcr_compdec;
80c0341432SJohn Baldwin };
81507281e5SSean Eric Fagan 
826810ad6fSSam Leffler static	int32_t swcr_id;
836810ad6fSSam Leffler 
841b0909d5SConrad Meyer static	void swcr_freesession(device_t dev, crypto_session_t cses);
85091d81d1SSam Leffler 
86c0341432SJohn Baldwin /* Used for CRYPTO_NULL_CBC. */
87c0341432SJohn Baldwin static int
swcr_null(const struct swcr_session * ses,struct cryptop * crp)88dc475c9bSJohn Baldwin swcr_null(const struct swcr_session *ses, struct cryptop *crp)
89c0341432SJohn Baldwin {
90c0341432SJohn Baldwin 
91c0341432SJohn Baldwin 	return (0);
92c0341432SJohn Baldwin }
93c0341432SJohn Baldwin 
94091d81d1SSam Leffler /*
95091d81d1SSam Leffler  * Apply a symmetric encryption/decryption algorithm.
96091d81d1SSam Leffler  */
97091d81d1SSam Leffler static int
swcr_encdec(const struct swcr_session * ses,struct cryptop * crp)98dc475c9bSJohn Baldwin swcr_encdec(const struct swcr_session *ses, struct cryptop *crp)
99091d81d1SSam Leffler {
1002cd83828SJohn Baldwin 	unsigned char blk[EALG_MAX_BLOCK_LEN];
101c0341432SJohn Baldwin 	const struct crypto_session_params *csp;
102d8787d4fSMark Johnston 	const struct enc_xform *exf;
103b54d1284SJohn Baldwin 	const struct swcr_encdec *sw;
104b54d1284SJohn Baldwin 	void *ctx;
105cfb7b942SJohn Baldwin 	size_t inlen, outlen, todo;
10669e533c3SJohn Baldwin 	int blksz, resid;
1079c0e3d3aSJohn Baldwin 	struct crypto_buffer_cursor cc_in, cc_out;
10826d292d3SJohn Baldwin 	const unsigned char *inblk;
10926d292d3SJohn Baldwin 	unsigned char *outblk;
11008fca7a5SJohn-Mark Gurney 	int error;
111c0341432SJohn Baldwin 	bool encrypting;
11208fca7a5SJohn-Mark Gurney 
11308fca7a5SJohn-Mark Gurney 	error = 0;
114091d81d1SSam Leffler 
115c0341432SJohn Baldwin 	sw = &ses->swcr_encdec;
116091d81d1SSam Leffler 	exf = sw->sw_exf;
1171833d604SJohn Baldwin 	csp = crypto_get_params(crp->crp_session);
118091d81d1SSam Leffler 
119723d8764SJohn Baldwin 	if (exf->native_blocksize == 0) {
120091d81d1SSam Leffler 		/* Check for non-padded data */
121723d8764SJohn Baldwin 		if ((crp->crp_payload_length % exf->blocksize) != 0)
122723d8764SJohn Baldwin 			return (EINVAL);
123723d8764SJohn Baldwin 
12469e533c3SJohn Baldwin 		blksz = exf->blocksize;
125723d8764SJohn Baldwin 	} else
12669e533c3SJohn Baldwin 		blksz = exf->native_blocksize;
127091d81d1SSam Leffler 
128c0341432SJohn Baldwin 	if (exf == &enc_xform_aes_icm &&
129c0341432SJohn Baldwin 	    (crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0)
13008fca7a5SJohn-Mark Gurney 		return (EINVAL);
13108fca7a5SJohn-Mark Gurney 
132b54d1284SJohn Baldwin 	ctx = __builtin_alloca(exf->ctxsize);
133c0341432SJohn Baldwin 	if (crp->crp_cipher_key != NULL) {
134b54d1284SJohn Baldwin 		error = exf->setkey(ctx, crp->crp_cipher_key,
135b54d1284SJohn Baldwin 		    csp->csp_cipher_klen);
136c740ae4bSPoul-Henning Kamp 		if (error)
137c740ae4bSPoul-Henning Kamp 			return (error);
138b54d1284SJohn Baldwin 	} else
139b54d1284SJohn Baldwin 		memcpy(ctx, sw->sw_ctx, exf->ctxsize);
140d295bdeeSPawel Jakub Dawidek 
1412cd83828SJohn Baldwin 	crypto_read_iv(crp, blk);
1422cd83828SJohn Baldwin 	exf->reinit(ctx, blk, csp->csp_ivlen);
143091d81d1SSam Leffler 
1449c0e3d3aSJohn Baldwin 	crypto_cursor_init(&cc_in, &crp->crp_buf);
1459c0e3d3aSJohn Baldwin 	crypto_cursor_advance(&cc_in, crp->crp_payload_start);
1469c0e3d3aSJohn Baldwin 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
1479c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_out, &crp->crp_obuf);
1489c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_out, crp->crp_payload_output_start);
1499c0e3d3aSJohn Baldwin 	} else
1509c0e3d3aSJohn Baldwin 		cc_out = cc_in;
1519c0e3d3aSJohn Baldwin 
152c0341432SJohn Baldwin 	encrypting = CRYPTO_OP_IS_ENCRYPT(crp->crp_op);
153091d81d1SSam Leffler 
154091d81d1SSam Leffler 	/*
1559c0e3d3aSJohn Baldwin 	 * Loop through encrypting blocks.  'inlen' is the remaining
1569c0e3d3aSJohn Baldwin 	 * length of the current segment in the input buffer.
1579c0e3d3aSJohn Baldwin 	 * 'outlen' is the remaining length of current segment in the
1589c0e3d3aSJohn Baldwin 	 * output buffer.
159091d81d1SSam Leffler 	 */
16050722514SMark Johnston 	inlen = outlen = 0;
16169e533c3SJohn Baldwin 	for (resid = crp->crp_payload_length; resid >= blksz; resid -= todo) {
16250722514SMark Johnston 		if (inlen == 0)
16350722514SMark Johnston 			inblk = crypto_cursor_segment(&cc_in, &inlen);
16450722514SMark Johnston 		if (outlen == 0)
16550722514SMark Johnston 			outblk = crypto_cursor_segment(&cc_out, &outlen);
16650722514SMark Johnston 
1679c0e3d3aSJohn Baldwin 		/*
1689c0e3d3aSJohn Baldwin 		 * If the current block is not contained within the
1699c0e3d3aSJohn Baldwin 		 * current input/output segment, use 'blk' as a local
1709c0e3d3aSJohn Baldwin 		 * buffer.
1719c0e3d3aSJohn Baldwin 		 */
17269e533c3SJohn Baldwin 		if (inlen < blksz) {
17369e533c3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, blksz, blk);
1749c0e3d3aSJohn Baldwin 			inblk = blk;
17569e533c3SJohn Baldwin 			inlen = blksz;
176d295bdeeSPawel Jakub Dawidek 		}
17769e533c3SJohn Baldwin 		if (outlen < blksz) {
1789c0e3d3aSJohn Baldwin 			outblk = blk;
17969e533c3SJohn Baldwin 			outlen = blksz;
180cfb7b942SJohn Baldwin 		}
181cfb7b942SJohn Baldwin 
18269e533c3SJohn Baldwin 		todo = rounddown2(MIN(resid, MIN(inlen, outlen)), blksz);
1839c0e3d3aSJohn Baldwin 
1849c0e3d3aSJohn Baldwin 		if (encrypting)
185cfb7b942SJohn Baldwin 			exf->encrypt_multi(ctx, inblk, outblk, todo);
1869c0e3d3aSJohn Baldwin 		else
187cfb7b942SJohn Baldwin 			exf->decrypt_multi(ctx, inblk, outblk, todo);
188091d81d1SSam Leffler 
189cfb7b942SJohn Baldwin 		if (inblk == blk) {
19086be314dSJohn Baldwin 			inblk = crypto_cursor_segment(&cc_in, &inlen);
1919c0e3d3aSJohn Baldwin 		} else {
192cfb7b942SJohn Baldwin 			crypto_cursor_advance(&cc_in, todo);
193cfb7b942SJohn Baldwin 			inlen -= todo;
194cfb7b942SJohn Baldwin 			inblk += todo;
19508fca7a5SJohn-Mark Gurney 		}
196091d81d1SSam Leffler 
197cfb7b942SJohn Baldwin 		if (outblk == blk) {
19869e533c3SJohn Baldwin 			crypto_cursor_copyback(&cc_out, blksz, blk);
19986be314dSJohn Baldwin 			outblk = crypto_cursor_segment(&cc_out, &outlen);
2009c0e3d3aSJohn Baldwin 		} else {
201cfb7b942SJohn Baldwin 			crypto_cursor_advance(&cc_out, todo);
202cfb7b942SJohn Baldwin 			outlen -= todo;
203cfb7b942SJohn Baldwin 			outblk += todo;
204091d81d1SSam Leffler 		}
205f34a967bSPawel Jakub Dawidek 	}
206f34a967bSPawel Jakub Dawidek 
207723d8764SJohn Baldwin 	/* Handle trailing partial block for stream ciphers. */
2089c0e3d3aSJohn Baldwin 	if (resid > 0) {
209723d8764SJohn Baldwin 		KASSERT(exf->native_blocksize != 0,
210723d8764SJohn Baldwin 		    ("%s: partial block of %d bytes for cipher %s",
2112cd83828SJohn Baldwin 		    __func__, resid, exf->name));
21269e533c3SJohn Baldwin 		KASSERT(resid < blksz, ("%s: partial block too big", __func__));
213723d8764SJohn Baldwin 
21486be314dSJohn Baldwin 		inblk = crypto_cursor_segment(&cc_in, &inlen);
21586be314dSJohn Baldwin 		outblk = crypto_cursor_segment(&cc_out, &outlen);
2169c0e3d3aSJohn Baldwin 		if (inlen < resid) {
2179c0e3d3aSJohn Baldwin 			crypto_cursor_copydata(&cc_in, resid, blk);
2189c0e3d3aSJohn Baldwin 			inblk = blk;
21986be314dSJohn Baldwin 		}
2209c0e3d3aSJohn Baldwin 		if (outlen < resid)
2219c0e3d3aSJohn Baldwin 			outblk = blk;
2229c0e3d3aSJohn Baldwin 		if (encrypting)
223b54d1284SJohn Baldwin 			exf->encrypt_last(ctx, inblk, outblk,
2249c0e3d3aSJohn Baldwin 			    resid);
2259c0e3d3aSJohn Baldwin 		else
226b54d1284SJohn Baldwin 			exf->decrypt_last(ctx, inblk, outblk,
2279c0e3d3aSJohn Baldwin 			    resid);
2289c0e3d3aSJohn Baldwin 		if (outlen < resid)
2299c0e3d3aSJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
230723d8764SJohn Baldwin 	}
231723d8764SJohn Baldwin 
232b54d1284SJohn Baldwin 	explicit_bzero(ctx, exf->ctxsize);
23320c128daSJohn Baldwin 	explicit_bzero(blk, sizeof(blk));
2349c0e3d3aSJohn Baldwin 	return (0);
235091d81d1SSam Leffler }
236091d81d1SSam Leffler 
237091d81d1SSam Leffler /*
238c0341432SJohn Baldwin  * Compute or verify hash.
239091d81d1SSam Leffler  */
240091d81d1SSam Leffler static int
swcr_authcompute(const struct swcr_session * ses,struct cryptop * crp)241dc475c9bSJohn Baldwin swcr_authcompute(const struct swcr_session *ses, struct cryptop *crp)
242091d81d1SSam Leffler {
2437051c579SJohn Baldwin 	struct {
2447051c579SJohn Baldwin 		union authctx ctx;
245c0341432SJohn Baldwin 		u_char aalg[HASH_MAX_LEN];
2467051c579SJohn Baldwin 		u_char uaalg[HASH_MAX_LEN];
2477051c579SJohn Baldwin 	} s;
248c0341432SJohn Baldwin 	const struct crypto_session_params *csp;
2496113a08bSJohn Baldwin 	const struct swcr_auth *sw;
250d8787d4fSMark Johnston 	const struct auth_hash *axf;
251091d81d1SSam Leffler 	int err;
252091d81d1SSam Leffler 
253c0341432SJohn Baldwin 	sw = &ses->swcr_auth;
254091d81d1SSam Leffler 
255091d81d1SSam Leffler 	axf = sw->sw_axf;
256091d81d1SSam Leffler 
257c0341432SJohn Baldwin 	csp = crypto_get_params(crp->crp_session);
2586038018aSMarcin Wojtas 	if (crp->crp_auth_key != NULL) {
2596113a08bSJohn Baldwin 		if (sw->sw_hmac) {
2606113a08bSJohn Baldwin 			hmac_init_ipad(axf, crp->crp_auth_key,
2617051c579SJohn Baldwin 			    csp->csp_auth_klen, &s.ctx);
2626113a08bSJohn Baldwin 		} else {
2637051c579SJohn Baldwin 			axf->Init(&s.ctx);
2647051c579SJohn Baldwin 			axf->Setkey(&s.ctx, crp->crp_auth_key,
265c0341432SJohn Baldwin 			    csp->csp_auth_klen);
26625b7033bSConrad Meyer 		}
2676113a08bSJohn Baldwin 	} else
2687051c579SJohn Baldwin 		memcpy(&s.ctx, sw->sw_ictx, axf->ctxsize);
269091d81d1SSam Leffler 
2709b774dc0SJohn Baldwin 	if (crp->crp_aad != NULL)
2717051c579SJohn Baldwin 		err = axf->Update(&s.ctx, crp->crp_aad, crp->crp_aad_length);
2729b774dc0SJohn Baldwin 	else
273c0341432SJohn Baldwin 		err = crypto_apply(crp, crp->crp_aad_start, crp->crp_aad_length,
2747051c579SJohn Baldwin 		    axf->Update, &s.ctx);
275091d81d1SSam Leffler 	if (err)
276e0b155feSJohn Baldwin 		goto out;
277091d81d1SSam Leffler 
2789c0e3d3aSJohn Baldwin 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp) &&
2799c0e3d3aSJohn Baldwin 	    CRYPTO_OP_IS_ENCRYPT(crp->crp_op))
2809c0e3d3aSJohn Baldwin 		err = crypto_apply_buf(&crp->crp_obuf,
2819c0e3d3aSJohn Baldwin 		    crp->crp_payload_output_start, crp->crp_payload_length,
2827051c579SJohn Baldwin 		    axf->Update, &s.ctx);
2839c0e3d3aSJohn Baldwin 	else
2849c0e3d3aSJohn Baldwin 		err = crypto_apply(crp, crp->crp_payload_start,
2857051c579SJohn Baldwin 		    crp->crp_payload_length, axf->Update, &s.ctx);
286c0341432SJohn Baldwin 	if (err)
287e0b155feSJohn Baldwin 		goto out;
288091d81d1SSam Leffler 
2896038018aSMarcin Wojtas 	if (csp->csp_flags & CSP_F_ESN)
2907051c579SJohn Baldwin 		axf->Update(&s.ctx, crp->crp_esn, 4);
2916038018aSMarcin Wojtas 
2927051c579SJohn Baldwin 	axf->Final(s.aalg, &s.ctx);
2936113a08bSJohn Baldwin 	if (sw->sw_hmac) {
2946113a08bSJohn Baldwin 		if (crp->crp_auth_key != NULL)
2956113a08bSJohn Baldwin 			hmac_init_opad(axf, crp->crp_auth_key,
2967051c579SJohn Baldwin 			    csp->csp_auth_klen, &s.ctx);
2976113a08bSJohn Baldwin 		else
2987051c579SJohn Baldwin 			memcpy(&s.ctx, sw->sw_octx, axf->ctxsize);
2997051c579SJohn Baldwin 		axf->Update(&s.ctx, s.aalg, axf->hashsize);
3007051c579SJohn Baldwin 		axf->Final(s.aalg, &s.ctx);
301091d81d1SSam Leffler 	}
302091d81d1SSam Leffler 
303c0341432SJohn Baldwin 	if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
3047051c579SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, sw->sw_mlen, s.uaalg);
3057051c579SJohn Baldwin 		if (timingsafe_bcmp(s.aalg, s.uaalg, sw->sw_mlen) != 0)
30620c128daSJohn Baldwin 			err = EBADMSG;
307c0341432SJohn Baldwin 	} else {
308091d81d1SSam Leffler 		/* Inject the authentication data */
3097051c579SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, sw->sw_mlen, s.aalg);
310c0341432SJohn Baldwin 	}
311e0b155feSJohn Baldwin out:
3127051c579SJohn Baldwin 	explicit_bzero(&s, sizeof(s));
31320c128daSJohn Baldwin 	return (err);
314091d81d1SSam Leffler }
315091d81d1SSam Leffler 
31608fca7a5SJohn-Mark Gurney CTASSERT(INT_MAX <= (1ll<<39) - 256);	/* GCM: plain text < 2^39-256 */
31708fca7a5SJohn-Mark Gurney CTASSERT(INT_MAX <= (uint64_t)-1);	/* GCM: associated data <= 2^64-1 */
31808fca7a5SJohn-Mark Gurney 
31908fca7a5SJohn-Mark Gurney static int
swcr_gmac(const struct swcr_session * ses,struct cryptop * crp)320dc475c9bSJohn Baldwin swcr_gmac(const struct swcr_session *ses, struct cryptop *crp)
32108fca7a5SJohn-Mark Gurney {
3227051c579SJohn Baldwin 	struct {
3237051c579SJohn Baldwin 		union authctx ctx;
32426d292d3SJohn Baldwin 		uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))];
32526d292d3SJohn Baldwin 		u_char tag[GMAC_DIGEST_LEN];
3267051c579SJohn Baldwin 		u_char tag2[GMAC_DIGEST_LEN];
3277051c579SJohn Baldwin 	} s;
3287051c579SJohn Baldwin 	u_char *blk = (u_char *)s.blkbuf;
3299c0e3d3aSJohn Baldwin 	struct crypto_buffer_cursor cc;
33026d292d3SJohn Baldwin 	const u_char *inblk;
3316113a08bSJohn Baldwin 	const struct swcr_auth *swa;
332d8787d4fSMark Johnston 	const struct auth_hash *axf;
33308fca7a5SJohn-Mark Gurney 	uint32_t *blkp;
33486be314dSJohn Baldwin 	size_t len;
33586be314dSJohn Baldwin 	int blksz, error, ivlen, resid;
33608fca7a5SJohn-Mark Gurney 
337c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
33808fca7a5SJohn-Mark Gurney 	axf = swa->sw_axf;
33926d292d3SJohn Baldwin 	blksz = GMAC_BLOCK_LEN;
34026d292d3SJohn Baldwin 	KASSERT(axf->blocksize == blksz, ("%s: axf block size mismatch",
34126d292d3SJohn Baldwin 	    __func__));
34208fca7a5SJohn-Mark Gurney 
3436113a08bSJohn Baldwin 	if (crp->crp_auth_key != NULL) {
3447051c579SJohn Baldwin 		axf->Init(&s.ctx);
3457051c579SJohn Baldwin 		axf->Setkey(&s.ctx, crp->crp_auth_key,
3466113a08bSJohn Baldwin 		    crypto_get_params(crp->crp_session)->csp_auth_klen);
3476113a08bSJohn Baldwin 	} else
3487051c579SJohn Baldwin 		memcpy(&s.ctx, swa->sw_ictx, axf->ctxsize);
3496113a08bSJohn Baldwin 
35008fca7a5SJohn-Mark Gurney 	/* Initialize the IV */
351c0341432SJohn Baldwin 	ivlen = AES_GCM_IV_LEN;
3521c9b25a5SJohn Baldwin 	crypto_read_iv(crp, blk);
35308fca7a5SJohn-Mark Gurney 
3547051c579SJohn Baldwin 	axf->Reinit(&s.ctx, blk, ivlen);
3559c0e3d3aSJohn Baldwin 	crypto_cursor_init(&cc, &crp->crp_buf);
3569c0e3d3aSJohn Baldwin 	crypto_cursor_advance(&cc, crp->crp_payload_start);
35726d292d3SJohn Baldwin 	for (resid = crp->crp_payload_length; resid >= blksz; resid -= len) {
35886be314dSJohn Baldwin 		inblk = crypto_cursor_segment(&cc, &len);
35926d292d3SJohn Baldwin 		if (len >= blksz) {
36026d292d3SJohn Baldwin 			len = rounddown(MIN(len, resid), blksz);
36126d292d3SJohn Baldwin 			crypto_cursor_advance(&cc, len);
36226d292d3SJohn Baldwin 		} else {
36326d292d3SJohn Baldwin 			len = blksz;
3649c0e3d3aSJohn Baldwin 			crypto_cursor_copydata(&cc, len, blk);
36526d292d3SJohn Baldwin 			inblk = blk;
36626d292d3SJohn Baldwin 		}
3677051c579SJohn Baldwin 		axf->Update(&s.ctx, inblk, len);
36826d292d3SJohn Baldwin 	}
36926d292d3SJohn Baldwin 	if (resid > 0) {
37026d292d3SJohn Baldwin 		memset(blk, 0, blksz);
37126d292d3SJohn Baldwin 		crypto_cursor_copydata(&cc, resid, blk);
3727051c579SJohn Baldwin 		axf->Update(&s.ctx, blk, blksz);
37308fca7a5SJohn-Mark Gurney 	}
37408fca7a5SJohn-Mark Gurney 
37508fca7a5SJohn-Mark Gurney 	/* length block */
37626d292d3SJohn Baldwin 	memset(blk, 0, blksz);
37708fca7a5SJohn-Mark Gurney 	blkp = (uint32_t *)blk + 1;
378c0341432SJohn Baldwin 	*blkp = htobe32(crp->crp_payload_length * 8);
3797051c579SJohn Baldwin 	axf->Update(&s.ctx, blk, blksz);
380c0341432SJohn Baldwin 
381c0341432SJohn Baldwin 	/* Finalize MAC */
3827051c579SJohn Baldwin 	axf->Final(s.tag, &s.ctx);
383c0341432SJohn Baldwin 
38420c128daSJohn Baldwin 	error = 0;
385c0341432SJohn Baldwin 	if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
386c0341432SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen,
3877051c579SJohn Baldwin 		    s.tag2);
3887051c579SJohn Baldwin 		if (timingsafe_bcmp(s.tag, s.tag2, swa->sw_mlen) != 0)
38920c128daSJohn Baldwin 			error = EBADMSG;
390c0341432SJohn Baldwin 	} else {
391c0341432SJohn Baldwin 		/* Inject the authentication data */
3927051c579SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, s.tag);
393c0341432SJohn Baldwin 	}
3947051c579SJohn Baldwin 	explicit_bzero(&s, sizeof(s));
39520c128daSJohn Baldwin 	return (error);
396c0341432SJohn Baldwin }
397c0341432SJohn Baldwin 
398c0341432SJohn Baldwin static int
swcr_gcm(const struct swcr_session * ses,struct cryptop * crp)399dc475c9bSJohn Baldwin swcr_gcm(const struct swcr_session *ses, struct cryptop *crp)
400c0341432SJohn Baldwin {
4017051c579SJohn Baldwin 	struct {
40226d292d3SJohn Baldwin 		uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))];
40326d292d3SJohn Baldwin 		u_char tag[GMAC_DIGEST_LEN];
4047051c579SJohn Baldwin 		u_char tag2[GMAC_DIGEST_LEN];
4057051c579SJohn Baldwin 	} s;
4067051c579SJohn Baldwin 	u_char *blk = (u_char *)s.blkbuf;
4079c0e3d3aSJohn Baldwin 	struct crypto_buffer_cursor cc_in, cc_out;
40826d292d3SJohn Baldwin 	const u_char *inblk;
40926d292d3SJohn Baldwin 	u_char *outblk;
410a221a8f4SJohn Baldwin 	size_t inlen, outlen, todo;
411b54d1284SJohn Baldwin 	const struct swcr_auth *swa;
412b54d1284SJohn Baldwin 	const struct swcr_encdec *swe;
413d8787d4fSMark Johnston 	const struct enc_xform *exf;
414b54d1284SJohn Baldwin 	void *ctx;
415c0341432SJohn Baldwin 	uint32_t *blkp;
41686be314dSJohn Baldwin 	int blksz, error, ivlen, r, resid;
417c0341432SJohn Baldwin 
418c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
419c0341432SJohn Baldwin 	swe = &ses->swcr_encdec;
420c0341432SJohn Baldwin 	exf = swe->sw_exf;
421ab91fb6cSJohn Baldwin 	blksz = GMAC_BLOCK_LEN;
422ab91fb6cSJohn Baldwin 	KASSERT(blksz == exf->native_blocksize,
423723d8764SJohn Baldwin 	    ("%s: blocksize mismatch", __func__));
424c0341432SJohn Baldwin 
425c0341432SJohn Baldwin 	if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0)
426c0341432SJohn Baldwin 		return (EINVAL);
427c0341432SJohn Baldwin 
428c0341432SJohn Baldwin 	ivlen = AES_GCM_IV_LEN;
429c0341432SJohn Baldwin 
430b54d1284SJohn Baldwin 	ctx = __builtin_alloca(exf->ctxsize);
431ab91fb6cSJohn Baldwin 	if (crp->crp_cipher_key != NULL)
432b54d1284SJohn Baldwin 		exf->setkey(ctx, crp->crp_cipher_key,
433ab91fb6cSJohn Baldwin 		    crypto_get_params(crp->crp_session)->csp_cipher_klen);
434b54d1284SJohn Baldwin 	else
435b54d1284SJohn Baldwin 		memcpy(ctx, swe->sw_ctx, exf->ctxsize);
436b54d1284SJohn Baldwin 	exf->reinit(ctx, crp->crp_iv, ivlen);
437c0341432SJohn Baldwin 
438c0341432SJohn Baldwin 	/* Supply MAC with AAD */
4399b774dc0SJohn Baldwin 	if (crp->crp_aad != NULL) {
440a221a8f4SJohn Baldwin 		inlen = rounddown2(crp->crp_aad_length, blksz);
441a221a8f4SJohn Baldwin 		if (inlen != 0)
442a221a8f4SJohn Baldwin 			exf->update(ctx, crp->crp_aad, inlen);
443a221a8f4SJohn Baldwin 		if (crp->crp_aad_length != inlen) {
4449b774dc0SJohn Baldwin 			memset(blk, 0, blksz);
445a221a8f4SJohn Baldwin 			memcpy(blk, (char *)crp->crp_aad + inlen,
446a221a8f4SJohn Baldwin 			    crp->crp_aad_length - inlen);
447b54d1284SJohn Baldwin 			exf->update(ctx, blk, blksz);
4489b774dc0SJohn Baldwin 		}
4499b774dc0SJohn Baldwin 	} else {
4509c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_in, &crp->crp_buf);
4519c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_in, crp->crp_aad_start);
4529b774dc0SJohn Baldwin 		for (resid = crp->crp_aad_length; resid >= blksz;
453a221a8f4SJohn Baldwin 		     resid -= inlen) {
454a221a8f4SJohn Baldwin 			inblk = crypto_cursor_segment(&cc_in, &inlen);
455a221a8f4SJohn Baldwin 			if (inlen >= blksz) {
456a221a8f4SJohn Baldwin 				inlen = rounddown2(MIN(inlen, resid), blksz);
457a221a8f4SJohn Baldwin 				crypto_cursor_advance(&cc_in, inlen);
45826d292d3SJohn Baldwin 			} else {
459a221a8f4SJohn Baldwin 				inlen = blksz;
460a221a8f4SJohn Baldwin 				crypto_cursor_copydata(&cc_in, inlen, blk);
46126d292d3SJohn Baldwin 				inblk = blk;
46226d292d3SJohn Baldwin 			}
463a221a8f4SJohn Baldwin 			exf->update(ctx, inblk, inlen);
46426d292d3SJohn Baldwin 		}
46526d292d3SJohn Baldwin 		if (resid > 0) {
46626d292d3SJohn Baldwin 			memset(blk, 0, blksz);
46726d292d3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, resid, blk);
468b54d1284SJohn Baldwin 			exf->update(ctx, blk, blksz);
469c0341432SJohn Baldwin 		}
4709b774dc0SJohn Baldwin 	}
471c0341432SJohn Baldwin 
472c0341432SJohn Baldwin 	/* Do encryption with MAC */
4739c0e3d3aSJohn Baldwin 	crypto_cursor_init(&cc_in, &crp->crp_buf);
4749c0e3d3aSJohn Baldwin 	crypto_cursor_advance(&cc_in, crp->crp_payload_start);
4759c0e3d3aSJohn Baldwin 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
4769c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_out, &crp->crp_obuf);
4779c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_out, crp->crp_payload_output_start);
4789c0e3d3aSJohn Baldwin 	} else
4799c0e3d3aSJohn Baldwin 		cc_out = cc_in;
48050722514SMark Johnston 
48150722514SMark Johnston 	inlen = outlen = 0;
48250722514SMark Johnston 	for (resid = crp->crp_payload_length; resid >= blksz; resid -= todo) {
48350722514SMark Johnston 		if (inlen == 0)
48450722514SMark Johnston 			inblk = crypto_cursor_segment(&cc_in, &inlen);
48550722514SMark Johnston 		if (outlen == 0)
486a221a8f4SJohn Baldwin 			outblk = crypto_cursor_segment(&cc_out, &outlen);
487a221a8f4SJohn Baldwin 
488a221a8f4SJohn Baldwin 		if (inlen < blksz) {
48926d292d3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, blksz, blk);
49026d292d3SJohn Baldwin 			inblk = blk;
491a221a8f4SJohn Baldwin 			inlen = blksz;
492c0341432SJohn Baldwin 		}
493a221a8f4SJohn Baldwin 
49426d292d3SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
495a221a8f4SJohn Baldwin 			if (outlen < blksz) {
49626d292d3SJohn Baldwin 				outblk = blk;
497a221a8f4SJohn Baldwin 				outlen = blksz;
498a221a8f4SJohn Baldwin 			}
499a221a8f4SJohn Baldwin 
500a221a8f4SJohn Baldwin 			todo = rounddown2(MIN(resid, MIN(inlen, outlen)),
501a221a8f4SJohn Baldwin 			    blksz);
502a221a8f4SJohn Baldwin 
503a221a8f4SJohn Baldwin 			exf->encrypt_multi(ctx, inblk, outblk, todo);
504a221a8f4SJohn Baldwin 			exf->update(ctx, outblk, todo);
505a221a8f4SJohn Baldwin 
506a221a8f4SJohn Baldwin 			if (outblk == blk) {
50726d292d3SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
508a221a8f4SJohn Baldwin 				outblk = crypto_cursor_segment(&cc_out, &outlen);
50926d292d3SJohn Baldwin 			} else {
510a221a8f4SJohn Baldwin 				crypto_cursor_advance(&cc_out, todo);
511a221a8f4SJohn Baldwin 				outlen -= todo;
512a221a8f4SJohn Baldwin 				outblk += todo;
513a221a8f4SJohn Baldwin 			}
514a221a8f4SJohn Baldwin 		} else {
515a221a8f4SJohn Baldwin 			todo = rounddown2(MIN(resid, inlen), blksz);
516a221a8f4SJohn Baldwin 			exf->update(ctx, inblk, todo);
517a221a8f4SJohn Baldwin 		}
518a221a8f4SJohn Baldwin 
519a221a8f4SJohn Baldwin 		if (inblk == blk) {
520a221a8f4SJohn Baldwin 			inblk = crypto_cursor_segment(&cc_in, &inlen);
521a221a8f4SJohn Baldwin 		} else {
522a221a8f4SJohn Baldwin 			crypto_cursor_advance(&cc_in, todo);
523a221a8f4SJohn Baldwin 			inlen -= todo;
524a221a8f4SJohn Baldwin 			inblk += todo;
52526d292d3SJohn Baldwin 		}
52626d292d3SJohn Baldwin 	}
52726d292d3SJohn Baldwin 	if (resid > 0) {
52826d292d3SJohn Baldwin 		crypto_cursor_copydata(&cc_in, resid, blk);
52926d292d3SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
530b54d1284SJohn Baldwin 			exf->encrypt_last(ctx, blk, blk, resid);
53126d292d3SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
53226d292d3SJohn Baldwin 		}
533b54d1284SJohn Baldwin 		exf->update(ctx, blk, resid);
534c0341432SJohn Baldwin 	}
535c0341432SJohn Baldwin 
536c0341432SJohn Baldwin 	/* length block */
53726d292d3SJohn Baldwin 	memset(blk, 0, blksz);
538c0341432SJohn Baldwin 	blkp = (uint32_t *)blk + 1;
539c0341432SJohn Baldwin 	*blkp = htobe32(crp->crp_aad_length * 8);
540c0341432SJohn Baldwin 	blkp = (uint32_t *)blk + 3;
541c0341432SJohn Baldwin 	*blkp = htobe32(crp->crp_payload_length * 8);
542b54d1284SJohn Baldwin 	exf->update(ctx, blk, blksz);
543c0341432SJohn Baldwin 
544c0341432SJohn Baldwin 	/* Finalize MAC */
5457051c579SJohn Baldwin 	exf->final(s.tag, ctx);
546c0341432SJohn Baldwin 
547c0341432SJohn Baldwin 	/* Validate tag */
54820c128daSJohn Baldwin 	error = 0;
549c0341432SJohn Baldwin 	if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
5507051c579SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen,
5517051c579SJohn Baldwin 		    s.tag2);
5527051c579SJohn Baldwin 		r = timingsafe_bcmp(s.tag, s.tag2, swa->sw_mlen);
55320c128daSJohn Baldwin 		if (r != 0) {
55420c128daSJohn Baldwin 			error = EBADMSG;
55520c128daSJohn Baldwin 			goto out;
55620c128daSJohn Baldwin 		}
557c0341432SJohn Baldwin 
558c0341432SJohn Baldwin 		/* tag matches, decrypt data */
5599c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_in, &crp->crp_buf);
5609c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_in, crp->crp_payload_start);
561a221a8f4SJohn Baldwin 
56250722514SMark Johnston 		inlen = 0;
56326d292d3SJohn Baldwin 		for (resid = crp->crp_payload_length; resid > blksz;
564a221a8f4SJohn Baldwin 		     resid -= todo) {
56550722514SMark Johnston 			if (inlen == 0)
56650722514SMark Johnston 				inblk = crypto_cursor_segment(&cc_in, &inlen);
56750722514SMark Johnston 			if (outlen == 0)
56850722514SMark Johnston 				outblk = crypto_cursor_segment(&cc_out, &outlen);
569a221a8f4SJohn Baldwin 			if (inlen < blksz) {
57026d292d3SJohn Baldwin 				crypto_cursor_copydata(&cc_in, blksz, blk);
57126d292d3SJohn Baldwin 				inblk = blk;
572a221a8f4SJohn Baldwin 				inlen = blksz;
573a221a8f4SJohn Baldwin 			}
574a221a8f4SJohn Baldwin 			if (outlen < blksz) {
57526d292d3SJohn Baldwin 				outblk = blk;
576a221a8f4SJohn Baldwin 				outlen = blksz;
577a221a8f4SJohn Baldwin 			}
578a221a8f4SJohn Baldwin 
579a221a8f4SJohn Baldwin 			todo = rounddown2(MIN(resid, MIN(inlen, outlen)),
580a221a8f4SJohn Baldwin 			    blksz);
581a221a8f4SJohn Baldwin 
582a221a8f4SJohn Baldwin 			exf->decrypt_multi(ctx, inblk, outblk, todo);
583a221a8f4SJohn Baldwin 
584a221a8f4SJohn Baldwin 			if (inblk == blk) {
585a221a8f4SJohn Baldwin 				inblk = crypto_cursor_segment(&cc_in, &inlen);
586a221a8f4SJohn Baldwin 			} else {
587a221a8f4SJohn Baldwin 				crypto_cursor_advance(&cc_in, todo);
588a221a8f4SJohn Baldwin 				inlen -= todo;
589a221a8f4SJohn Baldwin 				inblk += todo;
590a221a8f4SJohn Baldwin 			}
591a221a8f4SJohn Baldwin 
592a221a8f4SJohn Baldwin 			if (outblk == blk) {
59326d292d3SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
594a221a8f4SJohn Baldwin 				outblk = crypto_cursor_segment(&cc_out,
595a221a8f4SJohn Baldwin 				    &outlen);
596a221a8f4SJohn Baldwin 			} else {
597a221a8f4SJohn Baldwin 				crypto_cursor_advance(&cc_out, todo);
598a221a8f4SJohn Baldwin 				outlen -= todo;
599a221a8f4SJohn Baldwin 				outblk += todo;
600a221a8f4SJohn Baldwin 			}
60126d292d3SJohn Baldwin 		}
60226d292d3SJohn Baldwin 		if (resid > 0) {
60326d292d3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, resid, blk);
604b54d1284SJohn Baldwin 			exf->decrypt_last(ctx, blk, blk, resid);
60526d292d3SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
606c0341432SJohn Baldwin 		}
607c0341432SJohn Baldwin 	} else {
608c0341432SJohn Baldwin 		/* Inject the authentication data */
6097051c579SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen,
6107051c579SJohn Baldwin 		    s.tag);
611c0341432SJohn Baldwin 	}
612c0341432SJohn Baldwin 
61320c128daSJohn Baldwin out:
614b54d1284SJohn Baldwin 	explicit_bzero(ctx, exf->ctxsize);
6157051c579SJohn Baldwin 	explicit_bzero(&s, sizeof(s));
61620c128daSJohn Baldwin 
61720c128daSJohn Baldwin 	return (error);
618c0341432SJohn Baldwin }
619c0341432SJohn Baldwin 
6204361c4ebSJohn Baldwin static void
build_ccm_b0(const char * nonce,u_int nonce_length,u_int aad_length,u_int data_length,u_int tag_length,uint8_t * b0)6214361c4ebSJohn Baldwin build_ccm_b0(const char *nonce, u_int nonce_length, u_int aad_length,
6224361c4ebSJohn Baldwin     u_int data_length, u_int tag_length, uint8_t *b0)
6234361c4ebSJohn Baldwin {
6244361c4ebSJohn Baldwin 	uint8_t *bp;
6254361c4ebSJohn Baldwin 	uint8_t flags, L;
6264361c4ebSJohn Baldwin 
6274361c4ebSJohn Baldwin 	KASSERT(nonce_length >= 7 && nonce_length <= 13,
6284361c4ebSJohn Baldwin 	    ("nonce_length must be between 7 and 13 bytes"));
6294361c4ebSJohn Baldwin 
6304361c4ebSJohn Baldwin 	/*
6314361c4ebSJohn Baldwin 	 * Need to determine the L field value.  This is the number of
6324361c4ebSJohn Baldwin 	 * bytes needed to specify the length of the message; the length
6334361c4ebSJohn Baldwin 	 * is whatever is left in the 16 bytes after specifying flags and
6344361c4ebSJohn Baldwin 	 * the nonce.
6354361c4ebSJohn Baldwin 	 */
6364361c4ebSJohn Baldwin 	L = 15 - nonce_length;
6374361c4ebSJohn Baldwin 
6384361c4ebSJohn Baldwin 	flags = ((aad_length > 0) << 6) +
6394361c4ebSJohn Baldwin 	    (((tag_length - 2) / 2) << 3) +
6404361c4ebSJohn Baldwin 	    L - 1;
6414361c4ebSJohn Baldwin 
6424361c4ebSJohn Baldwin 	/*
6434361c4ebSJohn Baldwin 	 * Now we need to set up the first block, which has flags, nonce,
6444361c4ebSJohn Baldwin 	 * and the message length.
6454361c4ebSJohn Baldwin 	 */
6464361c4ebSJohn Baldwin 	b0[0] = flags;
6474361c4ebSJohn Baldwin 	memcpy(b0 + 1, nonce, nonce_length);
6484361c4ebSJohn Baldwin 	bp = b0 + 1 + nonce_length;
6494361c4ebSJohn Baldwin 
6504361c4ebSJohn Baldwin 	/* Need to copy L' [aka L-1] bytes of data_length */
6514361c4ebSJohn Baldwin 	for (uint8_t *dst = b0 + CCM_CBC_BLOCK_LEN - 1; dst >= bp; dst--) {
6524361c4ebSJohn Baldwin 		*dst = data_length;
6534361c4ebSJohn Baldwin 		data_length >>= 8;
6544361c4ebSJohn Baldwin 	}
6554361c4ebSJohn Baldwin }
6564361c4ebSJohn Baldwin 
6574361c4ebSJohn Baldwin /* NB: OCF only supports AAD lengths < 2^32. */
6584361c4ebSJohn Baldwin static int
build_ccm_aad_length(u_int aad_length,uint8_t * blk)6594361c4ebSJohn Baldwin build_ccm_aad_length(u_int aad_length, uint8_t *blk)
6604361c4ebSJohn Baldwin {
6614361c4ebSJohn Baldwin 	if (aad_length < ((1 << 16) - (1 << 8))) {
6624361c4ebSJohn Baldwin 		be16enc(blk, aad_length);
6634361c4ebSJohn Baldwin 		return (sizeof(uint16_t));
6644361c4ebSJohn Baldwin 	} else {
6654361c4ebSJohn Baldwin 		blk[0] = 0xff;
6664361c4ebSJohn Baldwin 		blk[1] = 0xfe;
6674361c4ebSJohn Baldwin 		be32enc(blk + 2, aad_length);
6684361c4ebSJohn Baldwin 		return (2 + sizeof(uint32_t));
6694361c4ebSJohn Baldwin 	}
6704361c4ebSJohn Baldwin }
6714361c4ebSJohn Baldwin 
672c0341432SJohn Baldwin static int
swcr_ccm_cbc_mac(const struct swcr_session * ses,struct cryptop * crp)673dc475c9bSJohn Baldwin swcr_ccm_cbc_mac(const struct swcr_session *ses, struct cryptop *crp)
674c0341432SJohn Baldwin {
6757051c579SJohn Baldwin 	struct {
6767051c579SJohn Baldwin 		union authctx ctx;
6774361c4ebSJohn Baldwin 		u_char blk[CCM_CBC_BLOCK_LEN];
6784361c4ebSJohn Baldwin 		u_char tag[AES_CBC_MAC_HASH_LEN];
6797051c579SJohn Baldwin 		u_char tag2[AES_CBC_MAC_HASH_LEN];
6807051c579SJohn Baldwin 	} s;
681ae18720dSJohn Baldwin 	const struct crypto_session_params *csp;
6826113a08bSJohn Baldwin 	const struct swcr_auth *swa;
683d8787d4fSMark Johnston 	const struct auth_hash *axf;
6844361c4ebSJohn Baldwin 	int error, ivlen, len;
685c0341432SJohn Baldwin 
686ae18720dSJohn Baldwin 	csp = crypto_get_params(crp->crp_session);
687c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
688c0341432SJohn Baldwin 	axf = swa->sw_axf;
689c0341432SJohn Baldwin 
6906113a08bSJohn Baldwin 	if (crp->crp_auth_key != NULL) {
6917051c579SJohn Baldwin 		axf->Init(&s.ctx);
6927051c579SJohn Baldwin 		axf->Setkey(&s.ctx, crp->crp_auth_key, csp->csp_auth_klen);
6936113a08bSJohn Baldwin 	} else
6947051c579SJohn Baldwin 		memcpy(&s.ctx, swa->sw_ictx, axf->ctxsize);
695c0341432SJohn Baldwin 
696c0341432SJohn Baldwin 	/* Initialize the IV */
697ae18720dSJohn Baldwin 	ivlen = csp->csp_ivlen;
698c0341432SJohn Baldwin 
6994361c4ebSJohn Baldwin 	/* Supply MAC with IV */
7007051c579SJohn Baldwin 	axf->Reinit(&s.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,
7047051c579SJohn Baldwin 	    swa->sw_mlen, s.blk);
7057051c579SJohn Baldwin 	axf->Update(&s.ctx, s.blk, CCM_CBC_BLOCK_LEN);
7064361c4ebSJohn Baldwin 
7077051c579SJohn Baldwin 	len = build_ccm_aad_length(crp->crp_payload_length, s.blk);
7087051c579SJohn Baldwin 	axf->Update(&s.ctx, s.blk, len);
7094361c4ebSJohn Baldwin 
7104361c4ebSJohn Baldwin 	crypto_apply(crp, crp->crp_payload_start, crp->crp_payload_length,
7117051c579SJohn Baldwin 	    axf->Update, &s.ctx);
712c0341432SJohn Baldwin 
713c0341432SJohn Baldwin 	/* Finalize MAC */
7147051c579SJohn Baldwin 	axf->Final(s.tag, &s.ctx);
715c0341432SJohn Baldwin 
7164361c4ebSJohn Baldwin 	error = 0;
717c0341432SJohn Baldwin 	if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
718c0341432SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen,
7197051c579SJohn Baldwin 		    s.tag2);
7207051c579SJohn Baldwin 		if (timingsafe_bcmp(s.tag, s.tag2, swa->sw_mlen) != 0)
72120c128daSJohn Baldwin 			error = EBADMSG;
722c0341432SJohn Baldwin 	} else {
723c0341432SJohn Baldwin 		/* Inject the authentication data */
7247051c579SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen,
7257051c579SJohn Baldwin 		    s.tag);
726c0341432SJohn Baldwin 	}
7277051c579SJohn Baldwin 	explicit_bzero(&s, sizeof(s));
72820c128daSJohn Baldwin 	return (error);
729c0341432SJohn Baldwin }
730c0341432SJohn Baldwin 
731c0341432SJohn Baldwin static int
swcr_ccm(const struct swcr_session * ses,struct cryptop * crp)732dc475c9bSJohn Baldwin swcr_ccm(const struct swcr_session *ses, struct cryptop *crp)
733c0341432SJohn Baldwin {
734ae18720dSJohn Baldwin 	const struct crypto_session_params *csp;
7357051c579SJohn Baldwin 	struct {
73626d292d3SJohn Baldwin 		uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))];
73726d292d3SJohn Baldwin 		u_char tag[AES_CBC_MAC_HASH_LEN];
7387051c579SJohn Baldwin 		u_char tag2[AES_CBC_MAC_HASH_LEN];
7397051c579SJohn Baldwin 	} s;
7407051c579SJohn Baldwin 	u_char *blk = (u_char *)s.blkbuf;
7419c0e3d3aSJohn Baldwin 	struct crypto_buffer_cursor cc_in, cc_out;
74226d292d3SJohn Baldwin 	const u_char *inblk;
74326d292d3SJohn Baldwin 	u_char *outblk;
744f8580fcaSJohn Baldwin 	size_t inlen, outlen, todo;
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. */
7777051c579SJohn Baldwin 	_Static_assert(sizeof(s.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;
81050722514SMark Johnston 
81150722514SMark Johnston 	inlen = outlen = 0;
81250722514SMark Johnston 	for (resid = crp->crp_payload_length; resid >= blksz; resid -= todo) {
81350722514SMark Johnston 		if (inlen == 0)
81450722514SMark Johnston 			inblk = crypto_cursor_segment(&cc_in, &inlen);
81550722514SMark Johnston 		if (outlen == 0)
816f8580fcaSJohn Baldwin 			outblk = crypto_cursor_segment(&cc_out, &outlen);
817f8580fcaSJohn Baldwin 
818f8580fcaSJohn Baldwin 		if (inlen < blksz) {
81926d292d3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, blksz, blk);
82026d292d3SJohn Baldwin 			inblk = blk;
821f8580fcaSJohn Baldwin 			inlen = blksz;
822f8580fcaSJohn Baldwin 		}
823f8580fcaSJohn Baldwin 
824c0341432SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
825f8580fcaSJohn Baldwin 			if (outlen < blksz) {
82626d292d3SJohn Baldwin 				outblk = blk;
827f8580fcaSJohn Baldwin 				outlen = blksz;
828f8580fcaSJohn Baldwin 			}
829f8580fcaSJohn Baldwin 
830f8580fcaSJohn Baldwin 			todo = rounddown2(MIN(resid, MIN(inlen, outlen)),
831f8580fcaSJohn Baldwin 			    blksz);
832f8580fcaSJohn Baldwin 
833f8580fcaSJohn Baldwin 			exf->update(ctx, inblk, todo);
834f8580fcaSJohn Baldwin 			exf->encrypt_multi(ctx, inblk, outblk, todo);
835f8580fcaSJohn Baldwin 
836f8580fcaSJohn Baldwin 			if (outblk == blk) {
83726d292d3SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
838f8580fcaSJohn Baldwin 				outblk = crypto_cursor_segment(&cc_out, &outlen);
839f8580fcaSJohn Baldwin 			} else {
840f8580fcaSJohn Baldwin 				crypto_cursor_advance(&cc_out, todo);
841f8580fcaSJohn Baldwin 				outlen -= todo;
842f8580fcaSJohn Baldwin 				outblk += todo;
843f8580fcaSJohn Baldwin 			}
844c0341432SJohn Baldwin 		} else {
845c0341432SJohn Baldwin 			/*
846c0341432SJohn Baldwin 			 * One of the problems with CCM+CBC is that
847c0341432SJohn Baldwin 			 * the authentication is done on the
84826d292d3SJohn Baldwin 			 * unencrypted data.  As a result, we have to
849c0341432SJohn Baldwin 			 * decrypt the data twice: once to generate
850c0341432SJohn Baldwin 			 * the tag and a second time after the tag is
851c0341432SJohn Baldwin 			 * verified.
852c0341432SJohn Baldwin 			 */
853f8580fcaSJohn Baldwin 			todo = blksz;
854b54d1284SJohn Baldwin 			exf->decrypt(ctx, inblk, blk);
855f8580fcaSJohn Baldwin 			exf->update(ctx, blk, todo);
856f8580fcaSJohn Baldwin 		}
857f8580fcaSJohn Baldwin 
858f8580fcaSJohn Baldwin 		if (inblk == blk) {
859f8580fcaSJohn Baldwin 			inblk = crypto_cursor_segment(&cc_in, &inlen);
860f8580fcaSJohn Baldwin 		} else {
861f8580fcaSJohn Baldwin 			crypto_cursor_advance(&cc_in, todo);
862f8580fcaSJohn Baldwin 			inlen -= todo;
863f8580fcaSJohn Baldwin 			inblk += todo;
86426d292d3SJohn Baldwin 		}
86526d292d3SJohn Baldwin 	}
86626d292d3SJohn Baldwin 	if (resid > 0) {
86726d292d3SJohn Baldwin 		crypto_cursor_copydata(&cc_in, resid, blk);
86826d292d3SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
869b54d1284SJohn Baldwin 			exf->update(ctx, blk, resid);
870b54d1284SJohn Baldwin 			exf->encrypt_last(ctx, blk, blk, resid);
87126d292d3SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
87226d292d3SJohn Baldwin 		} else {
873b54d1284SJohn Baldwin 			exf->decrypt_last(ctx, blk, blk, resid);
874b54d1284SJohn Baldwin 			exf->update(ctx, blk, resid);
875c0341432SJohn Baldwin 		}
87608fca7a5SJohn-Mark Gurney 	}
87708fca7a5SJohn-Mark Gurney 
87808fca7a5SJohn-Mark Gurney 	/* Finalize MAC */
8797051c579SJohn Baldwin 	exf->final(s.tag, ctx);
88008fca7a5SJohn-Mark Gurney 
88108fca7a5SJohn-Mark Gurney 	/* Validate tag */
88220c128daSJohn Baldwin 	error = 0;
883c0341432SJohn Baldwin 	if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
884c0341432SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen,
8857051c579SJohn Baldwin 		    s.tag2);
8867051c579SJohn Baldwin 		r = timingsafe_bcmp(s.tag, s.tag2, swa->sw_mlen);
88720c128daSJohn Baldwin 		if (r != 0) {
88820c128daSJohn Baldwin 			error = EBADMSG;
88920c128daSJohn Baldwin 			goto out;
89020c128daSJohn Baldwin 		}
891c0341432SJohn Baldwin 
89208fca7a5SJohn-Mark Gurney 		/* tag matches, decrypt data */
893b54d1284SJohn Baldwin 		exf->reinit(ctx, crp->crp_iv, ivlen);
8949c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_in, &crp->crp_buf);
8959c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_in, crp->crp_payload_start);
896f8580fcaSJohn Baldwin 
89750722514SMark Johnston 		inlen = 0;
898f8580fcaSJohn Baldwin 		for (resid = crp->crp_payload_length; resid >= blksz;
899f8580fcaSJohn Baldwin 		     resid -= todo) {
90050722514SMark Johnston 			if (inlen == 0)
90150722514SMark Johnston 				inblk = crypto_cursor_segment(&cc_in, &inlen);
90250722514SMark Johnston 			if (outlen == 0)
90350722514SMark Johnston 				outblk = crypto_cursor_segment(&cc_out,
90450722514SMark Johnston 				    &outlen);
90550722514SMark Johnston 
906f8580fcaSJohn Baldwin 			if (inlen < blksz) {
90726d292d3SJohn Baldwin 				crypto_cursor_copydata(&cc_in, blksz, blk);
90826d292d3SJohn Baldwin 				inblk = blk;
909f8580fcaSJohn Baldwin 				inlen = blksz;
910f8580fcaSJohn Baldwin 			}
911f8580fcaSJohn Baldwin 			if (outlen < blksz) {
91226d292d3SJohn Baldwin 				outblk = blk;
913f8580fcaSJohn Baldwin 				outlen = blksz;
914f8580fcaSJohn Baldwin 			}
915f8580fcaSJohn Baldwin 
916f8580fcaSJohn Baldwin 			todo = rounddown2(MIN(resid, MIN(inlen, outlen)),
917f8580fcaSJohn Baldwin 			    blksz);
918f8580fcaSJohn Baldwin 
919f8580fcaSJohn Baldwin 			exf->decrypt_multi(ctx, inblk, outblk, todo);
920f8580fcaSJohn Baldwin 
921f8580fcaSJohn Baldwin 			if (inblk == blk) {
922f8580fcaSJohn Baldwin 				inblk = crypto_cursor_segment(&cc_in, &inlen);
923f8580fcaSJohn Baldwin 			} else {
924f8580fcaSJohn Baldwin 				crypto_cursor_advance(&cc_in, todo);
925f8580fcaSJohn Baldwin 				inlen -= todo;
926f8580fcaSJohn Baldwin 				inblk += todo;
927f8580fcaSJohn Baldwin 			}
928f8580fcaSJohn Baldwin 
929f8580fcaSJohn Baldwin 			if (outblk == blk) {
93026d292d3SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
931f8580fcaSJohn Baldwin 				outblk = crypto_cursor_segment(&cc_out,
932f8580fcaSJohn Baldwin 				    &outlen);
933f8580fcaSJohn Baldwin 			} else {
934f8580fcaSJohn Baldwin 				crypto_cursor_advance(&cc_out, todo);
935f8580fcaSJohn Baldwin 				outlen -= todo;
936f8580fcaSJohn Baldwin 				outblk += todo;
937f8580fcaSJohn Baldwin 			}
93826d292d3SJohn Baldwin 		}
93926d292d3SJohn Baldwin 		if (resid > 0) {
94026d292d3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, resid, blk);
941b54d1284SJohn Baldwin 			exf->decrypt_last(ctx, blk, blk, resid);
94226d292d3SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
94308fca7a5SJohn-Mark Gurney 		}
94408fca7a5SJohn-Mark Gurney 	} else {
94508fca7a5SJohn-Mark Gurney 		/* Inject the authentication data */
9467051c579SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen,
9477051c579SJohn Baldwin 		    s.tag);
94808fca7a5SJohn-Mark Gurney 	}
94908fca7a5SJohn-Mark Gurney 
95020c128daSJohn Baldwin out:
951b54d1284SJohn Baldwin 	explicit_bzero(ctx, exf->ctxsize);
9527051c579SJohn Baldwin 	explicit_bzero(&s, sizeof(s));
95320c128daSJohn Baldwin 	return (error);
95408fca7a5SJohn-Mark Gurney }
95508fca7a5SJohn-Mark Gurney 
956dd2e1352SJohn Baldwin static int
swcr_chacha20_poly1305(const struct swcr_session * ses,struct cryptop * crp)957dc475c9bSJohn Baldwin swcr_chacha20_poly1305(const struct swcr_session *ses, struct cryptop *crp)
958dd2e1352SJohn Baldwin {
959dd2e1352SJohn Baldwin 	const struct crypto_session_params *csp;
9607051c579SJohn Baldwin 	struct {
961dd2e1352SJohn Baldwin 		uint64_t blkbuf[howmany(CHACHA20_NATIVE_BLOCK_LEN, sizeof(uint64_t))];
962dd2e1352SJohn Baldwin 		u_char tag[POLY1305_HASH_LEN];
9637051c579SJohn Baldwin 		u_char tag2[POLY1305_HASH_LEN];
9647051c579SJohn Baldwin 	} s;
9657051c579SJohn Baldwin 	u_char *blk = (u_char *)s.blkbuf;
966dd2e1352SJohn Baldwin 	struct crypto_buffer_cursor cc_in, cc_out;
967dd2e1352SJohn Baldwin 	const u_char *inblk;
968dd2e1352SJohn Baldwin 	u_char *outblk;
9695022c687SJohn Baldwin 	size_t inlen, outlen, todo;
970dd2e1352SJohn Baldwin 	uint64_t *blkp;
971b54d1284SJohn Baldwin 	const struct swcr_auth *swa;
972b54d1284SJohn Baldwin 	const struct swcr_encdec *swe;
973d8787d4fSMark Johnston 	const struct enc_xform *exf;
974b54d1284SJohn Baldwin 	void *ctx;
975dd2e1352SJohn Baldwin 	int blksz, error, r, resid;
976dd2e1352SJohn Baldwin 
977dd2e1352SJohn Baldwin 	swa = &ses->swcr_auth;
978dd2e1352SJohn Baldwin 	swe = &ses->swcr_encdec;
979dd2e1352SJohn Baldwin 	exf = swe->sw_exf;
980dd2e1352SJohn Baldwin 	blksz = exf->native_blocksize;
9817051c579SJohn Baldwin 	KASSERT(blksz <= sizeof(s.blkbuf), ("%s: blocksize mismatch", __func__));
982dd2e1352SJohn Baldwin 
983dd2e1352SJohn Baldwin 	if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0)
984dd2e1352SJohn Baldwin 		return (EINVAL);
985dd2e1352SJohn Baldwin 
986dd2e1352SJohn Baldwin 	csp = crypto_get_params(crp->crp_session);
987dd2e1352SJohn Baldwin 
988b54d1284SJohn Baldwin 	ctx = __builtin_alloca(exf->ctxsize);
989dd2e1352SJohn Baldwin 	if (crp->crp_cipher_key != NULL)
990b54d1284SJohn Baldwin 		exf->setkey(ctx, crp->crp_cipher_key,
991dd2e1352SJohn Baldwin 		    csp->csp_cipher_klen);
992b54d1284SJohn Baldwin 	else
993b54d1284SJohn Baldwin 		memcpy(ctx, swe->sw_ctx, exf->ctxsize);
994b54d1284SJohn Baldwin 	exf->reinit(ctx, crp->crp_iv, csp->csp_ivlen);
995dd2e1352SJohn Baldwin 
996ab91fb6cSJohn Baldwin 	/* Supply MAC with AAD */
997ab91fb6cSJohn Baldwin 	if (crp->crp_aad != NULL)
998b54d1284SJohn Baldwin 		exf->update(ctx, crp->crp_aad, crp->crp_aad_length);
999ab91fb6cSJohn Baldwin 	else
1000b54d1284SJohn Baldwin 		crypto_apply(crp, crp->crp_aad_start, crp->crp_aad_length,
1001b54d1284SJohn Baldwin 		    exf->update, ctx);
100204781697SJohn Baldwin 	if (crp->crp_aad_length % POLY1305_BLOCK_LEN != 0) {
1003ab91fb6cSJohn Baldwin 		/* padding1 */
100404781697SJohn Baldwin 		memset(blk, 0, POLY1305_BLOCK_LEN);
100504781697SJohn Baldwin 		exf->update(ctx, blk, POLY1305_BLOCK_LEN -
100604781697SJohn Baldwin 		    crp->crp_aad_length % POLY1305_BLOCK_LEN);
1007ab91fb6cSJohn Baldwin 	}
1008ab91fb6cSJohn Baldwin 
1009dd2e1352SJohn Baldwin 	/* Do encryption with MAC */
1010dd2e1352SJohn Baldwin 	crypto_cursor_init(&cc_in, &crp->crp_buf);
1011dd2e1352SJohn Baldwin 	crypto_cursor_advance(&cc_in, crp->crp_payload_start);
1012dd2e1352SJohn Baldwin 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
1013dd2e1352SJohn Baldwin 		crypto_cursor_init(&cc_out, &crp->crp_obuf);
1014dd2e1352SJohn Baldwin 		crypto_cursor_advance(&cc_out, crp->crp_payload_output_start);
1015dd2e1352SJohn Baldwin 	} else
1016dd2e1352SJohn Baldwin 		cc_out = cc_in;
10175022c687SJohn Baldwin 
101850722514SMark Johnston 	inlen = outlen = 0;
10195022c687SJohn Baldwin 	if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
10205022c687SJohn Baldwin 		for (resid = crp->crp_payload_length; resid >= blksz;
10215022c687SJohn Baldwin 		     resid -= todo) {
102250722514SMark Johnston 			if (inlen == 0)
102350722514SMark Johnston 				inblk = crypto_cursor_segment(&cc_in, &inlen);
102450722514SMark Johnston 			if (outlen == 0)
102550722514SMark Johnston 				outblk = crypto_cursor_segment(&cc_out,
102650722514SMark Johnston 				    &outlen);
102750722514SMark Johnston 
10285022c687SJohn Baldwin 			if (inlen < blksz) {
1029dd2e1352SJohn Baldwin 				crypto_cursor_copydata(&cc_in, blksz, blk);
1030dd2e1352SJohn Baldwin 				inblk = blk;
10315022c687SJohn Baldwin 				inlen = blksz;
10325022c687SJohn Baldwin 			}
10335022c687SJohn Baldwin 
10345022c687SJohn Baldwin 			if (outlen < blksz) {
1035dd2e1352SJohn Baldwin 				outblk = blk;
10365022c687SJohn Baldwin 				outlen = blksz;
10375022c687SJohn Baldwin 			}
10385022c687SJohn Baldwin 
10395022c687SJohn Baldwin 			todo = rounddown2(MIN(resid, MIN(inlen, outlen)),
10405022c687SJohn Baldwin 			    blksz);
10415022c687SJohn Baldwin 
10425022c687SJohn Baldwin 			exf->encrypt_multi(ctx, inblk, outblk, todo);
10435022c687SJohn Baldwin 			exf->update(ctx, outblk, todo);
10445022c687SJohn Baldwin 
10455022c687SJohn Baldwin 			if (inblk == blk) {
10465022c687SJohn Baldwin 				inblk = crypto_cursor_segment(&cc_in, &inlen);
1047dd2e1352SJohn Baldwin 			} else {
10485022c687SJohn Baldwin 				crypto_cursor_advance(&cc_in, todo);
10495022c687SJohn Baldwin 				inlen -= todo;
10505022c687SJohn Baldwin 				inblk += todo;
10515022c687SJohn Baldwin 			}
10525022c687SJohn Baldwin 
10535022c687SJohn Baldwin 			if (outblk == blk) {
10545022c687SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
10555022c687SJohn Baldwin 				outblk = crypto_cursor_segment(&cc_out, &outlen);
10565022c687SJohn Baldwin 			} else {
10575022c687SJohn Baldwin 				crypto_cursor_advance(&cc_out, todo);
10585022c687SJohn Baldwin 				outlen -= todo;
10595022c687SJohn Baldwin 				outblk += todo;
1060dd2e1352SJohn Baldwin 			}
1061dd2e1352SJohn Baldwin 		}
1062dd2e1352SJohn Baldwin 		if (resid > 0) {
1063dd2e1352SJohn Baldwin 			crypto_cursor_copydata(&cc_in, resid, blk);
1064b54d1284SJohn Baldwin 			exf->encrypt_last(ctx, blk, blk, resid);
1065dd2e1352SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
1066b54d1284SJohn Baldwin 			exf->update(ctx, blk, resid);
10675022c687SJohn Baldwin 		}
10685022c687SJohn Baldwin 	} else
10695022c687SJohn Baldwin 		crypto_apply(crp, crp->crp_payload_start,
10705022c687SJohn Baldwin 		    crp->crp_payload_length, exf->update, ctx);
10715022c687SJohn Baldwin 	if (crp->crp_payload_length % POLY1305_BLOCK_LEN != 0) {
1072dd2e1352SJohn Baldwin 		/* padding2 */
107304781697SJohn Baldwin 		memset(blk, 0, POLY1305_BLOCK_LEN);
107404781697SJohn Baldwin 		exf->update(ctx, blk, POLY1305_BLOCK_LEN -
10755022c687SJohn Baldwin 		    crp->crp_payload_length % POLY1305_BLOCK_LEN);
1076dd2e1352SJohn Baldwin 	}
1077dd2e1352SJohn Baldwin 
1078dd2e1352SJohn Baldwin 	/* lengths */
1079dd2e1352SJohn Baldwin 	blkp = (uint64_t *)blk;
1080dd2e1352SJohn Baldwin 	blkp[0] = htole64(crp->crp_aad_length);
1081dd2e1352SJohn Baldwin 	blkp[1] = htole64(crp->crp_payload_length);
1082b54d1284SJohn Baldwin 	exf->update(ctx, blk, sizeof(uint64_t) * 2);
1083dd2e1352SJohn Baldwin 
1084dd2e1352SJohn Baldwin 	/* Finalize MAC */
10857051c579SJohn Baldwin 	exf->final(s.tag, ctx);
1086dd2e1352SJohn Baldwin 
1087dd2e1352SJohn Baldwin 	/* Validate tag */
1088dd2e1352SJohn Baldwin 	error = 0;
1089dd2e1352SJohn Baldwin 	if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
10907051c579SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen,
10917051c579SJohn Baldwin 		    s.tag2);
10927051c579SJohn Baldwin 		r = timingsafe_bcmp(s.tag, s.tag2, swa->sw_mlen);
1093dd2e1352SJohn Baldwin 		if (r != 0) {
1094dd2e1352SJohn Baldwin 			error = EBADMSG;
1095dd2e1352SJohn Baldwin 			goto out;
1096dd2e1352SJohn Baldwin 		}
1097dd2e1352SJohn Baldwin 
1098dd2e1352SJohn Baldwin 		/* tag matches, decrypt data */
1099dd2e1352SJohn Baldwin 		crypto_cursor_init(&cc_in, &crp->crp_buf);
1100dd2e1352SJohn Baldwin 		crypto_cursor_advance(&cc_in, crp->crp_payload_start);
11015022c687SJohn Baldwin 
110250722514SMark Johnston 		inlen = 0;
1103dd2e1352SJohn Baldwin 		for (resid = crp->crp_payload_length; resid > blksz;
11045022c687SJohn Baldwin 		     resid -= todo) {
110550722514SMark Johnston 			if (inlen == 0)
110650722514SMark Johnston 				inblk = crypto_cursor_segment(&cc_in, &inlen);
110750722514SMark Johnston 			if (outlen == 0)
110850722514SMark Johnston 				outblk = crypto_cursor_segment(&cc_out,
110950722514SMark Johnston 				    &outlen);
11105022c687SJohn Baldwin 			if (inlen < blksz) {
1111dd2e1352SJohn Baldwin 				crypto_cursor_copydata(&cc_in, blksz, blk);
1112dd2e1352SJohn Baldwin 				inblk = blk;
11135022c687SJohn Baldwin 				inlen = blksz;
11145022c687SJohn Baldwin 			}
11155022c687SJohn Baldwin 			if (outlen < blksz) {
1116dd2e1352SJohn Baldwin 				outblk = blk;
11175022c687SJohn Baldwin 				outlen = blksz;
11185022c687SJohn Baldwin 			}
11195022c687SJohn Baldwin 
11205022c687SJohn Baldwin 			todo = rounddown2(MIN(resid, MIN(inlen, outlen)),
11215022c687SJohn Baldwin 			    blksz);
11225022c687SJohn Baldwin 
11235022c687SJohn Baldwin 			exf->decrypt_multi(ctx, inblk, outblk, todo);
11245022c687SJohn Baldwin 
11255022c687SJohn Baldwin 			if (inblk == blk) {
11265022c687SJohn Baldwin 				inblk = crypto_cursor_segment(&cc_in, &inlen);
11275022c687SJohn Baldwin 			} else {
11285022c687SJohn Baldwin 				crypto_cursor_advance(&cc_in, todo);
11295022c687SJohn Baldwin 				inlen -= todo;
11305022c687SJohn Baldwin 				inblk += todo;
11315022c687SJohn Baldwin 			}
11325022c687SJohn Baldwin 
11335022c687SJohn Baldwin 			if (outblk == blk) {
1134dd2e1352SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
11355022c687SJohn Baldwin 				outblk = crypto_cursor_segment(&cc_out,
11365022c687SJohn Baldwin 				    &outlen);
11375022c687SJohn Baldwin 			} else {
11385022c687SJohn Baldwin 				crypto_cursor_advance(&cc_out, todo);
11395022c687SJohn Baldwin 				outlen -= todo;
11405022c687SJohn Baldwin 				outblk += todo;
11415022c687SJohn Baldwin 			}
1142dd2e1352SJohn Baldwin 		}
1143dd2e1352SJohn Baldwin 		if (resid > 0) {
1144dd2e1352SJohn Baldwin 			crypto_cursor_copydata(&cc_in, resid, blk);
1145b54d1284SJohn Baldwin 			exf->decrypt_last(ctx, blk, blk, resid);
1146dd2e1352SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
1147dd2e1352SJohn Baldwin 		}
1148dd2e1352SJohn Baldwin 	} else {
1149dd2e1352SJohn Baldwin 		/* Inject the authentication data */
11507051c579SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen,
11517051c579SJohn Baldwin 		    s.tag);
1152dd2e1352SJohn Baldwin 	}
1153dd2e1352SJohn Baldwin 
1154dd2e1352SJohn Baldwin out:
1155b54d1284SJohn Baldwin 	explicit_bzero(ctx, exf->ctxsize);
11567051c579SJohn Baldwin 	explicit_bzero(&s, sizeof(s));
1157dd2e1352SJohn Baldwin 	return (error);
1158dd2e1352SJohn Baldwin }
1159dd2e1352SJohn Baldwin 
1160091d81d1SSam Leffler /*
1161c0341432SJohn Baldwin  * Apply a cipher and a digest to perform EtA.
1162c0341432SJohn Baldwin  */
1163c0341432SJohn Baldwin static int
swcr_eta(const struct swcr_session * ses,struct cryptop * crp)1164dc475c9bSJohn Baldwin swcr_eta(const struct swcr_session *ses, struct cryptop *crp)
1165c0341432SJohn Baldwin {
1166c0341432SJohn Baldwin 	int error;
1167c0341432SJohn Baldwin 
1168c0341432SJohn Baldwin 	if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
1169c0341432SJohn Baldwin 		error = swcr_encdec(ses, crp);
1170c0341432SJohn Baldwin 		if (error == 0)
1171c0341432SJohn Baldwin 			error = swcr_authcompute(ses, crp);
1172c0341432SJohn Baldwin 	} else {
1173c0341432SJohn Baldwin 		error = swcr_authcompute(ses, crp);
1174c0341432SJohn Baldwin 		if (error == 0)
1175c0341432SJohn Baldwin 			error = swcr_encdec(ses, crp);
1176c0341432SJohn Baldwin 	}
1177c0341432SJohn Baldwin 	return (error);
1178c0341432SJohn Baldwin }
1179c0341432SJohn Baldwin 
1180c0341432SJohn Baldwin /*
1181091d81d1SSam Leffler  * Apply a compression/decompression algorithm
1182091d81d1SSam Leffler  */
1183091d81d1SSam Leffler static int
swcr_compdec(const struct swcr_session * ses,struct cryptop * crp)1184dc475c9bSJohn Baldwin swcr_compdec(const struct swcr_session *ses, struct cryptop *crp)
1185091d81d1SSam Leffler {
1186d8787d4fSMark Johnston 	const struct comp_algo *cxf;
1187d3d79e96SJohn Baldwin 	uint8_t *data, *out;
1188091d81d1SSam Leffler 	int adj;
1189d3d79e96SJohn Baldwin 	uint32_t result;
1190091d81d1SSam Leffler 
1191c0341432SJohn Baldwin 	cxf = ses->swcr_compdec.sw_cxf;
1192091d81d1SSam Leffler 
1193091d81d1SSam Leffler 	/* We must handle the whole buffer of data in one time
1194091d81d1SSam Leffler 	 * then if there is not all the data in the mbuf, we must
1195091d81d1SSam Leffler 	 * copy in a buffer.
1196091d81d1SSam Leffler 	 */
1197091d81d1SSam Leffler 
1198c0341432SJohn Baldwin 	data = malloc(crp->crp_payload_length, M_CRYPTO_DATA,  M_NOWAIT);
1199091d81d1SSam Leffler 	if (data == NULL)
1200091d81d1SSam Leffler 		return (EINVAL);
1201c0341432SJohn Baldwin 	crypto_copydata(crp, crp->crp_payload_start, crp->crp_payload_length,
1202c0341432SJohn Baldwin 	    data);
1203091d81d1SSam Leffler 
1204c0341432SJohn Baldwin 	if (CRYPTO_OP_IS_COMPRESS(crp->crp_op))
1205c0341432SJohn Baldwin 		result = cxf->compress(data, crp->crp_payload_length, &out);
1206091d81d1SSam Leffler 	else
1207c0341432SJohn Baldwin 		result = cxf->decompress(data, crp->crp_payload_length, &out);
1208091d81d1SSam Leffler 
12091ede983cSDag-Erling Smørgrav 	free(data, M_CRYPTO_DATA);
1210091d81d1SSam Leffler 	if (result == 0)
1211c0341432SJohn Baldwin 		return (EINVAL);
1212c0341432SJohn Baldwin 	crp->crp_olen = result;
1213c0341432SJohn Baldwin 
1214c0341432SJohn Baldwin 	/* Check the compressed size when doing compression */
1215c0341432SJohn Baldwin 	if (CRYPTO_OP_IS_COMPRESS(crp->crp_op)) {
1216c0341432SJohn Baldwin 		if (result >= crp->crp_payload_length) {
1217c0341432SJohn Baldwin 			/* Compression was useless, we lost time */
1218c0341432SJohn Baldwin 			free(out, M_CRYPTO_DATA);
1219c0341432SJohn Baldwin 			return (0);
1220c0341432SJohn Baldwin 		}
1221c0341432SJohn Baldwin 	}
1222091d81d1SSam Leffler 
1223091d81d1SSam Leffler 	/* Copy back the (de)compressed data. m_copyback is
1224091d81d1SSam Leffler 	 * extending the mbuf as necessary.
1225091d81d1SSam Leffler 	 */
1226c0341432SJohn Baldwin 	crypto_copyback(crp, crp->crp_payload_start, result, out);
1227c0341432SJohn Baldwin 	if (result < crp->crp_payload_length) {
12289c0e3d3aSJohn Baldwin 		switch (crp->crp_buf.cb_type) {
1229c0341432SJohn Baldwin 		case CRYPTO_BUF_MBUF:
1230883a0196SJohn Baldwin 		case CRYPTO_BUF_SINGLE_MBUF:
1231c0341432SJohn Baldwin 			adj = result - crp->crp_payload_length;
12329c0e3d3aSJohn Baldwin 			m_adj(crp->crp_buf.cb_mbuf, adj);
1233c0341432SJohn Baldwin 			break;
1234c0341432SJohn Baldwin 		case CRYPTO_BUF_UIO: {
12359c0e3d3aSJohn Baldwin 			struct uio *uio = crp->crp_buf.cb_uio;
1236091d81d1SSam Leffler 			int ind;
1237091d81d1SSam Leffler 
1238c0341432SJohn Baldwin 			adj = crp->crp_payload_length - result;
1239091d81d1SSam Leffler 			ind = uio->uio_iovcnt - 1;
1240091d81d1SSam Leffler 
1241091d81d1SSam Leffler 			while (adj > 0 && ind >= 0) {
1242091d81d1SSam Leffler 				if (adj < uio->uio_iov[ind].iov_len) {
1243091d81d1SSam Leffler 					uio->uio_iov[ind].iov_len -= adj;
1244091d81d1SSam Leffler 					break;
1245091d81d1SSam Leffler 				}
1246091d81d1SSam Leffler 
1247091d81d1SSam Leffler 				adj -= uio->uio_iov[ind].iov_len;
1248091d81d1SSam Leffler 				uio->uio_iov[ind].iov_len = 0;
1249091d81d1SSam Leffler 				ind--;
1250091d81d1SSam Leffler 				uio->uio_iovcnt--;
1251091d81d1SSam Leffler 			}
1252091d81d1SSam Leffler 			}
1253c0341432SJohn Baldwin 			break;
1254e6f6d0c9SAlan Somers 		case CRYPTO_BUF_VMPAGE:
1255e6f6d0c9SAlan Somers 			adj = crp->crp_payload_length - result;
1256e6f6d0c9SAlan Somers 			crp->crp_buf.cb_vm_page_len -= adj;
1257e6f6d0c9SAlan Somers 			break;
12589c0e3d3aSJohn Baldwin 		default:
12599c0e3d3aSJohn Baldwin 			break;
1260c0341432SJohn Baldwin 		}
1261091d81d1SSam Leffler 	}
12621ede983cSDag-Erling Smørgrav 	free(out, M_CRYPTO_DATA);
1263091d81d1SSam Leffler 	return 0;
1264091d81d1SSam Leffler }
1265091d81d1SSam Leffler 
1266091d81d1SSam Leffler static int
swcr_setup_cipher(struct swcr_session * ses,const struct crypto_session_params * csp)12673e947048SJohn Baldwin swcr_setup_cipher(struct swcr_session *ses,
1268c0341432SJohn Baldwin     const struct crypto_session_params *csp)
1269091d81d1SSam Leffler {
1270c0341432SJohn Baldwin 	struct swcr_encdec *swe;
1271d8787d4fSMark Johnston 	const struct enc_xform *txf;
1272f6c4bc3bSPawel Jakub Dawidek 	int error;
1273091d81d1SSam Leffler 
1274c0341432SJohn Baldwin 	swe = &ses->swcr_encdec;
1275c0341432SJohn Baldwin 	txf = crypto_cipher(csp);
1276b54d1284SJohn Baldwin 	if (csp->csp_cipher_key != NULL) {
12773e947048SJohn Baldwin 		if (txf->ctxsize != 0) {
1278f313909aSJohn Baldwin 			swe->sw_ctx = malloc(txf->ctxsize, M_CRYPTO_DATA,
12793e947048SJohn Baldwin 			    M_NOWAIT);
1280f313909aSJohn Baldwin 			if (swe->sw_ctx == NULL)
12813e947048SJohn Baldwin 				return (ENOMEM);
12823e947048SJohn Baldwin 		}
1283f313909aSJohn Baldwin 		error = txf->setkey(swe->sw_ctx,
1284c0341432SJohn Baldwin 		    csp->csp_cipher_key, csp->csp_cipher_klen);
1285c0341432SJohn Baldwin 		if (error)
1286c0341432SJohn Baldwin 			return (error);
1287091d81d1SSam Leffler 	}
1288c0341432SJohn Baldwin 	swe->sw_exf = txf;
1289c0341432SJohn Baldwin 	return (0);
1290f6c4bc3bSPawel Jakub Dawidek }
1291091d81d1SSam Leffler 
1292c0341432SJohn Baldwin static int
swcr_setup_auth(struct swcr_session * ses,const struct crypto_session_params * csp)1293c0341432SJohn Baldwin swcr_setup_auth(struct swcr_session *ses,
1294c0341432SJohn Baldwin     const struct crypto_session_params *csp)
1295c0341432SJohn Baldwin {
1296c0341432SJohn Baldwin 	struct swcr_auth *swa;
1297d8787d4fSMark Johnston 	const struct auth_hash *axf;
1298c0341432SJohn Baldwin 
1299c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
1300c0341432SJohn Baldwin 
1301c0341432SJohn Baldwin 	axf = crypto_auth_hash(csp);
1302c0341432SJohn Baldwin 	swa->sw_axf = axf;
1303c0341432SJohn Baldwin 	if (csp->csp_auth_mlen < 0 || csp->csp_auth_mlen > axf->hashsize)
1304c0341432SJohn Baldwin 		return (EINVAL);
1305c0341432SJohn Baldwin 	if (csp->csp_auth_mlen == 0)
1306c0341432SJohn Baldwin 		swa->sw_mlen = axf->hashsize;
1307c0341432SJohn Baldwin 	else
1308c0341432SJohn Baldwin 		swa->sw_mlen = csp->csp_auth_mlen;
13096113a08bSJohn Baldwin 	if (csp->csp_auth_klen == 0 || csp->csp_auth_key != NULL) {
13106113a08bSJohn Baldwin 		swa->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
13116113a08bSJohn Baldwin 		    M_NOWAIT);
1312c0341432SJohn Baldwin 		if (swa->sw_ictx == NULL)
1313c0341432SJohn Baldwin 			return (ENOBUFS);
13146113a08bSJohn Baldwin 	}
1315c0341432SJohn Baldwin 
1316c0341432SJohn Baldwin 	switch (csp->csp_auth_alg) {
1317091d81d1SSam Leffler 	case CRYPTO_SHA1_HMAC:
1318c97f39ceSConrad Meyer 	case CRYPTO_SHA2_224_HMAC:
1319f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_256_HMAC:
1320f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_384_HMAC:
1321f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_512_HMAC:
1322091d81d1SSam Leffler 	case CRYPTO_RIPEMD160_HMAC:
13236113a08bSJohn Baldwin 		swa->sw_hmac = true;
13246113a08bSJohn Baldwin 		if (csp->csp_auth_key != NULL) {
13253a0b6a93SJohn Baldwin 			swa->sw_octx = malloc(axf->ctxsize, M_CRYPTO_DATA,
1326091d81d1SSam Leffler 			    M_NOWAIT);
1327c0341432SJohn Baldwin 			if (swa->sw_octx == NULL)
1328c0341432SJohn Baldwin 				return (ENOBUFS);
13296113a08bSJohn Baldwin 			hmac_init_ipad(axf, csp->csp_auth_key,
13306113a08bSJohn Baldwin 			    csp->csp_auth_klen, swa->sw_ictx);
13316113a08bSJohn Baldwin 			hmac_init_opad(axf, csp->csp_auth_key,
13326113a08bSJohn Baldwin 			    csp->csp_auth_klen, swa->sw_octx);
1333091d81d1SSam Leffler 		}
1334091d81d1SSam Leffler 		break;
1335c3a688efSJohn Baldwin 	case CRYPTO_RIPEMD160:
1336091d81d1SSam Leffler 	case CRYPTO_SHA1:
1337c4729f6eSConrad Meyer 	case CRYPTO_SHA2_224:
1338c4729f6eSConrad Meyer 	case CRYPTO_SHA2_256:
1339c4729f6eSConrad Meyer 	case CRYPTO_SHA2_384:
1340c4729f6eSConrad Meyer 	case CRYPTO_SHA2_512:
1341aa268175SJohn Baldwin 	case CRYPTO_NULL_HMAC:
1342c0341432SJohn Baldwin 		axf->Init(swa->sw_ictx);
1343c0341432SJohn Baldwin 		break;
1344c0341432SJohn Baldwin 	case CRYPTO_AES_NIST_GMAC:
13456113a08bSJohn Baldwin 	case CRYPTO_AES_CCM_CBC_MAC:
13466113a08bSJohn Baldwin 	case CRYPTO_POLY1305:
13476113a08bSJohn Baldwin 		if (csp->csp_auth_key != NULL) {
1348c0341432SJohn Baldwin 			axf->Init(swa->sw_ictx);
1349c0341432SJohn Baldwin 			axf->Setkey(swa->sw_ictx, csp->csp_auth_key,
1350c0341432SJohn Baldwin 			    csp->csp_auth_klen);
13516113a08bSJohn Baldwin 		}
1352c0341432SJohn Baldwin 		break;
1353c0341432SJohn Baldwin 	case CRYPTO_BLAKE2B:
1354c0341432SJohn Baldwin 	case CRYPTO_BLAKE2S:
1355c0341432SJohn Baldwin 		/*
1356c0341432SJohn Baldwin 		 * Blake2b and Blake2s support an optional key but do
1357c0341432SJohn Baldwin 		 * not require one.
1358c0341432SJohn Baldwin 		 */
13596113a08bSJohn Baldwin 		if (csp->csp_auth_klen == 0)
13606113a08bSJohn Baldwin 			axf->Init(swa->sw_ictx);
13616113a08bSJohn Baldwin 		else if (csp->csp_auth_key != NULL)
1362c0341432SJohn Baldwin 			axf->Setkey(swa->sw_ictx, csp->csp_auth_key,
1363c0341432SJohn Baldwin 			    csp->csp_auth_klen);
13646113a08bSJohn Baldwin 		break;
13656113a08bSJohn Baldwin 	}
13666113a08bSJohn Baldwin 
13676113a08bSJohn Baldwin 	if (csp->csp_mode == CSP_MODE_DIGEST) {
13686113a08bSJohn Baldwin 		switch (csp->csp_auth_alg) {
13696113a08bSJohn Baldwin 		case CRYPTO_AES_NIST_GMAC:
13706113a08bSJohn Baldwin 			ses->swcr_process = swcr_gmac;
1371c0341432SJohn Baldwin 			break;
1372c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_CBC_MAC:
1373c0341432SJohn Baldwin 			ses->swcr_process = swcr_ccm_cbc_mac;
1374c0341432SJohn Baldwin 			break;
13756113a08bSJohn Baldwin 		default:
13766113a08bSJohn Baldwin 			ses->swcr_process = swcr_authcompute;
13776113a08bSJohn Baldwin 		}
1378091d81d1SSam Leffler 	}
1379091d81d1SSam Leffler 
1380c0341432SJohn Baldwin 	return (0);
1381c0341432SJohn Baldwin }
138208fca7a5SJohn-Mark Gurney 
1383c0341432SJohn Baldwin static int
swcr_setup_aead(struct swcr_session * ses,const struct crypto_session_params * csp)1384ab91fb6cSJohn Baldwin swcr_setup_aead(struct swcr_session *ses,
1385c0341432SJohn Baldwin     const struct crypto_session_params *csp)
1386c0341432SJohn Baldwin {
1387c0341432SJohn Baldwin 	struct swcr_auth *swa;
1388ab91fb6cSJohn Baldwin 	int error;
1389c0341432SJohn Baldwin 
1390ab91fb6cSJohn Baldwin 	error = swcr_setup_cipher(ses, csp);
1391ab91fb6cSJohn Baldwin 	if (error)
1392ab91fb6cSJohn Baldwin 		return (error);
1393ab91fb6cSJohn Baldwin 
1394c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
1395c0341432SJohn Baldwin 	if (csp->csp_auth_mlen == 0)
1396ab91fb6cSJohn Baldwin 		swa->sw_mlen = ses->swcr_encdec.sw_exf->macsize;
1397c0341432SJohn Baldwin 	else
1398c0341432SJohn Baldwin 		swa->sw_mlen = csp->csp_auth_mlen;
1399ab91fb6cSJohn Baldwin 	return (0);
1400dd2e1352SJohn Baldwin }
1401dd2e1352SJohn Baldwin 
1402c0341432SJohn Baldwin static bool
swcr_auth_supported(const struct crypto_session_params * csp)1403c0341432SJohn Baldwin swcr_auth_supported(const struct crypto_session_params *csp)
1404109919c6SBenno Rice {
1405d8787d4fSMark Johnston 	const struct auth_hash *axf;
1406091d81d1SSam Leffler 
1407c0341432SJohn Baldwin 	axf = crypto_auth_hash(csp);
1408c0341432SJohn Baldwin 	if (axf == NULL)
1409c0341432SJohn Baldwin 		return (false);
1410c0341432SJohn Baldwin 	switch (csp->csp_auth_alg) {
1411091d81d1SSam Leffler 	case CRYPTO_SHA1_HMAC:
1412c97f39ceSConrad Meyer 	case CRYPTO_SHA2_224_HMAC:
1413f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_256_HMAC:
1414f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_384_HMAC:
1415f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_512_HMAC:
1416091d81d1SSam Leffler 	case CRYPTO_NULL_HMAC:
1417c0341432SJohn Baldwin 	case CRYPTO_RIPEMD160_HMAC:
1418091d81d1SSam Leffler 		break;
1419c0341432SJohn Baldwin 	case CRYPTO_AES_NIST_GMAC:
1420c0341432SJohn Baldwin 		switch (csp->csp_auth_klen * 8) {
1421c0341432SJohn Baldwin 		case 128:
1422c0341432SJohn Baldwin 		case 192:
1423c0341432SJohn Baldwin 		case 256:
1424c0341432SJohn Baldwin 			break;
1425c0341432SJohn Baldwin 		default:
1426c0341432SJohn Baldwin 			return (false);
1427c0341432SJohn Baldwin 		}
1428c0341432SJohn Baldwin 		if (csp->csp_auth_key == NULL)
1429c0341432SJohn Baldwin 			return (false);
1430c0341432SJohn Baldwin 		if (csp->csp_ivlen != AES_GCM_IV_LEN)
1431c0341432SJohn Baldwin 			return (false);
1432c0341432SJohn Baldwin 		break;
143325b7033bSConrad Meyer 	case CRYPTO_POLY1305:
1434c0341432SJohn Baldwin 		if (csp->csp_auth_klen != POLY1305_KEY_LEN)
1435c0341432SJohn Baldwin 			return (false);
1436c0341432SJohn Baldwin 		break;
1437c0341432SJohn Baldwin 	case CRYPTO_AES_CCM_CBC_MAC:
1438c0341432SJohn Baldwin 		switch (csp->csp_auth_klen * 8) {
1439c0341432SJohn Baldwin 		case 128:
1440c0341432SJohn Baldwin 		case 192:
1441c0341432SJohn Baldwin 		case 256:
1442c0341432SJohn Baldwin 			break;
1443c0341432SJohn Baldwin 		default:
1444c0341432SJohn Baldwin 			return (false);
1445c0341432SJohn Baldwin 		}
1446c0341432SJohn Baldwin 		if (csp->csp_auth_key == NULL)
1447c0341432SJohn Baldwin 			return (false);
1448c0341432SJohn Baldwin 		break;
1449c0341432SJohn Baldwin 	}
1450c0341432SJohn Baldwin 	return (true);
1451c0341432SJohn Baldwin }
1452091d81d1SSam Leffler 
1453c0341432SJohn Baldwin static bool
swcr_cipher_supported(const struct crypto_session_params * csp)1454c0341432SJohn Baldwin swcr_cipher_supported(const struct crypto_session_params *csp)
1455c0341432SJohn Baldwin {
1456d8787d4fSMark Johnston 	const struct enc_xform *txf;
1457c0341432SJohn Baldwin 
1458c0341432SJohn Baldwin 	txf = crypto_cipher(csp);
1459c0341432SJohn Baldwin 	if (txf == NULL)
1460c0341432SJohn Baldwin 		return (false);
1461c0341432SJohn Baldwin 	if (csp->csp_cipher_alg != CRYPTO_NULL_CBC &&
1462c0341432SJohn Baldwin 	    txf->ivsize != csp->csp_ivlen)
1463c0341432SJohn Baldwin 		return (false);
1464c0341432SJohn Baldwin 	return (true);
1465c0341432SJohn Baldwin }
1466c0341432SJohn Baldwin 
14676038018aSMarcin Wojtas #define SUPPORTED_SES (CSP_F_SEPARATE_OUTPUT | CSP_F_SEPARATE_AAD | CSP_F_ESN)
14686038018aSMarcin Wojtas 
1469c0341432SJohn Baldwin static int
swcr_probesession(device_t dev,const struct crypto_session_params * csp)1470c0341432SJohn Baldwin swcr_probesession(device_t dev, const struct crypto_session_params *csp)
1471c0341432SJohn Baldwin {
14726038018aSMarcin Wojtas 	if ((csp->csp_flags & ~(SUPPORTED_SES)) != 0)
1473c0341432SJohn Baldwin 		return (EINVAL);
1474c0341432SJohn Baldwin 	switch (csp->csp_mode) {
1475c0341432SJohn Baldwin 	case CSP_MODE_COMPRESS:
1476c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1477c0341432SJohn Baldwin 		case CRYPTO_DEFLATE_COMP:
1478c0341432SJohn Baldwin 			break;
1479c0341432SJohn Baldwin 		default:
1480c0341432SJohn Baldwin 			return (EINVAL);
14815fbc5b5aSConrad Meyer 		}
1482091d81d1SSam Leffler 		break;
1483c0341432SJohn Baldwin 	case CSP_MODE_CIPHER:
1484c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1485c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1486c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1487dd2e1352SJohn Baldwin 		case CRYPTO_CHACHA20_POLY1305:
14888f35841fSJohn Baldwin 		case CRYPTO_XCHACHA20_POLY1305:
1489c0341432SJohn Baldwin 			return (EINVAL);
1490c0341432SJohn Baldwin 		default:
1491c0341432SJohn Baldwin 			if (!swcr_cipher_supported(csp))
1492c0341432SJohn Baldwin 				return (EINVAL);
1493091d81d1SSam Leffler 			break;
1494091d81d1SSam Leffler 		}
1495c0341432SJohn Baldwin 		break;
1496c0341432SJohn Baldwin 	case CSP_MODE_DIGEST:
1497c0341432SJohn Baldwin 		if (!swcr_auth_supported(csp))
1498c0341432SJohn Baldwin 			return (EINVAL);
1499c0341432SJohn Baldwin 		break;
1500c0341432SJohn Baldwin 	case CSP_MODE_AEAD:
1501c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1502c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1503c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1504c172a407SJohn Baldwin 			switch (csp->csp_cipher_klen * 8) {
1505c172a407SJohn Baldwin 			case 128:
1506c172a407SJohn Baldwin 			case 192:
1507c172a407SJohn Baldwin 			case 256:
1508c172a407SJohn Baldwin 				break;
1509c172a407SJohn Baldwin 			default:
1510c172a407SJohn Baldwin 				return (EINVAL);
1511c172a407SJohn Baldwin 			}
1512c172a407SJohn Baldwin 			break;
1513dd2e1352SJohn Baldwin 		case CRYPTO_CHACHA20_POLY1305:
15148f35841fSJohn Baldwin 		case CRYPTO_XCHACHA20_POLY1305:
1515c0341432SJohn Baldwin 			break;
1516c0341432SJohn Baldwin 		default:
1517c0341432SJohn Baldwin 			return (EINVAL);
1518c0341432SJohn Baldwin 		}
1519c0341432SJohn Baldwin 		break;
1520c0341432SJohn Baldwin 	case CSP_MODE_ETA:
1521c0341432SJohn Baldwin 		/* AEAD algorithms cannot be used for EtA. */
1522c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1523c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1524c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1525dd2e1352SJohn Baldwin 		case CRYPTO_CHACHA20_POLY1305:
15268f35841fSJohn Baldwin 		case CRYPTO_XCHACHA20_POLY1305:
1527c0341432SJohn Baldwin 			return (EINVAL);
1528c0341432SJohn Baldwin 		}
1529c0341432SJohn Baldwin 		switch (csp->csp_auth_alg) {
1530c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GMAC:
1531c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_CBC_MAC:
1532c0341432SJohn Baldwin 			return (EINVAL);
1533c0341432SJohn Baldwin 		}
1534c0341432SJohn Baldwin 
1535c0341432SJohn Baldwin 		if (!swcr_cipher_supported(csp) ||
1536c0341432SJohn Baldwin 		    !swcr_auth_supported(csp))
1537c0341432SJohn Baldwin 			return (EINVAL);
1538c0341432SJohn Baldwin 		break;
1539c0341432SJohn Baldwin 	default:
1540c0341432SJohn Baldwin 		return (EINVAL);
1541c0341432SJohn Baldwin 	}
1542c0341432SJohn Baldwin 
1543c0341432SJohn Baldwin 	return (CRYPTODEV_PROBE_SOFTWARE);
1544c0341432SJohn Baldwin }
1545c0341432SJohn Baldwin 
1546c0341432SJohn Baldwin /*
1547c0341432SJohn Baldwin  * Generate a new software session.
1548c0341432SJohn Baldwin  */
1549c0341432SJohn Baldwin static int
swcr_newsession(device_t dev,crypto_session_t cses,const struct crypto_session_params * csp)1550c0341432SJohn Baldwin swcr_newsession(device_t dev, crypto_session_t cses,
1551c0341432SJohn Baldwin     const struct crypto_session_params *csp)
1552c0341432SJohn Baldwin {
1553c0341432SJohn Baldwin 	struct swcr_session *ses;
1554d8787d4fSMark Johnston 	const struct comp_algo *cxf;
1555c0341432SJohn Baldwin 	int error;
1556c0341432SJohn Baldwin 
1557c0341432SJohn Baldwin 	ses = crypto_get_driver_session(cses);
1558c0341432SJohn Baldwin 
1559c0341432SJohn Baldwin 	error = 0;
1560c0341432SJohn Baldwin 	switch (csp->csp_mode) {
1561c0341432SJohn Baldwin 	case CSP_MODE_COMPRESS:
1562c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1563c0341432SJohn Baldwin 		case CRYPTO_DEFLATE_COMP:
1564c0341432SJohn Baldwin 			cxf = &comp_algo_deflate;
1565c0341432SJohn Baldwin 			break;
1566c0341432SJohn Baldwin #ifdef INVARIANTS
1567c0341432SJohn Baldwin 		default:
1568c0341432SJohn Baldwin 			panic("bad compression algo");
1569c0341432SJohn Baldwin #endif
1570c0341432SJohn Baldwin 		}
1571c0341432SJohn Baldwin 		ses->swcr_compdec.sw_cxf = cxf;
1572c0341432SJohn Baldwin 		ses->swcr_process = swcr_compdec;
1573c0341432SJohn Baldwin 		break;
1574c0341432SJohn Baldwin 	case CSP_MODE_CIPHER:
1575c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1576c0341432SJohn Baldwin 		case CRYPTO_NULL_CBC:
1577c0341432SJohn Baldwin 			ses->swcr_process = swcr_null;
1578c0341432SJohn Baldwin 			break;
1579c0341432SJohn Baldwin #ifdef INVARIANTS
1580c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1581c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1582dd2e1352SJohn Baldwin 		case CRYPTO_CHACHA20_POLY1305:
15838f35841fSJohn Baldwin 		case CRYPTO_XCHACHA20_POLY1305:
1584c0341432SJohn Baldwin 			panic("bad cipher algo");
1585c0341432SJohn Baldwin #endif
1586c0341432SJohn Baldwin 		default:
15873e947048SJohn Baldwin 			error = swcr_setup_cipher(ses, csp);
1588c0341432SJohn Baldwin 			if (error == 0)
1589c0341432SJohn Baldwin 				ses->swcr_process = swcr_encdec;
1590c0341432SJohn Baldwin 		}
1591c0341432SJohn Baldwin 		break;
1592c0341432SJohn Baldwin 	case CSP_MODE_DIGEST:
1593c0341432SJohn Baldwin 		error = swcr_setup_auth(ses, csp);
1594c0341432SJohn Baldwin 		break;
1595c0341432SJohn Baldwin 	case CSP_MODE_AEAD:
1596c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1597c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1598ab91fb6cSJohn Baldwin 			error = swcr_setup_aead(ses, csp);
1599c0341432SJohn Baldwin 			if (error == 0)
1600c0341432SJohn Baldwin 				ses->swcr_process = swcr_gcm;
1601c0341432SJohn Baldwin 			break;
1602c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1603ab91fb6cSJohn Baldwin 			error = swcr_setup_aead(ses, csp);
1604c0341432SJohn Baldwin 			if (error == 0)
1605c0341432SJohn Baldwin 				ses->swcr_process = swcr_ccm;
1606c0341432SJohn Baldwin 			break;
1607dd2e1352SJohn Baldwin 		case CRYPTO_CHACHA20_POLY1305:
16088f35841fSJohn Baldwin 		case CRYPTO_XCHACHA20_POLY1305:
1609ab91fb6cSJohn Baldwin 			error = swcr_setup_aead(ses, csp);
1610dd2e1352SJohn Baldwin 			if (error == 0)
1611dd2e1352SJohn Baldwin 				ses->swcr_process = swcr_chacha20_poly1305;
1612dd2e1352SJohn Baldwin 			break;
1613c0341432SJohn Baldwin #ifdef INVARIANTS
1614c0341432SJohn Baldwin 		default:
1615c0341432SJohn Baldwin 			panic("bad aead algo");
1616c0341432SJohn Baldwin #endif
1617c0341432SJohn Baldwin 		}
1618c0341432SJohn Baldwin 		break;
1619c0341432SJohn Baldwin 	case CSP_MODE_ETA:
1620c0341432SJohn Baldwin #ifdef INVARIANTS
1621c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1622c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1623c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1624dd2e1352SJohn Baldwin 		case CRYPTO_CHACHA20_POLY1305:
16258f35841fSJohn Baldwin 		case CRYPTO_XCHACHA20_POLY1305:
1626c0341432SJohn Baldwin 			panic("bad eta cipher algo");
1627c0341432SJohn Baldwin 		}
1628c0341432SJohn Baldwin 		switch (csp->csp_auth_alg) {
1629c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GMAC:
1630c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_CBC_MAC:
1631c0341432SJohn Baldwin 			panic("bad eta auth algo");
1632c0341432SJohn Baldwin 		}
1633c0341432SJohn Baldwin #endif
1634c0341432SJohn Baldwin 
1635c0341432SJohn Baldwin 		error = swcr_setup_auth(ses, csp);
1636c0341432SJohn Baldwin 		if (error)
1637c0341432SJohn Baldwin 			break;
1638c0341432SJohn Baldwin 		if (csp->csp_cipher_alg == CRYPTO_NULL_CBC) {
1639c0341432SJohn Baldwin 			/* Effectively degrade to digest mode. */
1640c0341432SJohn Baldwin 			ses->swcr_process = swcr_authcompute;
1641c0341432SJohn Baldwin 			break;
1642c0341432SJohn Baldwin 		}
1643c0341432SJohn Baldwin 
16443e947048SJohn Baldwin 		error = swcr_setup_cipher(ses, csp);
1645c0341432SJohn Baldwin 		if (error == 0)
1646c0341432SJohn Baldwin 			ses->swcr_process = swcr_eta;
1647c0341432SJohn Baldwin 		break;
1648c0341432SJohn Baldwin 	default:
1649c0341432SJohn Baldwin 		error = EINVAL;
1650c0341432SJohn Baldwin 	}
1651c0341432SJohn Baldwin 
1652c0341432SJohn Baldwin 	if (error)
1653c0341432SJohn Baldwin 		swcr_freesession(dev, cses);
1654c0341432SJohn Baldwin 	return (error);
1655c0341432SJohn Baldwin }
1656c0341432SJohn Baldwin 
1657c0341432SJohn Baldwin static void
swcr_freesession(device_t dev,crypto_session_t cses)1658c0341432SJohn Baldwin swcr_freesession(device_t dev, crypto_session_t cses)
1659c0341432SJohn Baldwin {
1660c0341432SJohn Baldwin 	struct swcr_session *ses;
1661c0341432SJohn Baldwin 
1662c0341432SJohn Baldwin 	ses = crypto_get_driver_session(cses);
1663c0341432SJohn Baldwin 
1664f313909aSJohn Baldwin 	zfree(ses->swcr_encdec.sw_ctx, M_CRYPTO_DATA);
16654a711b8dSJohn Baldwin 	zfree(ses->swcr_auth.sw_ictx, M_CRYPTO_DATA);
16664a711b8dSJohn Baldwin 	zfree(ses->swcr_auth.sw_octx, M_CRYPTO_DATA);
1667091d81d1SSam Leffler }
1668091d81d1SSam Leffler 
1669091d81d1SSam Leffler /*
1670091d81d1SSam Leffler  * Process a software request.
1671091d81d1SSam Leffler  */
1672091d81d1SSam Leffler static int
swcr_process(device_t dev,struct cryptop * crp,int hint)16736810ad6fSSam Leffler swcr_process(device_t dev, struct cryptop *crp, int hint)
1674091d81d1SSam Leffler {
1675c0341432SJohn Baldwin 	struct swcr_session *ses;
1676091d81d1SSam Leffler 
16771b0909d5SConrad Meyer 	ses = crypto_get_driver_session(crp->crp_session);
1678091d81d1SSam Leffler 
1679c0341432SJohn Baldwin 	crp->crp_etype = ses->swcr_process(ses, crp);
1680091d81d1SSam Leffler 
1681091d81d1SSam Leffler 	crypto_done(crp);
1682c0341432SJohn Baldwin 	return (0);
1683091d81d1SSam Leffler }
1684091d81d1SSam Leffler 
1685091d81d1SSam Leffler static void
swcr_identify(driver_t * drv,device_t parent)16863f147ab2SWarner Losh swcr_identify(driver_t *drv, device_t parent)
1687091d81d1SSam Leffler {
16886810ad6fSSam Leffler 	/* NB: order 10 is so we get attached after h/w devices */
16896810ad6fSSam Leffler 	if (device_find_child(parent, "cryptosoft", -1) == NULL &&
169086c585d9SMarius Strobl 	    BUS_ADD_CHILD(parent, 10, "cryptosoft", 0) == 0)
16916810ad6fSSam Leffler 		panic("cryptosoft: could not attach");
16926810ad6fSSam Leffler }
1693f6c4bc3bSPawel Jakub Dawidek 
16946810ad6fSSam Leffler static int
swcr_probe(device_t dev)16956810ad6fSSam Leffler swcr_probe(device_t dev)
16966810ad6fSSam Leffler {
16976810ad6fSSam Leffler 	device_set_desc(dev, "software crypto");
16984fc60fa9SMark Johnston 	device_quiet(dev);
169986c585d9SMarius Strobl 	return (BUS_PROBE_NOWILDCARD);
17006810ad6fSSam Leffler }
1701f6c4bc3bSPawel Jakub Dawidek 
17026810ad6fSSam Leffler static int
swcr_attach(device_t dev)17036810ad6fSSam Leffler swcr_attach(device_t dev)
17046810ad6fSSam Leffler {
17056810ad6fSSam Leffler 
17069ebbebe4SConrad Meyer 	swcr_id = crypto_get_driverid(dev, sizeof(struct swcr_session),
17076810ad6fSSam Leffler 			CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC);
17086810ad6fSSam Leffler 	if (swcr_id < 0) {
17096810ad6fSSam Leffler 		device_printf(dev, "cannot initialize!");
1710c0341432SJohn Baldwin 		return (ENXIO);
17116810ad6fSSam Leffler 	}
17126810ad6fSSam Leffler 
1713c0341432SJohn Baldwin 	return (0);
1714091d81d1SSam Leffler }
17154b465da2SPawel Jakub Dawidek 
17163f147ab2SWarner Losh static int
swcr_detach(device_t dev)17176810ad6fSSam Leffler swcr_detach(device_t dev)
17184b465da2SPawel Jakub Dawidek {
17196810ad6fSSam Leffler 	crypto_unregister_all(swcr_id);
17203f147ab2SWarner Losh 	return 0;
17214b465da2SPawel Jakub Dawidek }
17226810ad6fSSam Leffler 
17236810ad6fSSam Leffler static device_method_t swcr_methods[] = {
17246810ad6fSSam Leffler 	DEVMETHOD(device_identify,	swcr_identify),
17256810ad6fSSam Leffler 	DEVMETHOD(device_probe,		swcr_probe),
17266810ad6fSSam Leffler 	DEVMETHOD(device_attach,	swcr_attach),
17276810ad6fSSam Leffler 	DEVMETHOD(device_detach,	swcr_detach),
17286810ad6fSSam Leffler 
1729c0341432SJohn Baldwin 	DEVMETHOD(cryptodev_probesession, swcr_probesession),
17306810ad6fSSam Leffler 	DEVMETHOD(cryptodev_newsession,	swcr_newsession),
17316810ad6fSSam Leffler 	DEVMETHOD(cryptodev_freesession,swcr_freesession),
17326810ad6fSSam Leffler 	DEVMETHOD(cryptodev_process,	swcr_process),
17336810ad6fSSam Leffler 
17346810ad6fSSam Leffler 	{0, 0},
17356810ad6fSSam Leffler };
17366810ad6fSSam Leffler 
17376810ad6fSSam Leffler static driver_t swcr_driver = {
17386810ad6fSSam Leffler 	"cryptosoft",
17396810ad6fSSam Leffler 	swcr_methods,
17406810ad6fSSam Leffler 	0,		/* NB: no softc */
17416810ad6fSSam Leffler };
17426810ad6fSSam Leffler 
17436810ad6fSSam Leffler /*
17446810ad6fSSam Leffler  * NB: We explicitly reference the crypto module so we
17456810ad6fSSam Leffler  * get the necessary ordering when built as a loadable
17466810ad6fSSam Leffler  * module.  This is required because we bundle the crypto
17476810ad6fSSam Leffler  * module code together with the cryptosoft driver (otherwise
17486810ad6fSSam Leffler  * normal module dependencies would handle things).
17496810ad6fSSam Leffler  */
17506810ad6fSSam Leffler extern int crypto_modevent(struct module *, int, void *);
17516810ad6fSSam Leffler /* XXX where to attach */
1752ab050b2bSJohn Baldwin DRIVER_MODULE(cryptosoft, nexus, swcr_driver, crypto_modevent, NULL);
17536810ad6fSSam Leffler MODULE_VERSION(cryptosoft, 1);
17546810ad6fSSam Leffler MODULE_DEPEND(cryptosoft, crypto, 1, 1, 1);
1755