xref: /freebsd/sys/opencrypto/cryptosoft.c (revision 04781697f8e675528078249ff79c3e948a95b7c9)
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 {
78dc475c9bSJohn 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
91dc475c9bSJohn 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
101dc475c9bSJohn Baldwin swcr_encdec(const struct swcr_session *ses, struct cryptop *crp)
102091d81d1SSam Leffler {
1032cd83828SJohn Baldwin 	unsigned char blk[EALG_MAX_BLOCK_LEN];
104c0341432SJohn Baldwin 	const struct crypto_session_params *csp;
105d8787d4fSMark Johnston 	const struct enc_xform *exf;
106b54d1284SJohn Baldwin 	const struct swcr_encdec *sw;
107b54d1284SJohn Baldwin 	void *ctx;
10886be314dSJohn Baldwin 	size_t inlen, outlen;
1092cd83828SJohn Baldwin 	int blks, resid;
1109c0e3d3aSJohn Baldwin 	struct crypto_buffer_cursor cc_in, cc_out;
11126d292d3SJohn Baldwin 	const unsigned char *inblk;
11226d292d3SJohn Baldwin 	unsigned char *outblk;
11308fca7a5SJohn-Mark Gurney 	int error;
114c0341432SJohn Baldwin 	bool encrypting;
11508fca7a5SJohn-Mark Gurney 
11608fca7a5SJohn-Mark Gurney 	error = 0;
117091d81d1SSam Leffler 
118c0341432SJohn Baldwin 	sw = &ses->swcr_encdec;
119091d81d1SSam Leffler 	exf = sw->sw_exf;
1201833d604SJohn Baldwin 	csp = crypto_get_params(crp->crp_session);
121091d81d1SSam Leffler 
122723d8764SJohn Baldwin 	if (exf->native_blocksize == 0) {
123091d81d1SSam Leffler 		/* Check for non-padded data */
124723d8764SJohn Baldwin 		if ((crp->crp_payload_length % exf->blocksize) != 0)
125723d8764SJohn Baldwin 			return (EINVAL);
126723d8764SJohn Baldwin 
127723d8764SJohn Baldwin 		blks = exf->blocksize;
128723d8764SJohn Baldwin 	} else
129723d8764SJohn Baldwin 		blks = exf->native_blocksize;
130091d81d1SSam Leffler 
131c0341432SJohn Baldwin 	if (exf == &enc_xform_aes_icm &&
132c0341432SJohn Baldwin 	    (crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0)
13308fca7a5SJohn-Mark Gurney 		return (EINVAL);
13408fca7a5SJohn-Mark Gurney 
135b54d1284SJohn Baldwin 	ctx = __builtin_alloca(exf->ctxsize);
136c0341432SJohn Baldwin 	if (crp->crp_cipher_key != NULL) {
137b54d1284SJohn Baldwin 		error = exf->setkey(ctx, crp->crp_cipher_key,
138b54d1284SJohn Baldwin 		    csp->csp_cipher_klen);
139c740ae4bSPoul-Henning Kamp 		if (error)
140c740ae4bSPoul-Henning Kamp 			return (error);
141b54d1284SJohn Baldwin 	} else
142b54d1284SJohn Baldwin 		memcpy(ctx, sw->sw_ctx, exf->ctxsize);
143d295bdeeSPawel Jakub Dawidek 
1442cd83828SJohn Baldwin 	crypto_read_iv(crp, blk);
1452cd83828SJohn Baldwin 	exf->reinit(ctx, blk, csp->csp_ivlen);
146091d81d1SSam Leffler 
1479c0e3d3aSJohn Baldwin 	crypto_cursor_init(&cc_in, &crp->crp_buf);
1489c0e3d3aSJohn Baldwin 	crypto_cursor_advance(&cc_in, crp->crp_payload_start);
14986be314dSJohn Baldwin 	inblk = crypto_cursor_segment(&cc_in, &inlen);
1509c0e3d3aSJohn Baldwin 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
1519c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_out, &crp->crp_obuf);
1529c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_out, crp->crp_payload_output_start);
1539c0e3d3aSJohn Baldwin 	} else
1549c0e3d3aSJohn Baldwin 		cc_out = cc_in;
15586be314dSJohn Baldwin 	outblk = crypto_cursor_segment(&cc_out, &outlen);
1569c0e3d3aSJohn Baldwin 
1579c0e3d3aSJohn Baldwin 	resid = crp->crp_payload_length;
158c0341432SJohn Baldwin 	encrypting = CRYPTO_OP_IS_ENCRYPT(crp->crp_op);
159091d81d1SSam Leffler 
160091d81d1SSam Leffler 	/*
1619c0e3d3aSJohn Baldwin 	 * Loop through encrypting blocks.  'inlen' is the remaining
1629c0e3d3aSJohn Baldwin 	 * length of the current segment in the input buffer.
1639c0e3d3aSJohn Baldwin 	 * 'outlen' is the remaining length of current segment in the
1649c0e3d3aSJohn Baldwin 	 * output buffer.
165091d81d1SSam Leffler 	 */
1669c0e3d3aSJohn Baldwin 	while (resid >= blks) {
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 		 */
1729c0e3d3aSJohn Baldwin 		if (inlen < blks) {
1739c0e3d3aSJohn Baldwin 			crypto_cursor_copydata(&cc_in, blks, blk);
1749c0e3d3aSJohn Baldwin 			inblk = blk;
175d295bdeeSPawel Jakub Dawidek 		}
1769c0e3d3aSJohn Baldwin 		if (outlen < blks)
1779c0e3d3aSJohn Baldwin 			outblk = blk;
1789c0e3d3aSJohn Baldwin 
1799c0e3d3aSJohn Baldwin 		if (encrypting)
180b54d1284SJohn Baldwin 			exf->encrypt(ctx, inblk, outblk);
1819c0e3d3aSJohn Baldwin 		else
182b54d1284SJohn Baldwin 			exf->decrypt(ctx, inblk, outblk);
183091d81d1SSam Leffler 
1849c0e3d3aSJohn Baldwin 		if (inlen < blks) {
18586be314dSJohn Baldwin 			inblk = crypto_cursor_segment(&cc_in, &inlen);
1869c0e3d3aSJohn Baldwin 		} else {
1879c0e3d3aSJohn Baldwin 			crypto_cursor_advance(&cc_in, blks);
1889c0e3d3aSJohn Baldwin 			inlen -= blks;
1899c0e3d3aSJohn Baldwin 			inblk += blks;
19008fca7a5SJohn-Mark Gurney 		}
191091d81d1SSam Leffler 
1929c0e3d3aSJohn Baldwin 		if (outlen < blks) {
1939c0e3d3aSJohn Baldwin 			crypto_cursor_copyback(&cc_out, blks, blk);
19486be314dSJohn Baldwin 			outblk = crypto_cursor_segment(&cc_out, &outlen);
1959c0e3d3aSJohn Baldwin 		} else {
1969c0e3d3aSJohn Baldwin 			crypto_cursor_advance(&cc_out, blks);
1979c0e3d3aSJohn Baldwin 			outlen -= blks;
1989c0e3d3aSJohn Baldwin 			outblk += blks;
199091d81d1SSam Leffler 		}
200091d81d1SSam Leffler 
2019c0e3d3aSJohn Baldwin 		resid -= blks;
202f34a967bSPawel Jakub Dawidek 	}
203f34a967bSPawel Jakub Dawidek 
204723d8764SJohn Baldwin 	/* Handle trailing partial block for stream ciphers. */
2059c0e3d3aSJohn Baldwin 	if (resid > 0) {
206723d8764SJohn Baldwin 		KASSERT(exf->native_blocksize != 0,
207723d8764SJohn Baldwin 		    ("%s: partial block of %d bytes for cipher %s",
2082cd83828SJohn Baldwin 		    __func__, resid, exf->name));
2099c0e3d3aSJohn Baldwin 		KASSERT(resid < blks, ("%s: partial block too big", __func__));
210723d8764SJohn Baldwin 
21186be314dSJohn Baldwin 		inblk = crypto_cursor_segment(&cc_in, &inlen);
21286be314dSJohn Baldwin 		outblk = crypto_cursor_segment(&cc_out, &outlen);
2139c0e3d3aSJohn Baldwin 		if (inlen < resid) {
2149c0e3d3aSJohn Baldwin 			crypto_cursor_copydata(&cc_in, resid, blk);
2159c0e3d3aSJohn Baldwin 			inblk = blk;
21686be314dSJohn Baldwin 		}
2179c0e3d3aSJohn Baldwin 		if (outlen < resid)
2189c0e3d3aSJohn Baldwin 			outblk = blk;
2199c0e3d3aSJohn Baldwin 		if (encrypting)
220b54d1284SJohn Baldwin 			exf->encrypt_last(ctx, inblk, outblk,
2219c0e3d3aSJohn Baldwin 			    resid);
2229c0e3d3aSJohn Baldwin 		else
223b54d1284SJohn Baldwin 			exf->decrypt_last(ctx, inblk, outblk,
2249c0e3d3aSJohn Baldwin 			    resid);
2259c0e3d3aSJohn Baldwin 		if (outlen < resid)
2269c0e3d3aSJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
227723d8764SJohn Baldwin 	}
228723d8764SJohn Baldwin 
229b54d1284SJohn Baldwin 	explicit_bzero(ctx, exf->ctxsize);
23020c128daSJohn Baldwin 	explicit_bzero(blk, sizeof(blk));
2319c0e3d3aSJohn Baldwin 	return (0);
232091d81d1SSam Leffler }
233091d81d1SSam Leffler 
234091d81d1SSam Leffler /*
235c0341432SJohn Baldwin  * Compute or verify hash.
236091d81d1SSam Leffler  */
237091d81d1SSam Leffler static int
238dc475c9bSJohn Baldwin swcr_authcompute(const struct swcr_session *ses, struct cryptop *crp)
239091d81d1SSam Leffler {
2407051c579SJohn Baldwin 	struct {
2417051c579SJohn Baldwin 		union authctx ctx;
242c0341432SJohn Baldwin 		u_char aalg[HASH_MAX_LEN];
2437051c579SJohn Baldwin 		u_char uaalg[HASH_MAX_LEN];
2447051c579SJohn Baldwin 	} s;
245c0341432SJohn Baldwin 	const struct crypto_session_params *csp;
2466113a08bSJohn Baldwin 	const struct swcr_auth *sw;
247d8787d4fSMark Johnston 	const struct auth_hash *axf;
248091d81d1SSam Leffler 	int err;
249091d81d1SSam Leffler 
250c0341432SJohn Baldwin 	sw = &ses->swcr_auth;
251091d81d1SSam Leffler 
252091d81d1SSam Leffler 	axf = sw->sw_axf;
253091d81d1SSam Leffler 
254c0341432SJohn Baldwin 	csp = crypto_get_params(crp->crp_session);
2556038018aSMarcin Wojtas 	if (crp->crp_auth_key != NULL) {
2566113a08bSJohn Baldwin 		if (sw->sw_hmac) {
2576113a08bSJohn Baldwin 			hmac_init_ipad(axf, crp->crp_auth_key,
2587051c579SJohn Baldwin 			    csp->csp_auth_klen, &s.ctx);
2596113a08bSJohn Baldwin 		} else {
2607051c579SJohn Baldwin 			axf->Init(&s.ctx);
2617051c579SJohn Baldwin 			axf->Setkey(&s.ctx, crp->crp_auth_key,
262c0341432SJohn Baldwin 			    csp->csp_auth_klen);
26325b7033bSConrad Meyer 		}
2646113a08bSJohn Baldwin 	} else
2657051c579SJohn Baldwin 		memcpy(&s.ctx, sw->sw_ictx, axf->ctxsize);
266091d81d1SSam Leffler 
2679b774dc0SJohn Baldwin 	if (crp->crp_aad != NULL)
2687051c579SJohn Baldwin 		err = axf->Update(&s.ctx, crp->crp_aad, crp->crp_aad_length);
2699b774dc0SJohn Baldwin 	else
270c0341432SJohn Baldwin 		err = crypto_apply(crp, crp->crp_aad_start, crp->crp_aad_length,
2717051c579SJohn Baldwin 		    axf->Update, &s.ctx);
272091d81d1SSam Leffler 	if (err)
273e0b155feSJohn Baldwin 		goto out;
274091d81d1SSam Leffler 
2759c0e3d3aSJohn Baldwin 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp) &&
2769c0e3d3aSJohn Baldwin 	    CRYPTO_OP_IS_ENCRYPT(crp->crp_op))
2779c0e3d3aSJohn Baldwin 		err = crypto_apply_buf(&crp->crp_obuf,
2789c0e3d3aSJohn Baldwin 		    crp->crp_payload_output_start, crp->crp_payload_length,
2797051c579SJohn Baldwin 		    axf->Update, &s.ctx);
2809c0e3d3aSJohn Baldwin 	else
2819c0e3d3aSJohn Baldwin 		err = crypto_apply(crp, crp->crp_payload_start,
2827051c579SJohn Baldwin 		    crp->crp_payload_length, axf->Update, &s.ctx);
283c0341432SJohn Baldwin 	if (err)
284e0b155feSJohn Baldwin 		goto out;
285091d81d1SSam Leffler 
2866038018aSMarcin Wojtas 	if (csp->csp_flags & CSP_F_ESN)
2877051c579SJohn Baldwin 		axf->Update(&s.ctx, crp->crp_esn, 4);
2886038018aSMarcin Wojtas 
2897051c579SJohn Baldwin 	axf->Final(s.aalg, &s.ctx);
2906113a08bSJohn Baldwin 	if (sw->sw_hmac) {
2916113a08bSJohn Baldwin 		if (crp->crp_auth_key != NULL)
2926113a08bSJohn Baldwin 			hmac_init_opad(axf, crp->crp_auth_key,
2937051c579SJohn Baldwin 			    csp->csp_auth_klen, &s.ctx);
2946113a08bSJohn Baldwin 		else
2957051c579SJohn Baldwin 			memcpy(&s.ctx, sw->sw_octx, axf->ctxsize);
2967051c579SJohn Baldwin 		axf->Update(&s.ctx, s.aalg, axf->hashsize);
2977051c579SJohn Baldwin 		axf->Final(s.aalg, &s.ctx);
298091d81d1SSam Leffler 	}
299091d81d1SSam Leffler 
300c0341432SJohn Baldwin 	if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
3017051c579SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, sw->sw_mlen, s.uaalg);
3027051c579SJohn Baldwin 		if (timingsafe_bcmp(s.aalg, s.uaalg, sw->sw_mlen) != 0)
30320c128daSJohn Baldwin 			err = EBADMSG;
304c0341432SJohn Baldwin 	} else {
305091d81d1SSam Leffler 		/* Inject the authentication data */
3067051c579SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, sw->sw_mlen, s.aalg);
307c0341432SJohn Baldwin 	}
308e0b155feSJohn Baldwin out:
3097051c579SJohn Baldwin 	explicit_bzero(&s, sizeof(s));
31020c128daSJohn Baldwin 	return (err);
311091d81d1SSam Leffler }
312091d81d1SSam Leffler 
31308fca7a5SJohn-Mark Gurney CTASSERT(INT_MAX <= (1ll<<39) - 256);	/* GCM: plain text < 2^39-256 */
31408fca7a5SJohn-Mark Gurney CTASSERT(INT_MAX <= (uint64_t)-1);	/* GCM: associated data <= 2^64-1 */
31508fca7a5SJohn-Mark Gurney 
31608fca7a5SJohn-Mark Gurney static int
317dc475c9bSJohn Baldwin swcr_gmac(const struct swcr_session *ses, struct cryptop *crp)
31808fca7a5SJohn-Mark Gurney {
3197051c579SJohn Baldwin 	struct {
3207051c579SJohn Baldwin 		union authctx ctx;
32126d292d3SJohn Baldwin 		uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))];
32226d292d3SJohn Baldwin 		u_char tag[GMAC_DIGEST_LEN];
3237051c579SJohn Baldwin 		u_char tag2[GMAC_DIGEST_LEN];
3247051c579SJohn Baldwin 	} s;
3257051c579SJohn Baldwin 	u_char *blk = (u_char *)s.blkbuf;
3269c0e3d3aSJohn Baldwin 	struct crypto_buffer_cursor cc;
32726d292d3SJohn Baldwin 	const u_char *inblk;
3286113a08bSJohn Baldwin 	const struct swcr_auth *swa;
329d8787d4fSMark Johnston 	const struct auth_hash *axf;
33008fca7a5SJohn-Mark Gurney 	uint32_t *blkp;
33186be314dSJohn Baldwin 	size_t len;
33286be314dSJohn Baldwin 	int blksz, error, ivlen, resid;
33308fca7a5SJohn-Mark Gurney 
334c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
33508fca7a5SJohn-Mark Gurney 	axf = swa->sw_axf;
33626d292d3SJohn Baldwin 	blksz = GMAC_BLOCK_LEN;
33726d292d3SJohn Baldwin 	KASSERT(axf->blocksize == blksz, ("%s: axf block size mismatch",
33826d292d3SJohn Baldwin 	    __func__));
33908fca7a5SJohn-Mark Gurney 
3406113a08bSJohn Baldwin 	if (crp->crp_auth_key != NULL) {
3417051c579SJohn Baldwin 		axf->Init(&s.ctx);
3427051c579SJohn Baldwin 		axf->Setkey(&s.ctx, crp->crp_auth_key,
3436113a08bSJohn Baldwin 		    crypto_get_params(crp->crp_session)->csp_auth_klen);
3446113a08bSJohn Baldwin 	} else
3457051c579SJohn Baldwin 		memcpy(&s.ctx, swa->sw_ictx, axf->ctxsize);
3466113a08bSJohn Baldwin 
34708fca7a5SJohn-Mark Gurney 	/* Initialize the IV */
348c0341432SJohn Baldwin 	ivlen = AES_GCM_IV_LEN;
3491c9b25a5SJohn Baldwin 	crypto_read_iv(crp, blk);
35008fca7a5SJohn-Mark Gurney 
3517051c579SJohn Baldwin 	axf->Reinit(&s.ctx, blk, ivlen);
3529c0e3d3aSJohn Baldwin 	crypto_cursor_init(&cc, &crp->crp_buf);
3539c0e3d3aSJohn Baldwin 	crypto_cursor_advance(&cc, crp->crp_payload_start);
35426d292d3SJohn Baldwin 	for (resid = crp->crp_payload_length; resid >= blksz; resid -= len) {
35586be314dSJohn Baldwin 		inblk = crypto_cursor_segment(&cc, &len);
35626d292d3SJohn Baldwin 		if (len >= blksz) {
35726d292d3SJohn Baldwin 			len = rounddown(MIN(len, resid), blksz);
35826d292d3SJohn Baldwin 			crypto_cursor_advance(&cc, len);
35926d292d3SJohn Baldwin 		} else {
36026d292d3SJohn Baldwin 			len = blksz;
3619c0e3d3aSJohn Baldwin 			crypto_cursor_copydata(&cc, len, blk);
36226d292d3SJohn Baldwin 			inblk = blk;
36326d292d3SJohn Baldwin 		}
3647051c579SJohn Baldwin 		axf->Update(&s.ctx, inblk, len);
36526d292d3SJohn Baldwin 	}
36626d292d3SJohn Baldwin 	if (resid > 0) {
36726d292d3SJohn Baldwin 		memset(blk, 0, blksz);
36826d292d3SJohn Baldwin 		crypto_cursor_copydata(&cc, resid, blk);
3697051c579SJohn Baldwin 		axf->Update(&s.ctx, blk, blksz);
37008fca7a5SJohn-Mark Gurney 	}
37108fca7a5SJohn-Mark Gurney 
37208fca7a5SJohn-Mark Gurney 	/* length block */
37326d292d3SJohn Baldwin 	memset(blk, 0, blksz);
37408fca7a5SJohn-Mark Gurney 	blkp = (uint32_t *)blk + 1;
375c0341432SJohn Baldwin 	*blkp = htobe32(crp->crp_payload_length * 8);
3767051c579SJohn Baldwin 	axf->Update(&s.ctx, blk, blksz);
377c0341432SJohn Baldwin 
378c0341432SJohn Baldwin 	/* Finalize MAC */
3797051c579SJohn Baldwin 	axf->Final(s.tag, &s.ctx);
380c0341432SJohn Baldwin 
38120c128daSJohn Baldwin 	error = 0;
382c0341432SJohn Baldwin 	if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
383c0341432SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen,
3847051c579SJohn Baldwin 		    s.tag2);
3857051c579SJohn Baldwin 		if (timingsafe_bcmp(s.tag, s.tag2, swa->sw_mlen) != 0)
38620c128daSJohn Baldwin 			error = EBADMSG;
387c0341432SJohn Baldwin 	} else {
388c0341432SJohn Baldwin 		/* Inject the authentication data */
3897051c579SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, s.tag);
390c0341432SJohn Baldwin 	}
3917051c579SJohn Baldwin 	explicit_bzero(&s, sizeof(s));
39220c128daSJohn Baldwin 	return (error);
393c0341432SJohn Baldwin }
394c0341432SJohn Baldwin 
395c0341432SJohn Baldwin static int
396dc475c9bSJohn Baldwin swcr_gcm(const struct swcr_session *ses, struct cryptop *crp)
397c0341432SJohn Baldwin {
3987051c579SJohn Baldwin 	struct {
39926d292d3SJohn Baldwin 		uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))];
40026d292d3SJohn Baldwin 		u_char tag[GMAC_DIGEST_LEN];
4017051c579SJohn Baldwin 		u_char tag2[GMAC_DIGEST_LEN];
4027051c579SJohn Baldwin 	} s;
4037051c579SJohn Baldwin 	u_char *blk = (u_char *)s.blkbuf;
4049c0e3d3aSJohn Baldwin 	struct crypto_buffer_cursor cc_in, cc_out;
40526d292d3SJohn Baldwin 	const u_char *inblk;
40626d292d3SJohn Baldwin 	u_char *outblk;
407b54d1284SJohn Baldwin 	const struct swcr_auth *swa;
408b54d1284SJohn Baldwin 	const struct swcr_encdec *swe;
409d8787d4fSMark Johnston 	const struct enc_xform *exf;
410b54d1284SJohn Baldwin 	void *ctx;
411c0341432SJohn Baldwin 	uint32_t *blkp;
41286be314dSJohn Baldwin 	size_t len;
41386be314dSJohn Baldwin 	int blksz, error, ivlen, r, resid;
414c0341432SJohn Baldwin 
415c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
416c0341432SJohn Baldwin 	swe = &ses->swcr_encdec;
417c0341432SJohn Baldwin 	exf = swe->sw_exf;
418ab91fb6cSJohn Baldwin 	blksz = GMAC_BLOCK_LEN;
419ab91fb6cSJohn Baldwin 	KASSERT(blksz == exf->native_blocksize,
420723d8764SJohn Baldwin 	    ("%s: blocksize mismatch", __func__));
421c0341432SJohn Baldwin 
422c0341432SJohn Baldwin 	if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0)
423c0341432SJohn Baldwin 		return (EINVAL);
424c0341432SJohn Baldwin 
425c0341432SJohn Baldwin 	ivlen = AES_GCM_IV_LEN;
426c0341432SJohn Baldwin 
427b54d1284SJohn Baldwin 	ctx = __builtin_alloca(exf->ctxsize);
428ab91fb6cSJohn Baldwin 	if (crp->crp_cipher_key != NULL)
429b54d1284SJohn Baldwin 		exf->setkey(ctx, crp->crp_cipher_key,
430ab91fb6cSJohn Baldwin 		    crypto_get_params(crp->crp_session)->csp_cipher_klen);
431b54d1284SJohn Baldwin 	else
432b54d1284SJohn Baldwin 		memcpy(ctx, swe->sw_ctx, exf->ctxsize);
433b54d1284SJohn Baldwin 	exf->reinit(ctx, crp->crp_iv, ivlen);
434c0341432SJohn Baldwin 
435c0341432SJohn Baldwin 	/* Supply MAC with AAD */
4369b774dc0SJohn Baldwin 	if (crp->crp_aad != NULL) {
4379b774dc0SJohn Baldwin 		len = rounddown(crp->crp_aad_length, blksz);
4389b774dc0SJohn Baldwin 		if (len != 0)
439b54d1284SJohn Baldwin 			exf->update(ctx, crp->crp_aad, len);
4409b774dc0SJohn Baldwin 		if (crp->crp_aad_length != len) {
4419b774dc0SJohn Baldwin 			memset(blk, 0, blksz);
4429b774dc0SJohn Baldwin 			memcpy(blk, (char *)crp->crp_aad + len,
4439b774dc0SJohn Baldwin 			    crp->crp_aad_length - len);
444b54d1284SJohn Baldwin 			exf->update(ctx, blk, blksz);
4459b774dc0SJohn Baldwin 		}
4469b774dc0SJohn Baldwin 	} else {
4479c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_in, &crp->crp_buf);
4489c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_in, crp->crp_aad_start);
4499b774dc0SJohn Baldwin 		for (resid = crp->crp_aad_length; resid >= blksz;
4509b774dc0SJohn Baldwin 		     resid -= len) {
45186be314dSJohn Baldwin 			inblk = crypto_cursor_segment(&cc_in, &len);
45226d292d3SJohn Baldwin 			if (len >= blksz) {
45326d292d3SJohn Baldwin 				len = rounddown(MIN(len, resid), blksz);
45426d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_in, len);
45526d292d3SJohn Baldwin 			} else {
45626d292d3SJohn Baldwin 				len = blksz;
4579c0e3d3aSJohn Baldwin 				crypto_cursor_copydata(&cc_in, len, blk);
45826d292d3SJohn Baldwin 				inblk = blk;
45926d292d3SJohn Baldwin 			}
460b54d1284SJohn Baldwin 			exf->update(ctx, inblk, len);
46126d292d3SJohn Baldwin 		}
46226d292d3SJohn Baldwin 		if (resid > 0) {
46326d292d3SJohn Baldwin 			memset(blk, 0, blksz);
46426d292d3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, resid, blk);
465b54d1284SJohn Baldwin 			exf->update(ctx, blk, blksz);
466c0341432SJohn Baldwin 		}
4679b774dc0SJohn Baldwin 	}
468c0341432SJohn Baldwin 
469c0341432SJohn Baldwin 	/* Do encryption with MAC */
4709c0e3d3aSJohn Baldwin 	crypto_cursor_init(&cc_in, &crp->crp_buf);
4719c0e3d3aSJohn Baldwin 	crypto_cursor_advance(&cc_in, crp->crp_payload_start);
4729c0e3d3aSJohn Baldwin 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
4739c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_out, &crp->crp_obuf);
4749c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_out, crp->crp_payload_output_start);
4759c0e3d3aSJohn Baldwin 	} else
4769c0e3d3aSJohn Baldwin 		cc_out = cc_in;
47726d292d3SJohn Baldwin 	for (resid = crp->crp_payload_length; resid >= blksz; resid -= blksz) {
47886be314dSJohn Baldwin 		inblk = crypto_cursor_segment(&cc_in, &len);
47986be314dSJohn Baldwin 		if (len < blksz) {
48026d292d3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, blksz, blk);
48126d292d3SJohn Baldwin 			inblk = blk;
482c0341432SJohn Baldwin 		} else {
48326d292d3SJohn Baldwin 			crypto_cursor_advance(&cc_in, blksz);
484c0341432SJohn Baldwin 		}
48526d292d3SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
48686be314dSJohn Baldwin 			outblk = crypto_cursor_segment(&cc_out, &len);
48786be314dSJohn Baldwin 			if (len < blksz)
48826d292d3SJohn Baldwin 				outblk = blk;
489b54d1284SJohn Baldwin 			exf->encrypt(ctx, inblk, outblk);
490b54d1284SJohn Baldwin 			exf->update(ctx, outblk, blksz);
49126d292d3SJohn Baldwin 			if (outblk == blk)
49226d292d3SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
49326d292d3SJohn Baldwin 			else
49426d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_out, blksz);
49526d292d3SJohn Baldwin 		} else {
496b54d1284SJohn Baldwin 			exf->update(ctx, inblk, blksz);
49726d292d3SJohn Baldwin 		}
49826d292d3SJohn Baldwin 	}
49926d292d3SJohn Baldwin 	if (resid > 0) {
50026d292d3SJohn Baldwin 		crypto_cursor_copydata(&cc_in, resid, blk);
50126d292d3SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
502b54d1284SJohn Baldwin 			exf->encrypt_last(ctx, blk, blk, resid);
50326d292d3SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
50426d292d3SJohn Baldwin 		}
505b54d1284SJohn Baldwin 		exf->update(ctx, blk, resid);
506c0341432SJohn Baldwin 	}
507c0341432SJohn Baldwin 
508c0341432SJohn Baldwin 	/* length block */
50926d292d3SJohn Baldwin 	memset(blk, 0, blksz);
510c0341432SJohn Baldwin 	blkp = (uint32_t *)blk + 1;
511c0341432SJohn Baldwin 	*blkp = htobe32(crp->crp_aad_length * 8);
512c0341432SJohn Baldwin 	blkp = (uint32_t *)blk + 3;
513c0341432SJohn Baldwin 	*blkp = htobe32(crp->crp_payload_length * 8);
514b54d1284SJohn Baldwin 	exf->update(ctx, blk, blksz);
515c0341432SJohn Baldwin 
516c0341432SJohn Baldwin 	/* Finalize MAC */
5177051c579SJohn Baldwin 	exf->final(s.tag, ctx);
518c0341432SJohn Baldwin 
519c0341432SJohn Baldwin 	/* Validate tag */
52020c128daSJohn Baldwin 	error = 0;
521c0341432SJohn Baldwin 	if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
5227051c579SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen,
5237051c579SJohn Baldwin 		    s.tag2);
5247051c579SJohn Baldwin 		r = timingsafe_bcmp(s.tag, s.tag2, swa->sw_mlen);
52520c128daSJohn Baldwin 		if (r != 0) {
52620c128daSJohn Baldwin 			error = EBADMSG;
52720c128daSJohn Baldwin 			goto out;
52820c128daSJohn Baldwin 		}
529c0341432SJohn Baldwin 
530c0341432SJohn Baldwin 		/* tag matches, decrypt data */
5319c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_in, &crp->crp_buf);
5329c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_in, crp->crp_payload_start);
53326d292d3SJohn Baldwin 		for (resid = crp->crp_payload_length; resid > blksz;
53426d292d3SJohn Baldwin 		     resid -= blksz) {
53586be314dSJohn Baldwin 			inblk = crypto_cursor_segment(&cc_in, &len);
53686be314dSJohn Baldwin 			if (len < blksz) {
53726d292d3SJohn Baldwin 				crypto_cursor_copydata(&cc_in, blksz, blk);
53826d292d3SJohn Baldwin 				inblk = blk;
53986be314dSJohn Baldwin 			} else
54026d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_in, blksz);
54186be314dSJohn Baldwin 			outblk = crypto_cursor_segment(&cc_out, &len);
54286be314dSJohn Baldwin 			if (len < blksz)
54326d292d3SJohn Baldwin 				outblk = blk;
544b54d1284SJohn Baldwin 			exf->decrypt(ctx, inblk, outblk);
54526d292d3SJohn Baldwin 			if (outblk == blk)
54626d292d3SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
54726d292d3SJohn Baldwin 			else
54826d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_out, blksz);
54926d292d3SJohn Baldwin 		}
55026d292d3SJohn Baldwin 		if (resid > 0) {
55126d292d3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, resid, blk);
552b54d1284SJohn Baldwin 			exf->decrypt_last(ctx, blk, blk, resid);
55326d292d3SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
554c0341432SJohn Baldwin 		}
555c0341432SJohn Baldwin 	} else {
556c0341432SJohn Baldwin 		/* Inject the authentication data */
5577051c579SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen,
5587051c579SJohn Baldwin 		    s.tag);
559c0341432SJohn Baldwin 	}
560c0341432SJohn Baldwin 
56120c128daSJohn Baldwin out:
562b54d1284SJohn Baldwin 	explicit_bzero(ctx, exf->ctxsize);
5637051c579SJohn Baldwin 	explicit_bzero(&s, sizeof(s));
56420c128daSJohn Baldwin 
56520c128daSJohn Baldwin 	return (error);
566c0341432SJohn Baldwin }
567c0341432SJohn Baldwin 
5684361c4ebSJohn Baldwin static void
5694361c4ebSJohn Baldwin build_ccm_b0(const char *nonce, u_int nonce_length, u_int aad_length,
5704361c4ebSJohn Baldwin     u_int data_length, u_int tag_length, uint8_t *b0)
5714361c4ebSJohn Baldwin {
5724361c4ebSJohn Baldwin 	uint8_t *bp;
5734361c4ebSJohn Baldwin 	uint8_t flags, L;
5744361c4ebSJohn Baldwin 
5754361c4ebSJohn Baldwin 	KASSERT(nonce_length >= 7 && nonce_length <= 13,
5764361c4ebSJohn Baldwin 	    ("nonce_length must be between 7 and 13 bytes"));
5774361c4ebSJohn Baldwin 
5784361c4ebSJohn Baldwin 	/*
5794361c4ebSJohn Baldwin 	 * Need to determine the L field value.  This is the number of
5804361c4ebSJohn Baldwin 	 * bytes needed to specify the length of the message; the length
5814361c4ebSJohn Baldwin 	 * is whatever is left in the 16 bytes after specifying flags and
5824361c4ebSJohn Baldwin 	 * the nonce.
5834361c4ebSJohn Baldwin 	 */
5844361c4ebSJohn Baldwin 	L = 15 - nonce_length;
5854361c4ebSJohn Baldwin 
5864361c4ebSJohn Baldwin 	flags = ((aad_length > 0) << 6) +
5874361c4ebSJohn Baldwin 	    (((tag_length - 2) / 2) << 3) +
5884361c4ebSJohn Baldwin 	    L - 1;
5894361c4ebSJohn Baldwin 
5904361c4ebSJohn Baldwin 	/*
5914361c4ebSJohn Baldwin 	 * Now we need to set up the first block, which has flags, nonce,
5924361c4ebSJohn Baldwin 	 * and the message length.
5934361c4ebSJohn Baldwin 	 */
5944361c4ebSJohn Baldwin 	b0[0] = flags;
5954361c4ebSJohn Baldwin 	memcpy(b0 + 1, nonce, nonce_length);
5964361c4ebSJohn Baldwin 	bp = b0 + 1 + nonce_length;
5974361c4ebSJohn Baldwin 
5984361c4ebSJohn Baldwin 	/* Need to copy L' [aka L-1] bytes of data_length */
5994361c4ebSJohn Baldwin 	for (uint8_t *dst = b0 + CCM_CBC_BLOCK_LEN - 1; dst >= bp; dst--) {
6004361c4ebSJohn Baldwin 		*dst = data_length;
6014361c4ebSJohn Baldwin 		data_length >>= 8;
6024361c4ebSJohn Baldwin 	}
6034361c4ebSJohn Baldwin }
6044361c4ebSJohn Baldwin 
6054361c4ebSJohn Baldwin /* NB: OCF only supports AAD lengths < 2^32. */
6064361c4ebSJohn Baldwin static int
6074361c4ebSJohn Baldwin build_ccm_aad_length(u_int aad_length, uint8_t *blk)
6084361c4ebSJohn Baldwin {
6094361c4ebSJohn Baldwin 	if (aad_length < ((1 << 16) - (1 << 8))) {
6104361c4ebSJohn Baldwin 		be16enc(blk, aad_length);
6114361c4ebSJohn Baldwin 		return (sizeof(uint16_t));
6124361c4ebSJohn Baldwin 	} else {
6134361c4ebSJohn Baldwin 		blk[0] = 0xff;
6144361c4ebSJohn Baldwin 		blk[1] = 0xfe;
6154361c4ebSJohn Baldwin 		be32enc(blk + 2, aad_length);
6164361c4ebSJohn Baldwin 		return (2 + sizeof(uint32_t));
6174361c4ebSJohn Baldwin 	}
6184361c4ebSJohn Baldwin }
6194361c4ebSJohn Baldwin 
620c0341432SJohn Baldwin static int
621dc475c9bSJohn Baldwin swcr_ccm_cbc_mac(const struct swcr_session *ses, struct cryptop *crp)
622c0341432SJohn Baldwin {
6237051c579SJohn Baldwin 	struct {
6247051c579SJohn Baldwin 		union authctx ctx;
6254361c4ebSJohn Baldwin 		u_char blk[CCM_CBC_BLOCK_LEN];
6264361c4ebSJohn Baldwin 		u_char tag[AES_CBC_MAC_HASH_LEN];
6277051c579SJohn Baldwin 		u_char tag2[AES_CBC_MAC_HASH_LEN];
6287051c579SJohn Baldwin 	} s;
629ae18720dSJohn Baldwin 	const struct crypto_session_params *csp;
6306113a08bSJohn Baldwin 	const struct swcr_auth *swa;
631d8787d4fSMark Johnston 	const struct auth_hash *axf;
6324361c4ebSJohn Baldwin 	int error, ivlen, len;
633c0341432SJohn Baldwin 
634ae18720dSJohn Baldwin 	csp = crypto_get_params(crp->crp_session);
635c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
636c0341432SJohn Baldwin 	axf = swa->sw_axf;
637c0341432SJohn Baldwin 
6386113a08bSJohn Baldwin 	if (crp->crp_auth_key != NULL) {
6397051c579SJohn Baldwin 		axf->Init(&s.ctx);
6407051c579SJohn Baldwin 		axf->Setkey(&s.ctx, crp->crp_auth_key, csp->csp_auth_klen);
6416113a08bSJohn Baldwin 	} else
6427051c579SJohn Baldwin 		memcpy(&s.ctx, swa->sw_ictx, axf->ctxsize);
643c0341432SJohn Baldwin 
644c0341432SJohn Baldwin 	/* Initialize the IV */
645ae18720dSJohn Baldwin 	ivlen = csp->csp_ivlen;
646c0341432SJohn Baldwin 
6474361c4ebSJohn Baldwin 	/* Supply MAC with IV */
6487051c579SJohn Baldwin 	axf->Reinit(&s.ctx, crp->crp_iv, ivlen);
649c0341432SJohn Baldwin 
6504361c4ebSJohn Baldwin 	/* Supply MAC with b0. */
6514361c4ebSJohn Baldwin 	build_ccm_b0(crp->crp_iv, ivlen, crp->crp_payload_length, 0,
6527051c579SJohn Baldwin 	    swa->sw_mlen, s.blk);
6537051c579SJohn Baldwin 	axf->Update(&s.ctx, s.blk, CCM_CBC_BLOCK_LEN);
6544361c4ebSJohn Baldwin 
6557051c579SJohn Baldwin 	len = build_ccm_aad_length(crp->crp_payload_length, s.blk);
6567051c579SJohn Baldwin 	axf->Update(&s.ctx, s.blk, len);
6574361c4ebSJohn Baldwin 
6584361c4ebSJohn Baldwin 	crypto_apply(crp, crp->crp_payload_start, crp->crp_payload_length,
6597051c579SJohn Baldwin 	    axf->Update, &s.ctx);
660c0341432SJohn Baldwin 
661c0341432SJohn Baldwin 	/* Finalize MAC */
6627051c579SJohn Baldwin 	axf->Final(s.tag, &s.ctx);
663c0341432SJohn Baldwin 
6644361c4ebSJohn Baldwin 	error = 0;
665c0341432SJohn Baldwin 	if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
666c0341432SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen,
6677051c579SJohn Baldwin 		    s.tag2);
6687051c579SJohn Baldwin 		if (timingsafe_bcmp(s.tag, s.tag2, swa->sw_mlen) != 0)
66920c128daSJohn Baldwin 			error = EBADMSG;
670c0341432SJohn Baldwin 	} else {
671c0341432SJohn Baldwin 		/* Inject the authentication data */
6727051c579SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen,
6737051c579SJohn Baldwin 		    s.tag);
674c0341432SJohn Baldwin 	}
6757051c579SJohn Baldwin 	explicit_bzero(&s, sizeof(s));
67620c128daSJohn Baldwin 	return (error);
677c0341432SJohn Baldwin }
678c0341432SJohn Baldwin 
679c0341432SJohn Baldwin static int
680dc475c9bSJohn Baldwin swcr_ccm(const struct swcr_session *ses, struct cryptop *crp)
681c0341432SJohn Baldwin {
682ae18720dSJohn Baldwin 	const struct crypto_session_params *csp;
6837051c579SJohn Baldwin 	struct {
68426d292d3SJohn Baldwin 		uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))];
68526d292d3SJohn Baldwin 		u_char tag[AES_CBC_MAC_HASH_LEN];
6867051c579SJohn Baldwin 		u_char tag2[AES_CBC_MAC_HASH_LEN];
6877051c579SJohn Baldwin 	} s;
6887051c579SJohn Baldwin 	u_char *blk = (u_char *)s.blkbuf;
6899c0e3d3aSJohn Baldwin 	struct crypto_buffer_cursor cc_in, cc_out;
69026d292d3SJohn Baldwin 	const u_char *inblk;
69126d292d3SJohn Baldwin 	u_char *outblk;
692b54d1284SJohn Baldwin 	const struct swcr_auth *swa;
693b54d1284SJohn Baldwin 	const struct swcr_encdec *swe;
694d8787d4fSMark Johnston 	const struct enc_xform *exf;
695b54d1284SJohn Baldwin 	void *ctx;
69686be314dSJohn Baldwin 	size_t len;
69726d292d3SJohn Baldwin 	int blksz, error, ivlen, r, resid;
698c0341432SJohn Baldwin 
699ae18720dSJohn Baldwin 	csp = crypto_get_params(crp->crp_session);
700c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
701c0341432SJohn Baldwin 	swe = &ses->swcr_encdec;
702c0341432SJohn Baldwin 	exf = swe->sw_exf;
703ab91fb6cSJohn Baldwin 	blksz = AES_BLOCK_LEN;
704ab91fb6cSJohn Baldwin 	KASSERT(blksz == exf->native_blocksize,
705723d8764SJohn Baldwin 	    ("%s: blocksize mismatch", __func__));
706c0341432SJohn Baldwin 
707ae18720dSJohn Baldwin 	if (crp->crp_payload_length > ccm_max_payload_length(csp))
708ae18720dSJohn Baldwin 		return (EMSGSIZE);
709ae18720dSJohn Baldwin 
710c0341432SJohn Baldwin 	if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0)
711c0341432SJohn Baldwin 		return (EINVAL);
712c0341432SJohn Baldwin 
713ae18720dSJohn Baldwin 	ivlen = csp->csp_ivlen;
714c0341432SJohn Baldwin 
715b54d1284SJohn Baldwin 	ctx = __builtin_alloca(exf->ctxsize);
716ab91fb6cSJohn Baldwin 	if (crp->crp_cipher_key != NULL)
717b54d1284SJohn Baldwin 		exf->setkey(ctx, crp->crp_cipher_key,
718ab91fb6cSJohn Baldwin 		    crypto_get_params(crp->crp_session)->csp_cipher_klen);
719b54d1284SJohn Baldwin 	else
720b54d1284SJohn Baldwin 		memcpy(ctx, swe->sw_ctx, exf->ctxsize);
721b54d1284SJohn Baldwin 	exf->reinit(ctx, crp->crp_iv, ivlen);
722c0341432SJohn Baldwin 
7234361c4ebSJohn Baldwin 	/* Supply MAC with b0. */
7247051c579SJohn Baldwin 	_Static_assert(sizeof(s.blkbuf) >= CCM_CBC_BLOCK_LEN,
7254361c4ebSJohn Baldwin 	    "blkbuf too small for b0");
7264361c4ebSJohn Baldwin 	build_ccm_b0(crp->crp_iv, ivlen, crp->crp_aad_length,
7274361c4ebSJohn Baldwin 	    crp->crp_payload_length, swa->sw_mlen, blk);
728b54d1284SJohn Baldwin 	exf->update(ctx, blk, CCM_CBC_BLOCK_LEN);
7294361c4ebSJohn Baldwin 
730c0341432SJohn Baldwin 	/* Supply MAC with AAD */
7314361c4ebSJohn Baldwin 	if (crp->crp_aad_length != 0) {
7324361c4ebSJohn Baldwin 		len = build_ccm_aad_length(crp->crp_aad_length, blk);
733b54d1284SJohn Baldwin 		exf->update(ctx, blk, len);
7349b774dc0SJohn Baldwin 		if (crp->crp_aad != NULL)
735b54d1284SJohn Baldwin 			exf->update(ctx, crp->crp_aad, crp->crp_aad_length);
7369b774dc0SJohn Baldwin 		else
7374361c4ebSJohn Baldwin 			crypto_apply(crp, crp->crp_aad_start,
738b54d1284SJohn Baldwin 			    crp->crp_aad_length, exf->update, ctx);
7394361c4ebSJohn Baldwin 
7404361c4ebSJohn Baldwin 		/* Pad the AAD (including length field) to a full block. */
7414361c4ebSJohn Baldwin 		len = (len + crp->crp_aad_length) % CCM_CBC_BLOCK_LEN;
7424361c4ebSJohn Baldwin 		if (len != 0) {
7434361c4ebSJohn Baldwin 			len = CCM_CBC_BLOCK_LEN - len;
7444361c4ebSJohn Baldwin 			memset(blk, 0, CCM_CBC_BLOCK_LEN);
745b54d1284SJohn Baldwin 			exf->update(ctx, blk, len);
7464361c4ebSJohn Baldwin 		}
7474361c4ebSJohn Baldwin 	}
748c0341432SJohn Baldwin 
749c0341432SJohn Baldwin 	/* Do encryption/decryption with MAC */
7509c0e3d3aSJohn Baldwin 	crypto_cursor_init(&cc_in, &crp->crp_buf);
7519c0e3d3aSJohn Baldwin 	crypto_cursor_advance(&cc_in, crp->crp_payload_start);
7529c0e3d3aSJohn Baldwin 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
7539c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_out, &crp->crp_obuf);
7549c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_out, crp->crp_payload_output_start);
7559c0e3d3aSJohn Baldwin 	} else
7569c0e3d3aSJohn Baldwin 		cc_out = cc_in;
75726d292d3SJohn Baldwin 	for (resid = crp->crp_payload_length; resid >= blksz; resid -= blksz) {
75886be314dSJohn Baldwin 		inblk = crypto_cursor_segment(&cc_in, &len);
75986be314dSJohn Baldwin 		if (len < blksz) {
76026d292d3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, blksz, blk);
76126d292d3SJohn Baldwin 			inblk = blk;
76286be314dSJohn Baldwin 		} else
76326d292d3SJohn Baldwin 			crypto_cursor_advance(&cc_in, blksz);
764c0341432SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
76586be314dSJohn Baldwin 			outblk = crypto_cursor_segment(&cc_out, &len);
76686be314dSJohn Baldwin 			if (len < blksz)
76726d292d3SJohn Baldwin 				outblk = blk;
768b54d1284SJohn Baldwin 			exf->update(ctx, inblk, blksz);
769b54d1284SJohn Baldwin 			exf->encrypt(ctx, inblk, outblk);
77026d292d3SJohn Baldwin 			if (outblk == blk)
77126d292d3SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
77226d292d3SJohn Baldwin 			else
77326d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_out, blksz);
774c0341432SJohn Baldwin 		} else {
775c0341432SJohn Baldwin 			/*
776c0341432SJohn Baldwin 			 * One of the problems with CCM+CBC is that
777c0341432SJohn Baldwin 			 * the authentication is done on the
77826d292d3SJohn Baldwin 			 * unencrypted data.  As a result, we have to
779c0341432SJohn Baldwin 			 * decrypt the data twice: once to generate
780c0341432SJohn Baldwin 			 * the tag and a second time after the tag is
781c0341432SJohn Baldwin 			 * verified.
782c0341432SJohn Baldwin 			 */
783b54d1284SJohn Baldwin 			exf->decrypt(ctx, inblk, blk);
784b54d1284SJohn Baldwin 			exf->update(ctx, blk, blksz);
78526d292d3SJohn Baldwin 		}
78626d292d3SJohn Baldwin 	}
78726d292d3SJohn Baldwin 	if (resid > 0) {
78826d292d3SJohn Baldwin 		crypto_cursor_copydata(&cc_in, resid, blk);
78926d292d3SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
790b54d1284SJohn Baldwin 			exf->update(ctx, blk, resid);
791b54d1284SJohn Baldwin 			exf->encrypt_last(ctx, blk, blk, resid);
79226d292d3SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
79326d292d3SJohn Baldwin 		} else {
794b54d1284SJohn Baldwin 			exf->decrypt_last(ctx, blk, blk, resid);
795b54d1284SJohn Baldwin 			exf->update(ctx, blk, resid);
796c0341432SJohn Baldwin 		}
79708fca7a5SJohn-Mark Gurney 	}
79808fca7a5SJohn-Mark Gurney 
79908fca7a5SJohn-Mark Gurney 	/* Finalize MAC */
8007051c579SJohn Baldwin 	exf->final(s.tag, ctx);
80108fca7a5SJohn-Mark Gurney 
80208fca7a5SJohn-Mark Gurney 	/* Validate tag */
80320c128daSJohn Baldwin 	error = 0;
804c0341432SJohn Baldwin 	if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
805c0341432SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen,
8067051c579SJohn Baldwin 		    s.tag2);
8077051c579SJohn Baldwin 		r = timingsafe_bcmp(s.tag, s.tag2, swa->sw_mlen);
80820c128daSJohn Baldwin 		if (r != 0) {
80920c128daSJohn Baldwin 			error = EBADMSG;
81020c128daSJohn Baldwin 			goto out;
81120c128daSJohn Baldwin 		}
812c0341432SJohn Baldwin 
81308fca7a5SJohn-Mark Gurney 		/* tag matches, decrypt data */
814b54d1284SJohn Baldwin 		exf->reinit(ctx, crp->crp_iv, ivlen);
8159c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_in, &crp->crp_buf);
8169c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_in, crp->crp_payload_start);
81726d292d3SJohn Baldwin 		for (resid = crp->crp_payload_length; resid > blksz;
81826d292d3SJohn Baldwin 		     resid -= blksz) {
81986be314dSJohn Baldwin 			inblk = crypto_cursor_segment(&cc_in, &len);
82086be314dSJohn Baldwin 			if (len < blksz) {
82126d292d3SJohn Baldwin 				crypto_cursor_copydata(&cc_in, blksz, blk);
82226d292d3SJohn Baldwin 				inblk = blk;
82386be314dSJohn Baldwin 			} else
82426d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_in, blksz);
82586be314dSJohn Baldwin 			outblk = crypto_cursor_segment(&cc_out, &len);
82686be314dSJohn Baldwin 			if (len < blksz)
82726d292d3SJohn Baldwin 				outblk = blk;
828b54d1284SJohn Baldwin 			exf->decrypt(ctx, inblk, outblk);
82926d292d3SJohn Baldwin 			if (outblk == blk)
83026d292d3SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
83126d292d3SJohn Baldwin 			else
83226d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_out, blksz);
83326d292d3SJohn Baldwin 		}
83426d292d3SJohn Baldwin 		if (resid > 0) {
83526d292d3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, resid, blk);
836b54d1284SJohn Baldwin 			exf->decrypt_last(ctx, blk, blk, resid);
83726d292d3SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
83808fca7a5SJohn-Mark Gurney 		}
83908fca7a5SJohn-Mark Gurney 	} else {
84008fca7a5SJohn-Mark Gurney 		/* Inject the authentication data */
8417051c579SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen,
8427051c579SJohn Baldwin 		    s.tag);
84308fca7a5SJohn-Mark Gurney 	}
84408fca7a5SJohn-Mark Gurney 
84520c128daSJohn Baldwin out:
846b54d1284SJohn Baldwin 	explicit_bzero(ctx, exf->ctxsize);
8477051c579SJohn Baldwin 	explicit_bzero(&s, sizeof(s));
84820c128daSJohn Baldwin 	return (error);
84908fca7a5SJohn-Mark Gurney }
85008fca7a5SJohn-Mark Gurney 
851dd2e1352SJohn Baldwin static int
852dc475c9bSJohn Baldwin swcr_chacha20_poly1305(const struct swcr_session *ses, struct cryptop *crp)
853dd2e1352SJohn Baldwin {
854dd2e1352SJohn Baldwin 	const struct crypto_session_params *csp;
8557051c579SJohn Baldwin 	struct {
856dd2e1352SJohn Baldwin 		uint64_t blkbuf[howmany(CHACHA20_NATIVE_BLOCK_LEN, sizeof(uint64_t))];
857dd2e1352SJohn Baldwin 		u_char tag[POLY1305_HASH_LEN];
8587051c579SJohn Baldwin 		u_char tag2[POLY1305_HASH_LEN];
8597051c579SJohn Baldwin 	} s;
8607051c579SJohn Baldwin 	u_char *blk = (u_char *)s.blkbuf;
861dd2e1352SJohn Baldwin 	struct crypto_buffer_cursor cc_in, cc_out;
862dd2e1352SJohn Baldwin 	const u_char *inblk;
863dd2e1352SJohn Baldwin 	u_char *outblk;
864dd2e1352SJohn Baldwin 	uint64_t *blkp;
865b54d1284SJohn Baldwin 	const struct swcr_auth *swa;
866b54d1284SJohn Baldwin 	const struct swcr_encdec *swe;
867d8787d4fSMark Johnston 	const struct enc_xform *exf;
868b54d1284SJohn Baldwin 	void *ctx;
86986be314dSJohn Baldwin 	size_t len;
870dd2e1352SJohn Baldwin 	int blksz, error, r, resid;
871dd2e1352SJohn Baldwin 
872dd2e1352SJohn Baldwin 	swa = &ses->swcr_auth;
873dd2e1352SJohn Baldwin 	swe = &ses->swcr_encdec;
874dd2e1352SJohn Baldwin 	exf = swe->sw_exf;
875dd2e1352SJohn Baldwin 	blksz = exf->native_blocksize;
8767051c579SJohn Baldwin 	KASSERT(blksz <= sizeof(s.blkbuf), ("%s: blocksize mismatch", __func__));
877dd2e1352SJohn Baldwin 
878dd2e1352SJohn Baldwin 	if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0)
879dd2e1352SJohn Baldwin 		return (EINVAL);
880dd2e1352SJohn Baldwin 
881dd2e1352SJohn Baldwin 	csp = crypto_get_params(crp->crp_session);
882dd2e1352SJohn Baldwin 
883b54d1284SJohn Baldwin 	ctx = __builtin_alloca(exf->ctxsize);
884dd2e1352SJohn Baldwin 	if (crp->crp_cipher_key != NULL)
885b54d1284SJohn Baldwin 		exf->setkey(ctx, crp->crp_cipher_key,
886dd2e1352SJohn Baldwin 		    csp->csp_cipher_klen);
887b54d1284SJohn Baldwin 	else
888b54d1284SJohn Baldwin 		memcpy(ctx, swe->sw_ctx, exf->ctxsize);
889b54d1284SJohn Baldwin 	exf->reinit(ctx, crp->crp_iv, csp->csp_ivlen);
890dd2e1352SJohn Baldwin 
891ab91fb6cSJohn Baldwin 	/* Supply MAC with AAD */
892ab91fb6cSJohn Baldwin 	if (crp->crp_aad != NULL)
893b54d1284SJohn Baldwin 		exf->update(ctx, crp->crp_aad, crp->crp_aad_length);
894ab91fb6cSJohn Baldwin 	else
895b54d1284SJohn Baldwin 		crypto_apply(crp, crp->crp_aad_start, crp->crp_aad_length,
896b54d1284SJohn Baldwin 		    exf->update, ctx);
897*04781697SJohn Baldwin 	if (crp->crp_aad_length % POLY1305_BLOCK_LEN != 0) {
898ab91fb6cSJohn Baldwin 		/* padding1 */
899*04781697SJohn Baldwin 		memset(blk, 0, POLY1305_BLOCK_LEN);
900*04781697SJohn Baldwin 		exf->update(ctx, blk, POLY1305_BLOCK_LEN -
901*04781697SJohn Baldwin 		    crp->crp_aad_length % POLY1305_BLOCK_LEN);
902ab91fb6cSJohn Baldwin 	}
903ab91fb6cSJohn Baldwin 
904dd2e1352SJohn Baldwin 	/* Do encryption with MAC */
905dd2e1352SJohn Baldwin 	crypto_cursor_init(&cc_in, &crp->crp_buf);
906dd2e1352SJohn Baldwin 	crypto_cursor_advance(&cc_in, crp->crp_payload_start);
907dd2e1352SJohn Baldwin 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
908dd2e1352SJohn Baldwin 		crypto_cursor_init(&cc_out, &crp->crp_obuf);
909dd2e1352SJohn Baldwin 		crypto_cursor_advance(&cc_out, crp->crp_payload_output_start);
910dd2e1352SJohn Baldwin 	} else
911dd2e1352SJohn Baldwin 		cc_out = cc_in;
912dd2e1352SJohn Baldwin 	for (resid = crp->crp_payload_length; resid >= blksz; resid -= blksz) {
91386be314dSJohn Baldwin 		inblk = crypto_cursor_segment(&cc_in, &len);
91486be314dSJohn Baldwin 		if (len < blksz) {
915dd2e1352SJohn Baldwin 			crypto_cursor_copydata(&cc_in, blksz, blk);
916dd2e1352SJohn Baldwin 			inblk = blk;
91786be314dSJohn Baldwin 		} else
918dd2e1352SJohn Baldwin 			crypto_cursor_advance(&cc_in, blksz);
919dd2e1352SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
92086be314dSJohn Baldwin 			outblk = crypto_cursor_segment(&cc_out, &len);
92186be314dSJohn Baldwin 			if (len < blksz)
922dd2e1352SJohn Baldwin 				outblk = blk;
923b54d1284SJohn Baldwin 			exf->encrypt(ctx, inblk, outblk);
924b54d1284SJohn Baldwin 			exf->update(ctx, outblk, blksz);
925dd2e1352SJohn Baldwin 			if (outblk == blk)
926dd2e1352SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
927dd2e1352SJohn Baldwin 			else
928dd2e1352SJohn Baldwin 				crypto_cursor_advance(&cc_out, blksz);
929dd2e1352SJohn Baldwin 		} else {
930b54d1284SJohn Baldwin 			exf->update(ctx, inblk, blksz);
931dd2e1352SJohn Baldwin 		}
932dd2e1352SJohn Baldwin 	}
933dd2e1352SJohn Baldwin 	if (resid > 0) {
934dd2e1352SJohn Baldwin 		crypto_cursor_copydata(&cc_in, resid, blk);
935dd2e1352SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
936b54d1284SJohn Baldwin 			exf->encrypt_last(ctx, blk, blk, resid);
937dd2e1352SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
938dd2e1352SJohn Baldwin 		}
939b54d1284SJohn Baldwin 		exf->update(ctx, blk, resid);
940*04781697SJohn Baldwin 		if (resid % POLY1305_BLOCK_LEN != 0) {
941dd2e1352SJohn Baldwin 			/* padding2 */
942*04781697SJohn Baldwin 			memset(blk, 0, POLY1305_BLOCK_LEN);
943*04781697SJohn Baldwin 			exf->update(ctx, blk, POLY1305_BLOCK_LEN -
944*04781697SJohn Baldwin 			    resid % POLY1305_BLOCK_LEN);
945dd2e1352SJohn Baldwin 		}
946dd2e1352SJohn Baldwin 	}
947dd2e1352SJohn Baldwin 
948dd2e1352SJohn Baldwin 	/* lengths */
949dd2e1352SJohn Baldwin 	blkp = (uint64_t *)blk;
950dd2e1352SJohn Baldwin 	blkp[0] = htole64(crp->crp_aad_length);
951dd2e1352SJohn Baldwin 	blkp[1] = htole64(crp->crp_payload_length);
952b54d1284SJohn Baldwin 	exf->update(ctx, blk, sizeof(uint64_t) * 2);
953dd2e1352SJohn Baldwin 
954dd2e1352SJohn Baldwin 	/* Finalize MAC */
9557051c579SJohn Baldwin 	exf->final(s.tag, ctx);
956dd2e1352SJohn Baldwin 
957dd2e1352SJohn Baldwin 	/* Validate tag */
958dd2e1352SJohn Baldwin 	error = 0;
959dd2e1352SJohn Baldwin 	if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
9607051c579SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen,
9617051c579SJohn Baldwin 		    s.tag2);
9627051c579SJohn Baldwin 		r = timingsafe_bcmp(s.tag, s.tag2, swa->sw_mlen);
963dd2e1352SJohn Baldwin 		if (r != 0) {
964dd2e1352SJohn Baldwin 			error = EBADMSG;
965dd2e1352SJohn Baldwin 			goto out;
966dd2e1352SJohn Baldwin 		}
967dd2e1352SJohn Baldwin 
968dd2e1352SJohn Baldwin 		/* tag matches, decrypt data */
969dd2e1352SJohn Baldwin 		crypto_cursor_init(&cc_in, &crp->crp_buf);
970dd2e1352SJohn Baldwin 		crypto_cursor_advance(&cc_in, crp->crp_payload_start);
971dd2e1352SJohn Baldwin 		for (resid = crp->crp_payload_length; resid > blksz;
972dd2e1352SJohn Baldwin 		     resid -= blksz) {
97386be314dSJohn Baldwin 			inblk = crypto_cursor_segment(&cc_in, &len);
97486be314dSJohn Baldwin 			if (len < blksz) {
975dd2e1352SJohn Baldwin 				crypto_cursor_copydata(&cc_in, blksz, blk);
976dd2e1352SJohn Baldwin 				inblk = blk;
97786be314dSJohn Baldwin 			} else
978dd2e1352SJohn Baldwin 				crypto_cursor_advance(&cc_in, blksz);
97986be314dSJohn Baldwin 			outblk = crypto_cursor_segment(&cc_out, &len);
98086be314dSJohn Baldwin 			if (len < blksz)
981dd2e1352SJohn Baldwin 				outblk = blk;
982b54d1284SJohn Baldwin 			exf->decrypt(ctx, inblk, outblk);
983dd2e1352SJohn Baldwin 			if (outblk == blk)
984dd2e1352SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
985dd2e1352SJohn Baldwin 			else
986dd2e1352SJohn Baldwin 				crypto_cursor_advance(&cc_out, blksz);
987dd2e1352SJohn Baldwin 		}
988dd2e1352SJohn Baldwin 		if (resid > 0) {
989dd2e1352SJohn Baldwin 			crypto_cursor_copydata(&cc_in, resid, blk);
990b54d1284SJohn Baldwin 			exf->decrypt_last(ctx, blk, blk, resid);
991dd2e1352SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
992dd2e1352SJohn Baldwin 		}
993dd2e1352SJohn Baldwin 	} else {
994dd2e1352SJohn Baldwin 		/* Inject the authentication data */
9957051c579SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen,
9967051c579SJohn Baldwin 		    s.tag);
997dd2e1352SJohn Baldwin 	}
998dd2e1352SJohn Baldwin 
999dd2e1352SJohn Baldwin out:
1000b54d1284SJohn Baldwin 	explicit_bzero(ctx, exf->ctxsize);
10017051c579SJohn Baldwin 	explicit_bzero(&s, sizeof(s));
1002dd2e1352SJohn Baldwin 	return (error);
1003dd2e1352SJohn Baldwin }
1004dd2e1352SJohn Baldwin 
1005091d81d1SSam Leffler /*
1006c0341432SJohn Baldwin  * Apply a cipher and a digest to perform EtA.
1007c0341432SJohn Baldwin  */
1008c0341432SJohn Baldwin static int
1009dc475c9bSJohn Baldwin swcr_eta(const struct swcr_session *ses, struct cryptop *crp)
1010c0341432SJohn Baldwin {
1011c0341432SJohn Baldwin 	int error;
1012c0341432SJohn Baldwin 
1013c0341432SJohn Baldwin 	if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
1014c0341432SJohn Baldwin 		error = swcr_encdec(ses, crp);
1015c0341432SJohn Baldwin 		if (error == 0)
1016c0341432SJohn Baldwin 			error = swcr_authcompute(ses, crp);
1017c0341432SJohn Baldwin 	} else {
1018c0341432SJohn Baldwin 		error = swcr_authcompute(ses, crp);
1019c0341432SJohn Baldwin 		if (error == 0)
1020c0341432SJohn Baldwin 			error = swcr_encdec(ses, crp);
1021c0341432SJohn Baldwin 	}
1022c0341432SJohn Baldwin 	return (error);
1023c0341432SJohn Baldwin }
1024c0341432SJohn Baldwin 
1025c0341432SJohn Baldwin /*
1026091d81d1SSam Leffler  * Apply a compression/decompression algorithm
1027091d81d1SSam Leffler  */
1028091d81d1SSam Leffler static int
1029dc475c9bSJohn Baldwin swcr_compdec(const struct swcr_session *ses, struct cryptop *crp)
1030091d81d1SSam Leffler {
1031d8787d4fSMark Johnston 	const struct comp_algo *cxf;
1032d3d79e96SJohn Baldwin 	uint8_t *data, *out;
1033091d81d1SSam Leffler 	int adj;
1034d3d79e96SJohn Baldwin 	uint32_t result;
1035091d81d1SSam Leffler 
1036c0341432SJohn Baldwin 	cxf = ses->swcr_compdec.sw_cxf;
1037091d81d1SSam Leffler 
1038091d81d1SSam Leffler 	/* We must handle the whole buffer of data in one time
1039091d81d1SSam Leffler 	 * then if there is not all the data in the mbuf, we must
1040091d81d1SSam Leffler 	 * copy in a buffer.
1041091d81d1SSam Leffler 	 */
1042091d81d1SSam Leffler 
1043c0341432SJohn Baldwin 	data = malloc(crp->crp_payload_length, M_CRYPTO_DATA,  M_NOWAIT);
1044091d81d1SSam Leffler 	if (data == NULL)
1045091d81d1SSam Leffler 		return (EINVAL);
1046c0341432SJohn Baldwin 	crypto_copydata(crp, crp->crp_payload_start, crp->crp_payload_length,
1047c0341432SJohn Baldwin 	    data);
1048091d81d1SSam Leffler 
1049c0341432SJohn Baldwin 	if (CRYPTO_OP_IS_COMPRESS(crp->crp_op))
1050c0341432SJohn Baldwin 		result = cxf->compress(data, crp->crp_payload_length, &out);
1051091d81d1SSam Leffler 	else
1052c0341432SJohn Baldwin 		result = cxf->decompress(data, crp->crp_payload_length, &out);
1053091d81d1SSam Leffler 
10541ede983cSDag-Erling Smørgrav 	free(data, M_CRYPTO_DATA);
1055091d81d1SSam Leffler 	if (result == 0)
1056c0341432SJohn Baldwin 		return (EINVAL);
1057c0341432SJohn Baldwin 	crp->crp_olen = result;
1058c0341432SJohn Baldwin 
1059c0341432SJohn Baldwin 	/* Check the compressed size when doing compression */
1060c0341432SJohn Baldwin 	if (CRYPTO_OP_IS_COMPRESS(crp->crp_op)) {
1061c0341432SJohn Baldwin 		if (result >= crp->crp_payload_length) {
1062c0341432SJohn Baldwin 			/* Compression was useless, we lost time */
1063c0341432SJohn Baldwin 			free(out, M_CRYPTO_DATA);
1064c0341432SJohn Baldwin 			return (0);
1065c0341432SJohn Baldwin 		}
1066c0341432SJohn Baldwin 	}
1067091d81d1SSam Leffler 
1068091d81d1SSam Leffler 	/* Copy back the (de)compressed data. m_copyback is
1069091d81d1SSam Leffler 	 * extending the mbuf as necessary.
1070091d81d1SSam Leffler 	 */
1071c0341432SJohn Baldwin 	crypto_copyback(crp, crp->crp_payload_start, result, out);
1072c0341432SJohn Baldwin 	if (result < crp->crp_payload_length) {
10739c0e3d3aSJohn Baldwin 		switch (crp->crp_buf.cb_type) {
1074c0341432SJohn Baldwin 		case CRYPTO_BUF_MBUF:
1075883a0196SJohn Baldwin 		case CRYPTO_BUF_SINGLE_MBUF:
1076c0341432SJohn Baldwin 			adj = result - crp->crp_payload_length;
10779c0e3d3aSJohn Baldwin 			m_adj(crp->crp_buf.cb_mbuf, adj);
1078c0341432SJohn Baldwin 			break;
1079c0341432SJohn Baldwin 		case CRYPTO_BUF_UIO: {
10809c0e3d3aSJohn Baldwin 			struct uio *uio = crp->crp_buf.cb_uio;
1081091d81d1SSam Leffler 			int ind;
1082091d81d1SSam Leffler 
1083c0341432SJohn Baldwin 			adj = crp->crp_payload_length - result;
1084091d81d1SSam Leffler 			ind = uio->uio_iovcnt - 1;
1085091d81d1SSam Leffler 
1086091d81d1SSam Leffler 			while (adj > 0 && ind >= 0) {
1087091d81d1SSam Leffler 				if (adj < uio->uio_iov[ind].iov_len) {
1088091d81d1SSam Leffler 					uio->uio_iov[ind].iov_len -= adj;
1089091d81d1SSam Leffler 					break;
1090091d81d1SSam Leffler 				}
1091091d81d1SSam Leffler 
1092091d81d1SSam Leffler 				adj -= uio->uio_iov[ind].iov_len;
1093091d81d1SSam Leffler 				uio->uio_iov[ind].iov_len = 0;
1094091d81d1SSam Leffler 				ind--;
1095091d81d1SSam Leffler 				uio->uio_iovcnt--;
1096091d81d1SSam Leffler 			}
1097091d81d1SSam Leffler 			}
1098c0341432SJohn Baldwin 			break;
1099e6f6d0c9SAlan Somers 		case CRYPTO_BUF_VMPAGE:
1100e6f6d0c9SAlan Somers 			adj = crp->crp_payload_length - result;
1101e6f6d0c9SAlan Somers 			crp->crp_buf.cb_vm_page_len -= adj;
1102e6f6d0c9SAlan Somers 			break;
11039c0e3d3aSJohn Baldwin 		default:
11049c0e3d3aSJohn Baldwin 			break;
1105c0341432SJohn Baldwin 		}
1106091d81d1SSam Leffler 	}
11071ede983cSDag-Erling Smørgrav 	free(out, M_CRYPTO_DATA);
1108091d81d1SSam Leffler 	return 0;
1109091d81d1SSam Leffler }
1110091d81d1SSam Leffler 
1111091d81d1SSam Leffler static int
11123e947048SJohn Baldwin swcr_setup_cipher(struct swcr_session *ses,
1113c0341432SJohn Baldwin     const struct crypto_session_params *csp)
1114091d81d1SSam Leffler {
1115c0341432SJohn Baldwin 	struct swcr_encdec *swe;
1116d8787d4fSMark Johnston 	const struct enc_xform *txf;
1117f6c4bc3bSPawel Jakub Dawidek 	int error;
1118091d81d1SSam Leffler 
1119c0341432SJohn Baldwin 	swe = &ses->swcr_encdec;
1120c0341432SJohn Baldwin 	txf = crypto_cipher(csp);
1121b54d1284SJohn Baldwin 	if (csp->csp_cipher_key != NULL) {
11223e947048SJohn Baldwin 		if (txf->ctxsize != 0) {
1123f313909aSJohn Baldwin 			swe->sw_ctx = malloc(txf->ctxsize, M_CRYPTO_DATA,
11243e947048SJohn Baldwin 			    M_NOWAIT);
1125f313909aSJohn Baldwin 			if (swe->sw_ctx == NULL)
11263e947048SJohn Baldwin 				return (ENOMEM);
11273e947048SJohn Baldwin 		}
1128f313909aSJohn Baldwin 		error = txf->setkey(swe->sw_ctx,
1129c0341432SJohn Baldwin 		    csp->csp_cipher_key, csp->csp_cipher_klen);
1130c0341432SJohn Baldwin 		if (error)
1131c0341432SJohn Baldwin 			return (error);
1132091d81d1SSam Leffler 	}
1133c0341432SJohn Baldwin 	swe->sw_exf = txf;
1134c0341432SJohn Baldwin 	return (0);
1135f6c4bc3bSPawel Jakub Dawidek }
1136091d81d1SSam Leffler 
1137c0341432SJohn Baldwin static int
1138c0341432SJohn Baldwin swcr_setup_auth(struct swcr_session *ses,
1139c0341432SJohn Baldwin     const struct crypto_session_params *csp)
1140c0341432SJohn Baldwin {
1141c0341432SJohn Baldwin 	struct swcr_auth *swa;
1142d8787d4fSMark Johnston 	const struct auth_hash *axf;
1143c0341432SJohn Baldwin 
1144c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
1145c0341432SJohn Baldwin 
1146c0341432SJohn Baldwin 	axf = crypto_auth_hash(csp);
1147c0341432SJohn Baldwin 	swa->sw_axf = axf;
1148c0341432SJohn Baldwin 	if (csp->csp_auth_mlen < 0 || csp->csp_auth_mlen > axf->hashsize)
1149c0341432SJohn Baldwin 		return (EINVAL);
1150c0341432SJohn Baldwin 	if (csp->csp_auth_mlen == 0)
1151c0341432SJohn Baldwin 		swa->sw_mlen = axf->hashsize;
1152c0341432SJohn Baldwin 	else
1153c0341432SJohn Baldwin 		swa->sw_mlen = csp->csp_auth_mlen;
11546113a08bSJohn Baldwin 	if (csp->csp_auth_klen == 0 || csp->csp_auth_key != NULL) {
11556113a08bSJohn Baldwin 		swa->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
11566113a08bSJohn Baldwin 		    M_NOWAIT);
1157c0341432SJohn Baldwin 		if (swa->sw_ictx == NULL)
1158c0341432SJohn Baldwin 			return (ENOBUFS);
11596113a08bSJohn Baldwin 	}
1160c0341432SJohn Baldwin 
1161c0341432SJohn Baldwin 	switch (csp->csp_auth_alg) {
1162091d81d1SSam Leffler 	case CRYPTO_SHA1_HMAC:
1163c97f39ceSConrad Meyer 	case CRYPTO_SHA2_224_HMAC:
1164f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_256_HMAC:
1165f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_384_HMAC:
1166f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_512_HMAC:
1167091d81d1SSam Leffler 	case CRYPTO_RIPEMD160_HMAC:
11686113a08bSJohn Baldwin 		swa->sw_hmac = true;
11696113a08bSJohn Baldwin 		if (csp->csp_auth_key != NULL) {
11703a0b6a93SJohn Baldwin 			swa->sw_octx = malloc(axf->ctxsize, M_CRYPTO_DATA,
1171091d81d1SSam Leffler 			    M_NOWAIT);
1172c0341432SJohn Baldwin 			if (swa->sw_octx == NULL)
1173c0341432SJohn Baldwin 				return (ENOBUFS);
11746113a08bSJohn Baldwin 			hmac_init_ipad(axf, csp->csp_auth_key,
11756113a08bSJohn Baldwin 			    csp->csp_auth_klen, swa->sw_ictx);
11766113a08bSJohn Baldwin 			hmac_init_opad(axf, csp->csp_auth_key,
11776113a08bSJohn Baldwin 			    csp->csp_auth_klen, swa->sw_octx);
1178091d81d1SSam Leffler 		}
1179091d81d1SSam Leffler 		break;
1180091d81d1SSam Leffler 	case CRYPTO_SHA1:
1181c4729f6eSConrad Meyer 	case CRYPTO_SHA2_224:
1182c4729f6eSConrad Meyer 	case CRYPTO_SHA2_256:
1183c4729f6eSConrad Meyer 	case CRYPTO_SHA2_384:
1184c4729f6eSConrad Meyer 	case CRYPTO_SHA2_512:
1185aa268175SJohn Baldwin 	case CRYPTO_NULL_HMAC:
1186c0341432SJohn Baldwin 		axf->Init(swa->sw_ictx);
1187c0341432SJohn Baldwin 		break;
1188c0341432SJohn Baldwin 	case CRYPTO_AES_NIST_GMAC:
11896113a08bSJohn Baldwin 	case CRYPTO_AES_CCM_CBC_MAC:
11906113a08bSJohn Baldwin 	case CRYPTO_POLY1305:
11916113a08bSJohn Baldwin 		if (csp->csp_auth_key != NULL) {
1192c0341432SJohn Baldwin 			axf->Init(swa->sw_ictx);
1193c0341432SJohn Baldwin 			axf->Setkey(swa->sw_ictx, csp->csp_auth_key,
1194c0341432SJohn Baldwin 			    csp->csp_auth_klen);
11956113a08bSJohn Baldwin 		}
1196c0341432SJohn Baldwin 		break;
1197c0341432SJohn Baldwin 	case CRYPTO_BLAKE2B:
1198c0341432SJohn Baldwin 	case CRYPTO_BLAKE2S:
1199c0341432SJohn Baldwin 		/*
1200c0341432SJohn Baldwin 		 * Blake2b and Blake2s support an optional key but do
1201c0341432SJohn Baldwin 		 * not require one.
1202c0341432SJohn Baldwin 		 */
12036113a08bSJohn Baldwin 		if (csp->csp_auth_klen == 0)
12046113a08bSJohn Baldwin 			axf->Init(swa->sw_ictx);
12056113a08bSJohn Baldwin 		else if (csp->csp_auth_key != NULL)
1206c0341432SJohn Baldwin 			axf->Setkey(swa->sw_ictx, csp->csp_auth_key,
1207c0341432SJohn Baldwin 			    csp->csp_auth_klen);
12086113a08bSJohn Baldwin 		break;
12096113a08bSJohn Baldwin 	}
12106113a08bSJohn Baldwin 
12116113a08bSJohn Baldwin 	if (csp->csp_mode == CSP_MODE_DIGEST) {
12126113a08bSJohn Baldwin 		switch (csp->csp_auth_alg) {
12136113a08bSJohn Baldwin 		case CRYPTO_AES_NIST_GMAC:
12146113a08bSJohn Baldwin 			ses->swcr_process = swcr_gmac;
1215c0341432SJohn Baldwin 			break;
1216c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_CBC_MAC:
1217c0341432SJohn Baldwin 			ses->swcr_process = swcr_ccm_cbc_mac;
1218c0341432SJohn Baldwin 			break;
12196113a08bSJohn Baldwin 		default:
12206113a08bSJohn Baldwin 			ses->swcr_process = swcr_authcompute;
12216113a08bSJohn Baldwin 		}
1222091d81d1SSam Leffler 	}
1223091d81d1SSam Leffler 
1224c0341432SJohn Baldwin 	return (0);
1225c0341432SJohn Baldwin }
122608fca7a5SJohn-Mark Gurney 
1227c0341432SJohn Baldwin static int
1228ab91fb6cSJohn Baldwin swcr_setup_aead(struct swcr_session *ses,
1229c0341432SJohn Baldwin     const struct crypto_session_params *csp)
1230c0341432SJohn Baldwin {
1231c0341432SJohn Baldwin 	struct swcr_auth *swa;
1232ab91fb6cSJohn Baldwin 	int error;
1233c0341432SJohn Baldwin 
1234ab91fb6cSJohn Baldwin 	error = swcr_setup_cipher(ses, csp);
1235ab91fb6cSJohn Baldwin 	if (error)
1236ab91fb6cSJohn Baldwin 		return (error);
1237ab91fb6cSJohn Baldwin 
1238c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
1239c0341432SJohn Baldwin 	if (csp->csp_auth_mlen == 0)
1240ab91fb6cSJohn Baldwin 		swa->sw_mlen = ses->swcr_encdec.sw_exf->macsize;
1241c0341432SJohn Baldwin 	else
1242c0341432SJohn Baldwin 		swa->sw_mlen = csp->csp_auth_mlen;
1243ab91fb6cSJohn Baldwin 	return (0);
1244dd2e1352SJohn Baldwin }
1245dd2e1352SJohn Baldwin 
1246c0341432SJohn Baldwin static bool
1247c0341432SJohn Baldwin swcr_auth_supported(const struct crypto_session_params *csp)
1248109919c6SBenno Rice {
1249d8787d4fSMark Johnston 	const struct auth_hash *axf;
1250091d81d1SSam Leffler 
1251c0341432SJohn Baldwin 	axf = crypto_auth_hash(csp);
1252c0341432SJohn Baldwin 	if (axf == NULL)
1253c0341432SJohn Baldwin 		return (false);
1254c0341432SJohn Baldwin 	switch (csp->csp_auth_alg) {
1255091d81d1SSam Leffler 	case CRYPTO_SHA1_HMAC:
1256c97f39ceSConrad Meyer 	case CRYPTO_SHA2_224_HMAC:
1257f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_256_HMAC:
1258f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_384_HMAC:
1259f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_512_HMAC:
1260091d81d1SSam Leffler 	case CRYPTO_NULL_HMAC:
1261c0341432SJohn Baldwin 	case CRYPTO_RIPEMD160_HMAC:
1262091d81d1SSam Leffler 		break;
1263c0341432SJohn Baldwin 	case CRYPTO_AES_NIST_GMAC:
1264c0341432SJohn Baldwin 		switch (csp->csp_auth_klen * 8) {
1265c0341432SJohn Baldwin 		case 128:
1266c0341432SJohn Baldwin 		case 192:
1267c0341432SJohn Baldwin 		case 256:
1268c0341432SJohn Baldwin 			break;
1269c0341432SJohn Baldwin 		default:
1270c0341432SJohn Baldwin 			return (false);
1271c0341432SJohn Baldwin 		}
1272c0341432SJohn Baldwin 		if (csp->csp_auth_key == NULL)
1273c0341432SJohn Baldwin 			return (false);
1274c0341432SJohn Baldwin 		if (csp->csp_ivlen != AES_GCM_IV_LEN)
1275c0341432SJohn Baldwin 			return (false);
1276c0341432SJohn Baldwin 		break;
127725b7033bSConrad Meyer 	case CRYPTO_POLY1305:
1278c0341432SJohn Baldwin 		if (csp->csp_auth_klen != POLY1305_KEY_LEN)
1279c0341432SJohn Baldwin 			return (false);
1280c0341432SJohn Baldwin 		break;
1281c0341432SJohn Baldwin 	case CRYPTO_AES_CCM_CBC_MAC:
1282c0341432SJohn Baldwin 		switch (csp->csp_auth_klen * 8) {
1283c0341432SJohn Baldwin 		case 128:
1284c0341432SJohn Baldwin 		case 192:
1285c0341432SJohn Baldwin 		case 256:
1286c0341432SJohn Baldwin 			break;
1287c0341432SJohn Baldwin 		default:
1288c0341432SJohn Baldwin 			return (false);
1289c0341432SJohn Baldwin 		}
1290c0341432SJohn Baldwin 		if (csp->csp_auth_key == NULL)
1291c0341432SJohn Baldwin 			return (false);
1292c0341432SJohn Baldwin 		break;
1293c0341432SJohn Baldwin 	}
1294c0341432SJohn Baldwin 	return (true);
1295c0341432SJohn Baldwin }
1296091d81d1SSam Leffler 
1297c0341432SJohn Baldwin static bool
1298c0341432SJohn Baldwin swcr_cipher_supported(const struct crypto_session_params *csp)
1299c0341432SJohn Baldwin {
1300d8787d4fSMark Johnston 	const struct enc_xform *txf;
1301c0341432SJohn Baldwin 
1302c0341432SJohn Baldwin 	txf = crypto_cipher(csp);
1303c0341432SJohn Baldwin 	if (txf == NULL)
1304c0341432SJohn Baldwin 		return (false);
1305c0341432SJohn Baldwin 	if (csp->csp_cipher_alg != CRYPTO_NULL_CBC &&
1306c0341432SJohn Baldwin 	    txf->ivsize != csp->csp_ivlen)
1307c0341432SJohn Baldwin 		return (false);
1308c0341432SJohn Baldwin 	return (true);
1309c0341432SJohn Baldwin }
1310c0341432SJohn Baldwin 
13116038018aSMarcin Wojtas #define SUPPORTED_SES (CSP_F_SEPARATE_OUTPUT | CSP_F_SEPARATE_AAD | CSP_F_ESN)
13126038018aSMarcin Wojtas 
1313c0341432SJohn Baldwin static int
1314c0341432SJohn Baldwin swcr_probesession(device_t dev, const struct crypto_session_params *csp)
1315c0341432SJohn Baldwin {
13166038018aSMarcin Wojtas 	if ((csp->csp_flags & ~(SUPPORTED_SES)) != 0)
1317c0341432SJohn Baldwin 		return (EINVAL);
1318c0341432SJohn Baldwin 	switch (csp->csp_mode) {
1319c0341432SJohn Baldwin 	case CSP_MODE_COMPRESS:
1320c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1321c0341432SJohn Baldwin 		case CRYPTO_DEFLATE_COMP:
1322c0341432SJohn Baldwin 			break;
1323c0341432SJohn Baldwin 		default:
1324c0341432SJohn Baldwin 			return (EINVAL);
13255fbc5b5aSConrad Meyer 		}
1326091d81d1SSam Leffler 		break;
1327c0341432SJohn Baldwin 	case CSP_MODE_CIPHER:
1328c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1329c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1330c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1331dd2e1352SJohn Baldwin 		case CRYPTO_CHACHA20_POLY1305:
1332c0341432SJohn Baldwin 			return (EINVAL);
1333c0341432SJohn Baldwin 		default:
1334c0341432SJohn Baldwin 			if (!swcr_cipher_supported(csp))
1335c0341432SJohn Baldwin 				return (EINVAL);
1336091d81d1SSam Leffler 			break;
1337091d81d1SSam Leffler 		}
1338c0341432SJohn Baldwin 		break;
1339c0341432SJohn Baldwin 	case CSP_MODE_DIGEST:
1340c0341432SJohn Baldwin 		if (!swcr_auth_supported(csp))
1341c0341432SJohn Baldwin 			return (EINVAL);
1342c0341432SJohn Baldwin 		break;
1343c0341432SJohn Baldwin 	case CSP_MODE_AEAD:
1344c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1345c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1346c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1347c172a407SJohn Baldwin 			switch (csp->csp_cipher_klen * 8) {
1348c172a407SJohn Baldwin 			case 128:
1349c172a407SJohn Baldwin 			case 192:
1350c172a407SJohn Baldwin 			case 256:
1351c172a407SJohn Baldwin 				break;
1352c172a407SJohn Baldwin 			default:
1353c172a407SJohn Baldwin 				return (EINVAL);
1354c172a407SJohn Baldwin 			}
1355c172a407SJohn Baldwin 			break;
1356dd2e1352SJohn Baldwin 		case CRYPTO_CHACHA20_POLY1305:
1357c0341432SJohn Baldwin 			break;
1358c0341432SJohn Baldwin 		default:
1359c0341432SJohn Baldwin 			return (EINVAL);
1360c0341432SJohn Baldwin 		}
1361c0341432SJohn Baldwin 		break;
1362c0341432SJohn Baldwin 	case CSP_MODE_ETA:
1363c0341432SJohn Baldwin 		/* AEAD algorithms cannot be used for EtA. */
1364c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1365c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1366c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1367dd2e1352SJohn Baldwin 		case CRYPTO_CHACHA20_POLY1305:
1368c0341432SJohn Baldwin 			return (EINVAL);
1369c0341432SJohn Baldwin 		}
1370c0341432SJohn Baldwin 		switch (csp->csp_auth_alg) {
1371c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GMAC:
1372c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_CBC_MAC:
1373c0341432SJohn Baldwin 			return (EINVAL);
1374c0341432SJohn Baldwin 		}
1375c0341432SJohn Baldwin 
1376c0341432SJohn Baldwin 		if (!swcr_cipher_supported(csp) ||
1377c0341432SJohn Baldwin 		    !swcr_auth_supported(csp))
1378c0341432SJohn Baldwin 			return (EINVAL);
1379c0341432SJohn Baldwin 		break;
1380c0341432SJohn Baldwin 	default:
1381c0341432SJohn Baldwin 		return (EINVAL);
1382c0341432SJohn Baldwin 	}
1383c0341432SJohn Baldwin 
1384c0341432SJohn Baldwin 	return (CRYPTODEV_PROBE_SOFTWARE);
1385c0341432SJohn Baldwin }
1386c0341432SJohn Baldwin 
1387c0341432SJohn Baldwin /*
1388c0341432SJohn Baldwin  * Generate a new software session.
1389c0341432SJohn Baldwin  */
1390c0341432SJohn Baldwin static int
1391c0341432SJohn Baldwin swcr_newsession(device_t dev, crypto_session_t cses,
1392c0341432SJohn Baldwin     const struct crypto_session_params *csp)
1393c0341432SJohn Baldwin {
1394c0341432SJohn Baldwin 	struct swcr_session *ses;
1395d8787d4fSMark Johnston 	const struct comp_algo *cxf;
1396c0341432SJohn Baldwin 	int error;
1397c0341432SJohn Baldwin 
1398c0341432SJohn Baldwin 	ses = crypto_get_driver_session(cses);
1399c0341432SJohn Baldwin 
1400c0341432SJohn Baldwin 	error = 0;
1401c0341432SJohn Baldwin 	switch (csp->csp_mode) {
1402c0341432SJohn Baldwin 	case CSP_MODE_COMPRESS:
1403c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1404c0341432SJohn Baldwin 		case CRYPTO_DEFLATE_COMP:
1405c0341432SJohn Baldwin 			cxf = &comp_algo_deflate;
1406c0341432SJohn Baldwin 			break;
1407c0341432SJohn Baldwin #ifdef INVARIANTS
1408c0341432SJohn Baldwin 		default:
1409c0341432SJohn Baldwin 			panic("bad compression algo");
1410c0341432SJohn Baldwin #endif
1411c0341432SJohn Baldwin 		}
1412c0341432SJohn Baldwin 		ses->swcr_compdec.sw_cxf = cxf;
1413c0341432SJohn Baldwin 		ses->swcr_process = swcr_compdec;
1414c0341432SJohn Baldwin 		break;
1415c0341432SJohn Baldwin 	case CSP_MODE_CIPHER:
1416c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1417c0341432SJohn Baldwin 		case CRYPTO_NULL_CBC:
1418c0341432SJohn Baldwin 			ses->swcr_process = swcr_null;
1419c0341432SJohn Baldwin 			break;
1420c0341432SJohn Baldwin #ifdef INVARIANTS
1421c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1422c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1423dd2e1352SJohn Baldwin 		case CRYPTO_CHACHA20_POLY1305:
1424c0341432SJohn Baldwin 			panic("bad cipher algo");
1425c0341432SJohn Baldwin #endif
1426c0341432SJohn Baldwin 		default:
14273e947048SJohn Baldwin 			error = swcr_setup_cipher(ses, csp);
1428c0341432SJohn Baldwin 			if (error == 0)
1429c0341432SJohn Baldwin 				ses->swcr_process = swcr_encdec;
1430c0341432SJohn Baldwin 		}
1431c0341432SJohn Baldwin 		break;
1432c0341432SJohn Baldwin 	case CSP_MODE_DIGEST:
1433c0341432SJohn Baldwin 		error = swcr_setup_auth(ses, csp);
1434c0341432SJohn Baldwin 		break;
1435c0341432SJohn Baldwin 	case CSP_MODE_AEAD:
1436c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1437c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1438ab91fb6cSJohn Baldwin 			error = swcr_setup_aead(ses, csp);
1439c0341432SJohn Baldwin 			if (error == 0)
1440c0341432SJohn Baldwin 				ses->swcr_process = swcr_gcm;
1441c0341432SJohn Baldwin 			break;
1442c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1443ab91fb6cSJohn Baldwin 			error = swcr_setup_aead(ses, csp);
1444c0341432SJohn Baldwin 			if (error == 0)
1445c0341432SJohn Baldwin 				ses->swcr_process = swcr_ccm;
1446c0341432SJohn Baldwin 			break;
1447dd2e1352SJohn Baldwin 		case CRYPTO_CHACHA20_POLY1305:
1448ab91fb6cSJohn Baldwin 			error = swcr_setup_aead(ses, csp);
1449dd2e1352SJohn Baldwin 			if (error == 0)
1450dd2e1352SJohn Baldwin 				ses->swcr_process = swcr_chacha20_poly1305;
1451dd2e1352SJohn Baldwin 			break;
1452c0341432SJohn Baldwin #ifdef INVARIANTS
1453c0341432SJohn Baldwin 		default:
1454c0341432SJohn Baldwin 			panic("bad aead algo");
1455c0341432SJohn Baldwin #endif
1456c0341432SJohn Baldwin 		}
1457c0341432SJohn Baldwin 		break;
1458c0341432SJohn Baldwin 	case CSP_MODE_ETA:
1459c0341432SJohn Baldwin #ifdef INVARIANTS
1460c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1461c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1462c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1463dd2e1352SJohn Baldwin 		case CRYPTO_CHACHA20_POLY1305:
1464c0341432SJohn Baldwin 			panic("bad eta cipher algo");
1465c0341432SJohn Baldwin 		}
1466c0341432SJohn Baldwin 		switch (csp->csp_auth_alg) {
1467c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GMAC:
1468c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_CBC_MAC:
1469c0341432SJohn Baldwin 			panic("bad eta auth algo");
1470c0341432SJohn Baldwin 		}
1471c0341432SJohn Baldwin #endif
1472c0341432SJohn Baldwin 
1473c0341432SJohn Baldwin 		error = swcr_setup_auth(ses, csp);
1474c0341432SJohn Baldwin 		if (error)
1475c0341432SJohn Baldwin 			break;
1476c0341432SJohn Baldwin 		if (csp->csp_cipher_alg == CRYPTO_NULL_CBC) {
1477c0341432SJohn Baldwin 			/* Effectively degrade to digest mode. */
1478c0341432SJohn Baldwin 			ses->swcr_process = swcr_authcompute;
1479c0341432SJohn Baldwin 			break;
1480c0341432SJohn Baldwin 		}
1481c0341432SJohn Baldwin 
14823e947048SJohn Baldwin 		error = swcr_setup_cipher(ses, csp);
1483c0341432SJohn Baldwin 		if (error == 0)
1484c0341432SJohn Baldwin 			ses->swcr_process = swcr_eta;
1485c0341432SJohn Baldwin 		break;
1486c0341432SJohn Baldwin 	default:
1487c0341432SJohn Baldwin 		error = EINVAL;
1488c0341432SJohn Baldwin 	}
1489c0341432SJohn Baldwin 
1490c0341432SJohn Baldwin 	if (error)
1491c0341432SJohn Baldwin 		swcr_freesession(dev, cses);
1492c0341432SJohn Baldwin 	return (error);
1493c0341432SJohn Baldwin }
1494c0341432SJohn Baldwin 
1495c0341432SJohn Baldwin static void
1496c0341432SJohn Baldwin swcr_freesession(device_t dev, crypto_session_t cses)
1497c0341432SJohn Baldwin {
1498c0341432SJohn Baldwin 	struct swcr_session *ses;
1499c0341432SJohn Baldwin 
1500c0341432SJohn Baldwin 	ses = crypto_get_driver_session(cses);
1501c0341432SJohn Baldwin 
1502f313909aSJohn Baldwin 	zfree(ses->swcr_encdec.sw_ctx, M_CRYPTO_DATA);
15034a711b8dSJohn Baldwin 	zfree(ses->swcr_auth.sw_ictx, M_CRYPTO_DATA);
15044a711b8dSJohn Baldwin 	zfree(ses->swcr_auth.sw_octx, M_CRYPTO_DATA);
1505091d81d1SSam Leffler }
1506091d81d1SSam Leffler 
1507091d81d1SSam Leffler /*
1508091d81d1SSam Leffler  * Process a software request.
1509091d81d1SSam Leffler  */
1510091d81d1SSam Leffler static int
15116810ad6fSSam Leffler swcr_process(device_t dev, struct cryptop *crp, int hint)
1512091d81d1SSam Leffler {
1513c0341432SJohn Baldwin 	struct swcr_session *ses;
1514091d81d1SSam Leffler 
15151b0909d5SConrad Meyer 	ses = crypto_get_driver_session(crp->crp_session);
1516091d81d1SSam Leffler 
1517c0341432SJohn Baldwin 	crp->crp_etype = ses->swcr_process(ses, crp);
1518091d81d1SSam Leffler 
1519091d81d1SSam Leffler 	crypto_done(crp);
1520c0341432SJohn Baldwin 	return (0);
1521091d81d1SSam Leffler }
1522091d81d1SSam Leffler 
1523091d81d1SSam Leffler static void
15243f147ab2SWarner Losh swcr_identify(driver_t *drv, device_t parent)
1525091d81d1SSam Leffler {
15266810ad6fSSam Leffler 	/* NB: order 10 is so we get attached after h/w devices */
15276810ad6fSSam Leffler 	if (device_find_child(parent, "cryptosoft", -1) == NULL &&
152886c585d9SMarius Strobl 	    BUS_ADD_CHILD(parent, 10, "cryptosoft", 0) == 0)
15296810ad6fSSam Leffler 		panic("cryptosoft: could not attach");
15306810ad6fSSam Leffler }
1531f6c4bc3bSPawel Jakub Dawidek 
15326810ad6fSSam Leffler static int
15336810ad6fSSam Leffler swcr_probe(device_t dev)
15346810ad6fSSam Leffler {
15356810ad6fSSam Leffler 	device_set_desc(dev, "software crypto");
15364fc60fa9SMark Johnston 	device_quiet(dev);
153786c585d9SMarius Strobl 	return (BUS_PROBE_NOWILDCARD);
15386810ad6fSSam Leffler }
1539f6c4bc3bSPawel Jakub Dawidek 
15406810ad6fSSam Leffler static int
15416810ad6fSSam Leffler swcr_attach(device_t dev)
15426810ad6fSSam Leffler {
15436810ad6fSSam Leffler 
15449ebbebe4SConrad Meyer 	swcr_id = crypto_get_driverid(dev, sizeof(struct swcr_session),
15456810ad6fSSam Leffler 			CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC);
15466810ad6fSSam Leffler 	if (swcr_id < 0) {
15476810ad6fSSam Leffler 		device_printf(dev, "cannot initialize!");
1548c0341432SJohn Baldwin 		return (ENXIO);
15496810ad6fSSam Leffler 	}
15506810ad6fSSam Leffler 
1551c0341432SJohn Baldwin 	return (0);
1552091d81d1SSam Leffler }
15534b465da2SPawel Jakub Dawidek 
15543f147ab2SWarner Losh static int
15556810ad6fSSam Leffler swcr_detach(device_t dev)
15564b465da2SPawel Jakub Dawidek {
15576810ad6fSSam Leffler 	crypto_unregister_all(swcr_id);
15583f147ab2SWarner Losh 	return 0;
15594b465da2SPawel Jakub Dawidek }
15606810ad6fSSam Leffler 
15616810ad6fSSam Leffler static device_method_t swcr_methods[] = {
15626810ad6fSSam Leffler 	DEVMETHOD(device_identify,	swcr_identify),
15636810ad6fSSam Leffler 	DEVMETHOD(device_probe,		swcr_probe),
15646810ad6fSSam Leffler 	DEVMETHOD(device_attach,	swcr_attach),
15656810ad6fSSam Leffler 	DEVMETHOD(device_detach,	swcr_detach),
15666810ad6fSSam Leffler 
1567c0341432SJohn Baldwin 	DEVMETHOD(cryptodev_probesession, swcr_probesession),
15686810ad6fSSam Leffler 	DEVMETHOD(cryptodev_newsession,	swcr_newsession),
15696810ad6fSSam Leffler 	DEVMETHOD(cryptodev_freesession,swcr_freesession),
15706810ad6fSSam Leffler 	DEVMETHOD(cryptodev_process,	swcr_process),
15716810ad6fSSam Leffler 
15726810ad6fSSam Leffler 	{0, 0},
15736810ad6fSSam Leffler };
15746810ad6fSSam Leffler 
15756810ad6fSSam Leffler static driver_t swcr_driver = {
15766810ad6fSSam Leffler 	"cryptosoft",
15776810ad6fSSam Leffler 	swcr_methods,
15786810ad6fSSam Leffler 	0,		/* NB: no softc */
15796810ad6fSSam Leffler };
15806810ad6fSSam Leffler static devclass_t swcr_devclass;
15816810ad6fSSam Leffler 
15826810ad6fSSam Leffler /*
15836810ad6fSSam Leffler  * NB: We explicitly reference the crypto module so we
15846810ad6fSSam Leffler  * get the necessary ordering when built as a loadable
15856810ad6fSSam Leffler  * module.  This is required because we bundle the crypto
15866810ad6fSSam Leffler  * module code together with the cryptosoft driver (otherwise
15876810ad6fSSam Leffler  * normal module dependencies would handle things).
15886810ad6fSSam Leffler  */
15896810ad6fSSam Leffler extern int crypto_modevent(struct module *, int, void *);
15906810ad6fSSam Leffler /* XXX where to attach */
15916810ad6fSSam Leffler DRIVER_MODULE(cryptosoft, nexus, swcr_driver, swcr_devclass, crypto_modevent,0);
15926810ad6fSSam Leffler MODULE_VERSION(cryptosoft, 1);
15936810ad6fSSam Leffler MODULE_DEPEND(cryptosoft, crypto, 1, 1, 1);
1594