xref: /freebsd/sys/opencrypto/cryptosoft.c (revision a221a8f4a0deb6619448e9d2df696625d454ab3d)
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;
108cfb7b942SJohn Baldwin 	size_t inlen, outlen, todo;
10969e533c3SJohn Baldwin 	int blksz, 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 
12769e533c3SJohn Baldwin 		blksz = exf->blocksize;
128723d8764SJohn Baldwin 	} else
12969e533c3SJohn Baldwin 		blksz = 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 
157c0341432SJohn Baldwin 	encrypting = CRYPTO_OP_IS_ENCRYPT(crp->crp_op);
158091d81d1SSam Leffler 
159091d81d1SSam Leffler 	/*
1609c0e3d3aSJohn Baldwin 	 * Loop through encrypting blocks.  'inlen' is the remaining
1619c0e3d3aSJohn Baldwin 	 * length of the current segment in the input buffer.
1629c0e3d3aSJohn Baldwin 	 * 'outlen' is the remaining length of current segment in the
1639c0e3d3aSJohn Baldwin 	 * output buffer.
164091d81d1SSam Leffler 	 */
16569e533c3SJohn Baldwin 	for (resid = crp->crp_payload_length; resid >= blksz; resid -= todo) {
1669c0e3d3aSJohn Baldwin 		/*
1679c0e3d3aSJohn Baldwin 		 * If the current block is not contained within the
1689c0e3d3aSJohn Baldwin 		 * current input/output segment, use 'blk' as a local
1699c0e3d3aSJohn Baldwin 		 * buffer.
1709c0e3d3aSJohn Baldwin 		 */
17169e533c3SJohn Baldwin 		if (inlen < blksz) {
17269e533c3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, blksz, blk);
1739c0e3d3aSJohn Baldwin 			inblk = blk;
17469e533c3SJohn Baldwin 			inlen = blksz;
175d295bdeeSPawel Jakub Dawidek 		}
17669e533c3SJohn Baldwin 		if (outlen < blksz) {
1779c0e3d3aSJohn Baldwin 			outblk = blk;
17869e533c3SJohn Baldwin 			outlen = blksz;
179cfb7b942SJohn Baldwin 		}
180cfb7b942SJohn Baldwin 
18169e533c3SJohn Baldwin 		todo = rounddown2(MIN(resid, MIN(inlen, outlen)), blksz);
1829c0e3d3aSJohn Baldwin 
1839c0e3d3aSJohn Baldwin 		if (encrypting)
184cfb7b942SJohn Baldwin 			exf->encrypt_multi(ctx, inblk, outblk, todo);
1859c0e3d3aSJohn Baldwin 		else
186cfb7b942SJohn Baldwin 			exf->decrypt_multi(ctx, inblk, outblk, todo);
187091d81d1SSam Leffler 
188cfb7b942SJohn Baldwin 		if (inblk == blk) {
18986be314dSJohn Baldwin 			inblk = crypto_cursor_segment(&cc_in, &inlen);
1909c0e3d3aSJohn Baldwin 		} else {
191cfb7b942SJohn Baldwin 			crypto_cursor_advance(&cc_in, todo);
192cfb7b942SJohn Baldwin 			inlen -= todo;
193cfb7b942SJohn Baldwin 			inblk += todo;
194cfb7b942SJohn Baldwin 			if (inlen == 0)
195cfb7b942SJohn Baldwin 				inblk = crypto_cursor_segment(&cc_in, &inlen);
19608fca7a5SJohn-Mark Gurney 		}
197091d81d1SSam Leffler 
198cfb7b942SJohn Baldwin 		if (outblk == blk) {
19969e533c3SJohn Baldwin 			crypto_cursor_copyback(&cc_out, blksz, blk);
20086be314dSJohn Baldwin 			outblk = crypto_cursor_segment(&cc_out, &outlen);
2019c0e3d3aSJohn Baldwin 		} else {
202cfb7b942SJohn Baldwin 			crypto_cursor_advance(&cc_out, todo);
203cfb7b942SJohn Baldwin 			outlen -= todo;
204cfb7b942SJohn Baldwin 			outblk += todo;
205cfb7b942SJohn Baldwin 			if (outlen == 0)
206cfb7b942SJohn Baldwin 				outblk = crypto_cursor_segment(&cc_out,
207cfb7b942SJohn Baldwin 				    &outlen);
208091d81d1SSam Leffler 		}
209f34a967bSPawel Jakub Dawidek 	}
210f34a967bSPawel Jakub Dawidek 
211723d8764SJohn Baldwin 	/* Handle trailing partial block for stream ciphers. */
2129c0e3d3aSJohn Baldwin 	if (resid > 0) {
213723d8764SJohn Baldwin 		KASSERT(exf->native_blocksize != 0,
214723d8764SJohn Baldwin 		    ("%s: partial block of %d bytes for cipher %s",
2152cd83828SJohn Baldwin 		    __func__, resid, exf->name));
21669e533c3SJohn Baldwin 		KASSERT(resid < blksz, ("%s: partial block too big", __func__));
217723d8764SJohn Baldwin 
21886be314dSJohn Baldwin 		inblk = crypto_cursor_segment(&cc_in, &inlen);
21986be314dSJohn Baldwin 		outblk = crypto_cursor_segment(&cc_out, &outlen);
2209c0e3d3aSJohn Baldwin 		if (inlen < resid) {
2219c0e3d3aSJohn Baldwin 			crypto_cursor_copydata(&cc_in, resid, blk);
2229c0e3d3aSJohn Baldwin 			inblk = blk;
22386be314dSJohn Baldwin 		}
2249c0e3d3aSJohn Baldwin 		if (outlen < resid)
2259c0e3d3aSJohn Baldwin 			outblk = blk;
2269c0e3d3aSJohn Baldwin 		if (encrypting)
227b54d1284SJohn Baldwin 			exf->encrypt_last(ctx, inblk, outblk,
2289c0e3d3aSJohn Baldwin 			    resid);
2299c0e3d3aSJohn Baldwin 		else
230b54d1284SJohn Baldwin 			exf->decrypt_last(ctx, inblk, outblk,
2319c0e3d3aSJohn Baldwin 			    resid);
2329c0e3d3aSJohn Baldwin 		if (outlen < resid)
2339c0e3d3aSJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
234723d8764SJohn Baldwin 	}
235723d8764SJohn Baldwin 
236b54d1284SJohn Baldwin 	explicit_bzero(ctx, exf->ctxsize);
23720c128daSJohn Baldwin 	explicit_bzero(blk, sizeof(blk));
2389c0e3d3aSJohn Baldwin 	return (0);
239091d81d1SSam Leffler }
240091d81d1SSam Leffler 
241091d81d1SSam Leffler /*
242c0341432SJohn Baldwin  * Compute or verify hash.
243091d81d1SSam Leffler  */
244091d81d1SSam Leffler static int
245dc475c9bSJohn Baldwin swcr_authcompute(const struct swcr_session *ses, struct cryptop *crp)
246091d81d1SSam Leffler {
2477051c579SJohn Baldwin 	struct {
2487051c579SJohn Baldwin 		union authctx ctx;
249c0341432SJohn Baldwin 		u_char aalg[HASH_MAX_LEN];
2507051c579SJohn Baldwin 		u_char uaalg[HASH_MAX_LEN];
2517051c579SJohn Baldwin 	} s;
252c0341432SJohn Baldwin 	const struct crypto_session_params *csp;
2536113a08bSJohn Baldwin 	const struct swcr_auth *sw;
254d8787d4fSMark Johnston 	const struct auth_hash *axf;
255091d81d1SSam Leffler 	int err;
256091d81d1SSam Leffler 
257c0341432SJohn Baldwin 	sw = &ses->swcr_auth;
258091d81d1SSam Leffler 
259091d81d1SSam Leffler 	axf = sw->sw_axf;
260091d81d1SSam Leffler 
261c0341432SJohn Baldwin 	csp = crypto_get_params(crp->crp_session);
2626038018aSMarcin Wojtas 	if (crp->crp_auth_key != NULL) {
2636113a08bSJohn Baldwin 		if (sw->sw_hmac) {
2646113a08bSJohn Baldwin 			hmac_init_ipad(axf, crp->crp_auth_key,
2657051c579SJohn Baldwin 			    csp->csp_auth_klen, &s.ctx);
2666113a08bSJohn Baldwin 		} else {
2677051c579SJohn Baldwin 			axf->Init(&s.ctx);
2687051c579SJohn Baldwin 			axf->Setkey(&s.ctx, crp->crp_auth_key,
269c0341432SJohn Baldwin 			    csp->csp_auth_klen);
27025b7033bSConrad Meyer 		}
2716113a08bSJohn Baldwin 	} else
2727051c579SJohn Baldwin 		memcpy(&s.ctx, sw->sw_ictx, axf->ctxsize);
273091d81d1SSam Leffler 
2749b774dc0SJohn Baldwin 	if (crp->crp_aad != NULL)
2757051c579SJohn Baldwin 		err = axf->Update(&s.ctx, crp->crp_aad, crp->crp_aad_length);
2769b774dc0SJohn Baldwin 	else
277c0341432SJohn Baldwin 		err = crypto_apply(crp, crp->crp_aad_start, crp->crp_aad_length,
2787051c579SJohn Baldwin 		    axf->Update, &s.ctx);
279091d81d1SSam Leffler 	if (err)
280e0b155feSJohn Baldwin 		goto out;
281091d81d1SSam Leffler 
2829c0e3d3aSJohn Baldwin 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp) &&
2839c0e3d3aSJohn Baldwin 	    CRYPTO_OP_IS_ENCRYPT(crp->crp_op))
2849c0e3d3aSJohn Baldwin 		err = crypto_apply_buf(&crp->crp_obuf,
2859c0e3d3aSJohn Baldwin 		    crp->crp_payload_output_start, crp->crp_payload_length,
2867051c579SJohn Baldwin 		    axf->Update, &s.ctx);
2879c0e3d3aSJohn Baldwin 	else
2889c0e3d3aSJohn Baldwin 		err = crypto_apply(crp, crp->crp_payload_start,
2897051c579SJohn Baldwin 		    crp->crp_payload_length, axf->Update, &s.ctx);
290c0341432SJohn Baldwin 	if (err)
291e0b155feSJohn Baldwin 		goto out;
292091d81d1SSam Leffler 
2936038018aSMarcin Wojtas 	if (csp->csp_flags & CSP_F_ESN)
2947051c579SJohn Baldwin 		axf->Update(&s.ctx, crp->crp_esn, 4);
2956038018aSMarcin Wojtas 
2967051c579SJohn Baldwin 	axf->Final(s.aalg, &s.ctx);
2976113a08bSJohn Baldwin 	if (sw->sw_hmac) {
2986113a08bSJohn Baldwin 		if (crp->crp_auth_key != NULL)
2996113a08bSJohn Baldwin 			hmac_init_opad(axf, crp->crp_auth_key,
3007051c579SJohn Baldwin 			    csp->csp_auth_klen, &s.ctx);
3016113a08bSJohn Baldwin 		else
3027051c579SJohn Baldwin 			memcpy(&s.ctx, sw->sw_octx, axf->ctxsize);
3037051c579SJohn Baldwin 		axf->Update(&s.ctx, s.aalg, axf->hashsize);
3047051c579SJohn Baldwin 		axf->Final(s.aalg, &s.ctx);
305091d81d1SSam Leffler 	}
306091d81d1SSam Leffler 
307c0341432SJohn Baldwin 	if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
3087051c579SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, sw->sw_mlen, s.uaalg);
3097051c579SJohn Baldwin 		if (timingsafe_bcmp(s.aalg, s.uaalg, sw->sw_mlen) != 0)
31020c128daSJohn Baldwin 			err = EBADMSG;
311c0341432SJohn Baldwin 	} else {
312091d81d1SSam Leffler 		/* Inject the authentication data */
3137051c579SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, sw->sw_mlen, s.aalg);
314c0341432SJohn Baldwin 	}
315e0b155feSJohn Baldwin out:
3167051c579SJohn Baldwin 	explicit_bzero(&s, sizeof(s));
31720c128daSJohn Baldwin 	return (err);
318091d81d1SSam Leffler }
319091d81d1SSam Leffler 
32008fca7a5SJohn-Mark Gurney CTASSERT(INT_MAX <= (1ll<<39) - 256);	/* GCM: plain text < 2^39-256 */
32108fca7a5SJohn-Mark Gurney CTASSERT(INT_MAX <= (uint64_t)-1);	/* GCM: associated data <= 2^64-1 */
32208fca7a5SJohn-Mark Gurney 
32308fca7a5SJohn-Mark Gurney static int
324dc475c9bSJohn Baldwin swcr_gmac(const struct swcr_session *ses, struct cryptop *crp)
32508fca7a5SJohn-Mark Gurney {
3267051c579SJohn Baldwin 	struct {
3277051c579SJohn Baldwin 		union authctx ctx;
32826d292d3SJohn Baldwin 		uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))];
32926d292d3SJohn Baldwin 		u_char tag[GMAC_DIGEST_LEN];
3307051c579SJohn Baldwin 		u_char tag2[GMAC_DIGEST_LEN];
3317051c579SJohn Baldwin 	} s;
3327051c579SJohn Baldwin 	u_char *blk = (u_char *)s.blkbuf;
3339c0e3d3aSJohn Baldwin 	struct crypto_buffer_cursor cc;
33426d292d3SJohn Baldwin 	const u_char *inblk;
3356113a08bSJohn Baldwin 	const struct swcr_auth *swa;
336d8787d4fSMark Johnston 	const struct auth_hash *axf;
33708fca7a5SJohn-Mark Gurney 	uint32_t *blkp;
33886be314dSJohn Baldwin 	size_t len;
33986be314dSJohn Baldwin 	int blksz, error, ivlen, resid;
34008fca7a5SJohn-Mark Gurney 
341c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
34208fca7a5SJohn-Mark Gurney 	axf = swa->sw_axf;
34326d292d3SJohn Baldwin 	blksz = GMAC_BLOCK_LEN;
34426d292d3SJohn Baldwin 	KASSERT(axf->blocksize == blksz, ("%s: axf block size mismatch",
34526d292d3SJohn Baldwin 	    __func__));
34608fca7a5SJohn-Mark Gurney 
3476113a08bSJohn Baldwin 	if (crp->crp_auth_key != NULL) {
3487051c579SJohn Baldwin 		axf->Init(&s.ctx);
3497051c579SJohn Baldwin 		axf->Setkey(&s.ctx, crp->crp_auth_key,
3506113a08bSJohn Baldwin 		    crypto_get_params(crp->crp_session)->csp_auth_klen);
3516113a08bSJohn Baldwin 	} else
3527051c579SJohn Baldwin 		memcpy(&s.ctx, swa->sw_ictx, axf->ctxsize);
3536113a08bSJohn Baldwin 
35408fca7a5SJohn-Mark Gurney 	/* Initialize the IV */
355c0341432SJohn Baldwin 	ivlen = AES_GCM_IV_LEN;
3561c9b25a5SJohn Baldwin 	crypto_read_iv(crp, blk);
35708fca7a5SJohn-Mark Gurney 
3587051c579SJohn Baldwin 	axf->Reinit(&s.ctx, blk, ivlen);
3599c0e3d3aSJohn Baldwin 	crypto_cursor_init(&cc, &crp->crp_buf);
3609c0e3d3aSJohn Baldwin 	crypto_cursor_advance(&cc, crp->crp_payload_start);
36126d292d3SJohn Baldwin 	for (resid = crp->crp_payload_length; resid >= blksz; resid -= len) {
36286be314dSJohn Baldwin 		inblk = crypto_cursor_segment(&cc, &len);
36326d292d3SJohn Baldwin 		if (len >= blksz) {
36426d292d3SJohn Baldwin 			len = rounddown(MIN(len, resid), blksz);
36526d292d3SJohn Baldwin 			crypto_cursor_advance(&cc, len);
36626d292d3SJohn Baldwin 		} else {
36726d292d3SJohn Baldwin 			len = blksz;
3689c0e3d3aSJohn Baldwin 			crypto_cursor_copydata(&cc, len, blk);
36926d292d3SJohn Baldwin 			inblk = blk;
37026d292d3SJohn Baldwin 		}
3717051c579SJohn Baldwin 		axf->Update(&s.ctx, inblk, len);
37226d292d3SJohn Baldwin 	}
37326d292d3SJohn Baldwin 	if (resid > 0) {
37426d292d3SJohn Baldwin 		memset(blk, 0, blksz);
37526d292d3SJohn Baldwin 		crypto_cursor_copydata(&cc, resid, blk);
3767051c579SJohn Baldwin 		axf->Update(&s.ctx, blk, blksz);
37708fca7a5SJohn-Mark Gurney 	}
37808fca7a5SJohn-Mark Gurney 
37908fca7a5SJohn-Mark Gurney 	/* length block */
38026d292d3SJohn Baldwin 	memset(blk, 0, blksz);
38108fca7a5SJohn-Mark Gurney 	blkp = (uint32_t *)blk + 1;
382c0341432SJohn Baldwin 	*blkp = htobe32(crp->crp_payload_length * 8);
3837051c579SJohn Baldwin 	axf->Update(&s.ctx, blk, blksz);
384c0341432SJohn Baldwin 
385c0341432SJohn Baldwin 	/* Finalize MAC */
3867051c579SJohn Baldwin 	axf->Final(s.tag, &s.ctx);
387c0341432SJohn Baldwin 
38820c128daSJohn Baldwin 	error = 0;
389c0341432SJohn Baldwin 	if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
390c0341432SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen,
3917051c579SJohn Baldwin 		    s.tag2);
3927051c579SJohn Baldwin 		if (timingsafe_bcmp(s.tag, s.tag2, swa->sw_mlen) != 0)
39320c128daSJohn Baldwin 			error = EBADMSG;
394c0341432SJohn Baldwin 	} else {
395c0341432SJohn Baldwin 		/* Inject the authentication data */
3967051c579SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, s.tag);
397c0341432SJohn Baldwin 	}
3987051c579SJohn Baldwin 	explicit_bzero(&s, sizeof(s));
39920c128daSJohn Baldwin 	return (error);
400c0341432SJohn Baldwin }
401c0341432SJohn Baldwin 
402c0341432SJohn Baldwin static int
403dc475c9bSJohn Baldwin swcr_gcm(const struct swcr_session *ses, struct cryptop *crp)
404c0341432SJohn Baldwin {
4057051c579SJohn Baldwin 	struct {
40626d292d3SJohn Baldwin 		uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))];
40726d292d3SJohn Baldwin 		u_char tag[GMAC_DIGEST_LEN];
4087051c579SJohn Baldwin 		u_char tag2[GMAC_DIGEST_LEN];
4097051c579SJohn Baldwin 	} s;
4107051c579SJohn Baldwin 	u_char *blk = (u_char *)s.blkbuf;
4119c0e3d3aSJohn Baldwin 	struct crypto_buffer_cursor cc_in, cc_out;
41226d292d3SJohn Baldwin 	const u_char *inblk;
41326d292d3SJohn Baldwin 	u_char *outblk;
414*a221a8f4SJohn Baldwin 	size_t inlen, outlen, todo;
415b54d1284SJohn Baldwin 	const struct swcr_auth *swa;
416b54d1284SJohn Baldwin 	const struct swcr_encdec *swe;
417d8787d4fSMark Johnston 	const struct enc_xform *exf;
418b54d1284SJohn Baldwin 	void *ctx;
419c0341432SJohn Baldwin 	uint32_t *blkp;
42086be314dSJohn Baldwin 	int blksz, error, ivlen, r, resid;
421c0341432SJohn Baldwin 
422c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
423c0341432SJohn Baldwin 	swe = &ses->swcr_encdec;
424c0341432SJohn Baldwin 	exf = swe->sw_exf;
425ab91fb6cSJohn Baldwin 	blksz = GMAC_BLOCK_LEN;
426ab91fb6cSJohn Baldwin 	KASSERT(blksz == exf->native_blocksize,
427723d8764SJohn Baldwin 	    ("%s: blocksize mismatch", __func__));
428c0341432SJohn Baldwin 
429c0341432SJohn Baldwin 	if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0)
430c0341432SJohn Baldwin 		return (EINVAL);
431c0341432SJohn Baldwin 
432c0341432SJohn Baldwin 	ivlen = AES_GCM_IV_LEN;
433c0341432SJohn Baldwin 
434b54d1284SJohn Baldwin 	ctx = __builtin_alloca(exf->ctxsize);
435ab91fb6cSJohn Baldwin 	if (crp->crp_cipher_key != NULL)
436b54d1284SJohn Baldwin 		exf->setkey(ctx, crp->crp_cipher_key,
437ab91fb6cSJohn Baldwin 		    crypto_get_params(crp->crp_session)->csp_cipher_klen);
438b54d1284SJohn Baldwin 	else
439b54d1284SJohn Baldwin 		memcpy(ctx, swe->sw_ctx, exf->ctxsize);
440b54d1284SJohn Baldwin 	exf->reinit(ctx, crp->crp_iv, ivlen);
441c0341432SJohn Baldwin 
442c0341432SJohn Baldwin 	/* Supply MAC with AAD */
4439b774dc0SJohn Baldwin 	if (crp->crp_aad != NULL) {
444*a221a8f4SJohn Baldwin 		inlen = rounddown2(crp->crp_aad_length, blksz);
445*a221a8f4SJohn Baldwin 		if (inlen != 0)
446*a221a8f4SJohn Baldwin 			exf->update(ctx, crp->crp_aad, inlen);
447*a221a8f4SJohn Baldwin 		if (crp->crp_aad_length != inlen) {
4489b774dc0SJohn Baldwin 			memset(blk, 0, blksz);
449*a221a8f4SJohn Baldwin 			memcpy(blk, (char *)crp->crp_aad + inlen,
450*a221a8f4SJohn Baldwin 			    crp->crp_aad_length - inlen);
451b54d1284SJohn Baldwin 			exf->update(ctx, blk, blksz);
4529b774dc0SJohn Baldwin 		}
4539b774dc0SJohn Baldwin 	} else {
4549c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_in, &crp->crp_buf);
4559c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_in, crp->crp_aad_start);
4569b774dc0SJohn Baldwin 		for (resid = crp->crp_aad_length; resid >= blksz;
457*a221a8f4SJohn Baldwin 		     resid -= inlen) {
458*a221a8f4SJohn Baldwin 			inblk = crypto_cursor_segment(&cc_in, &inlen);
459*a221a8f4SJohn Baldwin 			if (inlen >= blksz) {
460*a221a8f4SJohn Baldwin 				inlen = rounddown2(MIN(inlen, resid), blksz);
461*a221a8f4SJohn Baldwin 				crypto_cursor_advance(&cc_in, inlen);
46226d292d3SJohn Baldwin 			} else {
463*a221a8f4SJohn Baldwin 				inlen = blksz;
464*a221a8f4SJohn Baldwin 				crypto_cursor_copydata(&cc_in, inlen, blk);
46526d292d3SJohn Baldwin 				inblk = blk;
46626d292d3SJohn Baldwin 			}
467*a221a8f4SJohn Baldwin 			exf->update(ctx, inblk, inlen);
46826d292d3SJohn Baldwin 		}
46926d292d3SJohn Baldwin 		if (resid > 0) {
47026d292d3SJohn Baldwin 			memset(blk, 0, blksz);
47126d292d3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, resid, blk);
472b54d1284SJohn Baldwin 			exf->update(ctx, blk, blksz);
473c0341432SJohn Baldwin 		}
4749b774dc0SJohn Baldwin 	}
475c0341432SJohn Baldwin 
476c0341432SJohn Baldwin 	/* Do encryption with MAC */
4779c0e3d3aSJohn Baldwin 	crypto_cursor_init(&cc_in, &crp->crp_buf);
4789c0e3d3aSJohn Baldwin 	crypto_cursor_advance(&cc_in, crp->crp_payload_start);
479*a221a8f4SJohn Baldwin 	inblk = crypto_cursor_segment(&cc_in, &inlen);
4809c0e3d3aSJohn Baldwin 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
4819c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_out, &crp->crp_obuf);
4829c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_out, crp->crp_payload_output_start);
4839c0e3d3aSJohn Baldwin 	} else
4849c0e3d3aSJohn Baldwin 		cc_out = cc_in;
485*a221a8f4SJohn Baldwin 	outblk = crypto_cursor_segment(&cc_out, &outlen);
486*a221a8f4SJohn Baldwin 
487*a221a8f4SJohn Baldwin 	for (resid = crp->crp_payload_length; resid >= blksz; resid -= todo) {
488*a221a8f4SJohn Baldwin 		if (inlen < blksz) {
48926d292d3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, blksz, blk);
49026d292d3SJohn Baldwin 			inblk = blk;
491*a221a8f4SJohn Baldwin 			inlen = blksz;
492c0341432SJohn Baldwin 		}
493*a221a8f4SJohn Baldwin 
49426d292d3SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
495*a221a8f4SJohn Baldwin 			if (outlen < blksz) {
49626d292d3SJohn Baldwin 				outblk = blk;
497*a221a8f4SJohn Baldwin 				outlen = blksz;
498*a221a8f4SJohn Baldwin 			}
499*a221a8f4SJohn Baldwin 
500*a221a8f4SJohn Baldwin 			todo = rounddown2(MIN(resid, MIN(inlen, outlen)),
501*a221a8f4SJohn Baldwin 			    blksz);
502*a221a8f4SJohn Baldwin 
503*a221a8f4SJohn Baldwin 			exf->encrypt_multi(ctx, inblk, outblk, todo);
504*a221a8f4SJohn Baldwin 			exf->update(ctx, outblk, todo);
505*a221a8f4SJohn Baldwin 
506*a221a8f4SJohn Baldwin 			if (outblk == blk) {
50726d292d3SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
508*a221a8f4SJohn Baldwin 				outblk = crypto_cursor_segment(&cc_out, &outlen);
50926d292d3SJohn Baldwin 			} else {
510*a221a8f4SJohn Baldwin 				crypto_cursor_advance(&cc_out, todo);
511*a221a8f4SJohn Baldwin 				outlen -= todo;
512*a221a8f4SJohn Baldwin 				outblk += todo;
513*a221a8f4SJohn Baldwin 				if (outlen == 0)
514*a221a8f4SJohn Baldwin 					outblk = crypto_cursor_segment(&cc_out,
515*a221a8f4SJohn Baldwin 					    &outlen);
516*a221a8f4SJohn Baldwin 			}
517*a221a8f4SJohn Baldwin 		} else {
518*a221a8f4SJohn Baldwin 			todo = rounddown2(MIN(resid, inlen), blksz);
519*a221a8f4SJohn Baldwin 			exf->update(ctx, inblk, todo);
520*a221a8f4SJohn Baldwin 		}
521*a221a8f4SJohn Baldwin 
522*a221a8f4SJohn Baldwin 		if (inblk == blk) {
523*a221a8f4SJohn Baldwin 			inblk = crypto_cursor_segment(&cc_in, &inlen);
524*a221a8f4SJohn Baldwin 		} else {
525*a221a8f4SJohn Baldwin 			crypto_cursor_advance(&cc_in, todo);
526*a221a8f4SJohn Baldwin 			inlen -= todo;
527*a221a8f4SJohn Baldwin 			inblk += todo;
528*a221a8f4SJohn Baldwin 			if (inlen == 0)
529*a221a8f4SJohn Baldwin 				inblk = crypto_cursor_segment(&cc_in, &inlen);
53026d292d3SJohn Baldwin 		}
53126d292d3SJohn Baldwin 	}
53226d292d3SJohn Baldwin 	if (resid > 0) {
53326d292d3SJohn Baldwin 		crypto_cursor_copydata(&cc_in, resid, blk);
53426d292d3SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
535b54d1284SJohn Baldwin 			exf->encrypt_last(ctx, blk, blk, resid);
53626d292d3SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
53726d292d3SJohn Baldwin 		}
538b54d1284SJohn Baldwin 		exf->update(ctx, blk, resid);
539c0341432SJohn Baldwin 	}
540c0341432SJohn Baldwin 
541c0341432SJohn Baldwin 	/* length block */
54226d292d3SJohn Baldwin 	memset(blk, 0, blksz);
543c0341432SJohn Baldwin 	blkp = (uint32_t *)blk + 1;
544c0341432SJohn Baldwin 	*blkp = htobe32(crp->crp_aad_length * 8);
545c0341432SJohn Baldwin 	blkp = (uint32_t *)blk + 3;
546c0341432SJohn Baldwin 	*blkp = htobe32(crp->crp_payload_length * 8);
547b54d1284SJohn Baldwin 	exf->update(ctx, blk, blksz);
548c0341432SJohn Baldwin 
549c0341432SJohn Baldwin 	/* Finalize MAC */
5507051c579SJohn Baldwin 	exf->final(s.tag, ctx);
551c0341432SJohn Baldwin 
552c0341432SJohn Baldwin 	/* Validate tag */
55320c128daSJohn Baldwin 	error = 0;
554c0341432SJohn Baldwin 	if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
5557051c579SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen,
5567051c579SJohn Baldwin 		    s.tag2);
5577051c579SJohn Baldwin 		r = timingsafe_bcmp(s.tag, s.tag2, swa->sw_mlen);
55820c128daSJohn Baldwin 		if (r != 0) {
55920c128daSJohn Baldwin 			error = EBADMSG;
56020c128daSJohn Baldwin 			goto out;
56120c128daSJohn Baldwin 		}
562c0341432SJohn Baldwin 
563c0341432SJohn Baldwin 		/* tag matches, decrypt data */
5649c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_in, &crp->crp_buf);
5659c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_in, crp->crp_payload_start);
566*a221a8f4SJohn Baldwin 		inblk = crypto_cursor_segment(&cc_in, &inlen);
567*a221a8f4SJohn Baldwin 
56826d292d3SJohn Baldwin 		for (resid = crp->crp_payload_length; resid > blksz;
569*a221a8f4SJohn Baldwin 		     resid -= todo) {
570*a221a8f4SJohn Baldwin 			if (inlen < blksz) {
57126d292d3SJohn Baldwin 				crypto_cursor_copydata(&cc_in, blksz, blk);
57226d292d3SJohn Baldwin 				inblk = blk;
573*a221a8f4SJohn Baldwin 				inlen = blksz;
574*a221a8f4SJohn Baldwin 			}
575*a221a8f4SJohn Baldwin 			if (outlen < blksz) {
57626d292d3SJohn Baldwin 				outblk = blk;
577*a221a8f4SJohn Baldwin 				outlen = blksz;
578*a221a8f4SJohn Baldwin 			}
579*a221a8f4SJohn Baldwin 
580*a221a8f4SJohn Baldwin 			todo = rounddown2(MIN(resid, MIN(inlen, outlen)),
581*a221a8f4SJohn Baldwin 			    blksz);
582*a221a8f4SJohn Baldwin 
583*a221a8f4SJohn Baldwin 			exf->decrypt_multi(ctx, inblk, outblk, todo);
584*a221a8f4SJohn Baldwin 
585*a221a8f4SJohn Baldwin 			if (inblk == blk) {
586*a221a8f4SJohn Baldwin 				inblk = crypto_cursor_segment(&cc_in, &inlen);
587*a221a8f4SJohn Baldwin 			} else {
588*a221a8f4SJohn Baldwin 				crypto_cursor_advance(&cc_in, todo);
589*a221a8f4SJohn Baldwin 				inlen -= todo;
590*a221a8f4SJohn Baldwin 				inblk += todo;
591*a221a8f4SJohn Baldwin 				if (inlen == 0)
592*a221a8f4SJohn Baldwin 					inblk = crypto_cursor_segment(&cc_in,
593*a221a8f4SJohn Baldwin 					    &inlen);
594*a221a8f4SJohn Baldwin 			}
595*a221a8f4SJohn Baldwin 
596*a221a8f4SJohn Baldwin 			if (outblk == blk) {
59726d292d3SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
598*a221a8f4SJohn Baldwin 				outblk = crypto_cursor_segment(&cc_out,
599*a221a8f4SJohn Baldwin 				    &outlen);
600*a221a8f4SJohn Baldwin 			} else {
601*a221a8f4SJohn Baldwin 				crypto_cursor_advance(&cc_out, todo);
602*a221a8f4SJohn Baldwin 				outlen -= todo;
603*a221a8f4SJohn Baldwin 				outblk += todo;
604*a221a8f4SJohn Baldwin 				if (outlen == 0)
605*a221a8f4SJohn Baldwin 					outblk = crypto_cursor_segment(&cc_out,
606*a221a8f4SJohn Baldwin 					    &outlen);
607*a221a8f4SJohn Baldwin 			}
60826d292d3SJohn Baldwin 		}
60926d292d3SJohn Baldwin 		if (resid > 0) {
61026d292d3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, resid, blk);
611b54d1284SJohn Baldwin 			exf->decrypt_last(ctx, blk, blk, resid);
61226d292d3SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
613c0341432SJohn Baldwin 		}
614c0341432SJohn Baldwin 	} else {
615c0341432SJohn Baldwin 		/* Inject the authentication data */
6167051c579SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen,
6177051c579SJohn Baldwin 		    s.tag);
618c0341432SJohn Baldwin 	}
619c0341432SJohn Baldwin 
62020c128daSJohn Baldwin out:
621b54d1284SJohn Baldwin 	explicit_bzero(ctx, exf->ctxsize);
6227051c579SJohn Baldwin 	explicit_bzero(&s, sizeof(s));
62320c128daSJohn Baldwin 
62420c128daSJohn Baldwin 	return (error);
625c0341432SJohn Baldwin }
626c0341432SJohn Baldwin 
6274361c4ebSJohn Baldwin static void
6284361c4ebSJohn Baldwin build_ccm_b0(const char *nonce, u_int nonce_length, u_int aad_length,
6294361c4ebSJohn Baldwin     u_int data_length, u_int tag_length, uint8_t *b0)
6304361c4ebSJohn Baldwin {
6314361c4ebSJohn Baldwin 	uint8_t *bp;
6324361c4ebSJohn Baldwin 	uint8_t flags, L;
6334361c4ebSJohn Baldwin 
6344361c4ebSJohn Baldwin 	KASSERT(nonce_length >= 7 && nonce_length <= 13,
6354361c4ebSJohn Baldwin 	    ("nonce_length must be between 7 and 13 bytes"));
6364361c4ebSJohn Baldwin 
6374361c4ebSJohn Baldwin 	/*
6384361c4ebSJohn Baldwin 	 * Need to determine the L field value.  This is the number of
6394361c4ebSJohn Baldwin 	 * bytes needed to specify the length of the message; the length
6404361c4ebSJohn Baldwin 	 * is whatever is left in the 16 bytes after specifying flags and
6414361c4ebSJohn Baldwin 	 * the nonce.
6424361c4ebSJohn Baldwin 	 */
6434361c4ebSJohn Baldwin 	L = 15 - nonce_length;
6444361c4ebSJohn Baldwin 
6454361c4ebSJohn Baldwin 	flags = ((aad_length > 0) << 6) +
6464361c4ebSJohn Baldwin 	    (((tag_length - 2) / 2) << 3) +
6474361c4ebSJohn Baldwin 	    L - 1;
6484361c4ebSJohn Baldwin 
6494361c4ebSJohn Baldwin 	/*
6504361c4ebSJohn Baldwin 	 * Now we need to set up the first block, which has flags, nonce,
6514361c4ebSJohn Baldwin 	 * and the message length.
6524361c4ebSJohn Baldwin 	 */
6534361c4ebSJohn Baldwin 	b0[0] = flags;
6544361c4ebSJohn Baldwin 	memcpy(b0 + 1, nonce, nonce_length);
6554361c4ebSJohn Baldwin 	bp = b0 + 1 + nonce_length;
6564361c4ebSJohn Baldwin 
6574361c4ebSJohn Baldwin 	/* Need to copy L' [aka L-1] bytes of data_length */
6584361c4ebSJohn Baldwin 	for (uint8_t *dst = b0 + CCM_CBC_BLOCK_LEN - 1; dst >= bp; dst--) {
6594361c4ebSJohn Baldwin 		*dst = data_length;
6604361c4ebSJohn Baldwin 		data_length >>= 8;
6614361c4ebSJohn Baldwin 	}
6624361c4ebSJohn Baldwin }
6634361c4ebSJohn Baldwin 
6644361c4ebSJohn Baldwin /* NB: OCF only supports AAD lengths < 2^32. */
6654361c4ebSJohn Baldwin static int
6664361c4ebSJohn Baldwin build_ccm_aad_length(u_int aad_length, uint8_t *blk)
6674361c4ebSJohn Baldwin {
6684361c4ebSJohn Baldwin 	if (aad_length < ((1 << 16) - (1 << 8))) {
6694361c4ebSJohn Baldwin 		be16enc(blk, aad_length);
6704361c4ebSJohn Baldwin 		return (sizeof(uint16_t));
6714361c4ebSJohn Baldwin 	} else {
6724361c4ebSJohn Baldwin 		blk[0] = 0xff;
6734361c4ebSJohn Baldwin 		blk[1] = 0xfe;
6744361c4ebSJohn Baldwin 		be32enc(blk + 2, aad_length);
6754361c4ebSJohn Baldwin 		return (2 + sizeof(uint32_t));
6764361c4ebSJohn Baldwin 	}
6774361c4ebSJohn Baldwin }
6784361c4ebSJohn Baldwin 
679c0341432SJohn Baldwin static int
680dc475c9bSJohn Baldwin swcr_ccm_cbc_mac(const struct swcr_session *ses, struct cryptop *crp)
681c0341432SJohn Baldwin {
6827051c579SJohn Baldwin 	struct {
6837051c579SJohn Baldwin 		union authctx ctx;
6844361c4ebSJohn Baldwin 		u_char blk[CCM_CBC_BLOCK_LEN];
6854361c4ebSJohn Baldwin 		u_char tag[AES_CBC_MAC_HASH_LEN];
6867051c579SJohn Baldwin 		u_char tag2[AES_CBC_MAC_HASH_LEN];
6877051c579SJohn Baldwin 	} s;
688ae18720dSJohn Baldwin 	const struct crypto_session_params *csp;
6896113a08bSJohn Baldwin 	const struct swcr_auth *swa;
690d8787d4fSMark Johnston 	const struct auth_hash *axf;
6914361c4ebSJohn Baldwin 	int error, ivlen, len;
692c0341432SJohn Baldwin 
693ae18720dSJohn Baldwin 	csp = crypto_get_params(crp->crp_session);
694c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
695c0341432SJohn Baldwin 	axf = swa->sw_axf;
696c0341432SJohn Baldwin 
6976113a08bSJohn Baldwin 	if (crp->crp_auth_key != NULL) {
6987051c579SJohn Baldwin 		axf->Init(&s.ctx);
6997051c579SJohn Baldwin 		axf->Setkey(&s.ctx, crp->crp_auth_key, csp->csp_auth_klen);
7006113a08bSJohn Baldwin 	} else
7017051c579SJohn Baldwin 		memcpy(&s.ctx, swa->sw_ictx, axf->ctxsize);
702c0341432SJohn Baldwin 
703c0341432SJohn Baldwin 	/* Initialize the IV */
704ae18720dSJohn Baldwin 	ivlen = csp->csp_ivlen;
705c0341432SJohn Baldwin 
7064361c4ebSJohn Baldwin 	/* Supply MAC with IV */
7077051c579SJohn Baldwin 	axf->Reinit(&s.ctx, crp->crp_iv, ivlen);
708c0341432SJohn Baldwin 
7094361c4ebSJohn Baldwin 	/* Supply MAC with b0. */
7104361c4ebSJohn Baldwin 	build_ccm_b0(crp->crp_iv, ivlen, crp->crp_payload_length, 0,
7117051c579SJohn Baldwin 	    swa->sw_mlen, s.blk);
7127051c579SJohn Baldwin 	axf->Update(&s.ctx, s.blk, CCM_CBC_BLOCK_LEN);
7134361c4ebSJohn Baldwin 
7147051c579SJohn Baldwin 	len = build_ccm_aad_length(crp->crp_payload_length, s.blk);
7157051c579SJohn Baldwin 	axf->Update(&s.ctx, s.blk, len);
7164361c4ebSJohn Baldwin 
7174361c4ebSJohn Baldwin 	crypto_apply(crp, crp->crp_payload_start, crp->crp_payload_length,
7187051c579SJohn Baldwin 	    axf->Update, &s.ctx);
719c0341432SJohn Baldwin 
720c0341432SJohn Baldwin 	/* Finalize MAC */
7217051c579SJohn Baldwin 	axf->Final(s.tag, &s.ctx);
722c0341432SJohn Baldwin 
7234361c4ebSJohn Baldwin 	error = 0;
724c0341432SJohn Baldwin 	if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
725c0341432SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen,
7267051c579SJohn Baldwin 		    s.tag2);
7277051c579SJohn Baldwin 		if (timingsafe_bcmp(s.tag, s.tag2, swa->sw_mlen) != 0)
72820c128daSJohn Baldwin 			error = EBADMSG;
729c0341432SJohn Baldwin 	} else {
730c0341432SJohn Baldwin 		/* Inject the authentication data */
7317051c579SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen,
7327051c579SJohn Baldwin 		    s.tag);
733c0341432SJohn Baldwin 	}
7347051c579SJohn Baldwin 	explicit_bzero(&s, sizeof(s));
73520c128daSJohn Baldwin 	return (error);
736c0341432SJohn Baldwin }
737c0341432SJohn Baldwin 
738c0341432SJohn Baldwin static int
739dc475c9bSJohn Baldwin swcr_ccm(const struct swcr_session *ses, struct cryptop *crp)
740c0341432SJohn Baldwin {
741ae18720dSJohn Baldwin 	const struct crypto_session_params *csp;
7427051c579SJohn Baldwin 	struct {
74326d292d3SJohn Baldwin 		uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))];
74426d292d3SJohn Baldwin 		u_char tag[AES_CBC_MAC_HASH_LEN];
7457051c579SJohn Baldwin 		u_char tag2[AES_CBC_MAC_HASH_LEN];
7467051c579SJohn Baldwin 	} s;
7477051c579SJohn Baldwin 	u_char *blk = (u_char *)s.blkbuf;
7489c0e3d3aSJohn Baldwin 	struct crypto_buffer_cursor cc_in, cc_out;
74926d292d3SJohn Baldwin 	const u_char *inblk;
75026d292d3SJohn Baldwin 	u_char *outblk;
751b54d1284SJohn Baldwin 	const struct swcr_auth *swa;
752b54d1284SJohn Baldwin 	const struct swcr_encdec *swe;
753d8787d4fSMark Johnston 	const struct enc_xform *exf;
754b54d1284SJohn Baldwin 	void *ctx;
75586be314dSJohn Baldwin 	size_t len;
75626d292d3SJohn Baldwin 	int blksz, error, ivlen, r, resid;
757c0341432SJohn Baldwin 
758ae18720dSJohn Baldwin 	csp = crypto_get_params(crp->crp_session);
759c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
760c0341432SJohn Baldwin 	swe = &ses->swcr_encdec;
761c0341432SJohn Baldwin 	exf = swe->sw_exf;
762ab91fb6cSJohn Baldwin 	blksz = AES_BLOCK_LEN;
763ab91fb6cSJohn Baldwin 	KASSERT(blksz == exf->native_blocksize,
764723d8764SJohn Baldwin 	    ("%s: blocksize mismatch", __func__));
765c0341432SJohn Baldwin 
766ae18720dSJohn Baldwin 	if (crp->crp_payload_length > ccm_max_payload_length(csp))
767ae18720dSJohn Baldwin 		return (EMSGSIZE);
768ae18720dSJohn Baldwin 
769c0341432SJohn Baldwin 	if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0)
770c0341432SJohn Baldwin 		return (EINVAL);
771c0341432SJohn Baldwin 
772ae18720dSJohn Baldwin 	ivlen = csp->csp_ivlen;
773c0341432SJohn Baldwin 
774b54d1284SJohn Baldwin 	ctx = __builtin_alloca(exf->ctxsize);
775ab91fb6cSJohn Baldwin 	if (crp->crp_cipher_key != NULL)
776b54d1284SJohn Baldwin 		exf->setkey(ctx, crp->crp_cipher_key,
777ab91fb6cSJohn Baldwin 		    crypto_get_params(crp->crp_session)->csp_cipher_klen);
778b54d1284SJohn Baldwin 	else
779b54d1284SJohn Baldwin 		memcpy(ctx, swe->sw_ctx, exf->ctxsize);
780b54d1284SJohn Baldwin 	exf->reinit(ctx, crp->crp_iv, ivlen);
781c0341432SJohn Baldwin 
7824361c4ebSJohn Baldwin 	/* Supply MAC with b0. */
7837051c579SJohn Baldwin 	_Static_assert(sizeof(s.blkbuf) >= CCM_CBC_BLOCK_LEN,
7844361c4ebSJohn Baldwin 	    "blkbuf too small for b0");
7854361c4ebSJohn Baldwin 	build_ccm_b0(crp->crp_iv, ivlen, crp->crp_aad_length,
7864361c4ebSJohn Baldwin 	    crp->crp_payload_length, swa->sw_mlen, blk);
787b54d1284SJohn Baldwin 	exf->update(ctx, blk, CCM_CBC_BLOCK_LEN);
7884361c4ebSJohn Baldwin 
789c0341432SJohn Baldwin 	/* Supply MAC with AAD */
7904361c4ebSJohn Baldwin 	if (crp->crp_aad_length != 0) {
7914361c4ebSJohn Baldwin 		len = build_ccm_aad_length(crp->crp_aad_length, blk);
792b54d1284SJohn Baldwin 		exf->update(ctx, blk, len);
7939b774dc0SJohn Baldwin 		if (crp->crp_aad != NULL)
794b54d1284SJohn Baldwin 			exf->update(ctx, crp->crp_aad, crp->crp_aad_length);
7959b774dc0SJohn Baldwin 		else
7964361c4ebSJohn Baldwin 			crypto_apply(crp, crp->crp_aad_start,
797b54d1284SJohn Baldwin 			    crp->crp_aad_length, exf->update, ctx);
7984361c4ebSJohn Baldwin 
7994361c4ebSJohn Baldwin 		/* Pad the AAD (including length field) to a full block. */
8004361c4ebSJohn Baldwin 		len = (len + crp->crp_aad_length) % CCM_CBC_BLOCK_LEN;
8014361c4ebSJohn Baldwin 		if (len != 0) {
8024361c4ebSJohn Baldwin 			len = CCM_CBC_BLOCK_LEN - len;
8034361c4ebSJohn Baldwin 			memset(blk, 0, CCM_CBC_BLOCK_LEN);
804b54d1284SJohn Baldwin 			exf->update(ctx, blk, len);
8054361c4ebSJohn Baldwin 		}
8064361c4ebSJohn Baldwin 	}
807c0341432SJohn Baldwin 
808c0341432SJohn Baldwin 	/* Do encryption/decryption with MAC */
8099c0e3d3aSJohn Baldwin 	crypto_cursor_init(&cc_in, &crp->crp_buf);
8109c0e3d3aSJohn Baldwin 	crypto_cursor_advance(&cc_in, crp->crp_payload_start);
8119c0e3d3aSJohn Baldwin 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
8129c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_out, &crp->crp_obuf);
8139c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_out, crp->crp_payload_output_start);
8149c0e3d3aSJohn Baldwin 	} else
8159c0e3d3aSJohn Baldwin 		cc_out = cc_in;
81626d292d3SJohn Baldwin 	for (resid = crp->crp_payload_length; resid >= blksz; resid -= blksz) {
81786be314dSJohn Baldwin 		inblk = crypto_cursor_segment(&cc_in, &len);
81886be314dSJohn Baldwin 		if (len < blksz) {
81926d292d3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, blksz, blk);
82026d292d3SJohn Baldwin 			inblk = blk;
82186be314dSJohn Baldwin 		} else
82226d292d3SJohn Baldwin 			crypto_cursor_advance(&cc_in, blksz);
823c0341432SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
82486be314dSJohn Baldwin 			outblk = crypto_cursor_segment(&cc_out, &len);
82586be314dSJohn Baldwin 			if (len < blksz)
82626d292d3SJohn Baldwin 				outblk = blk;
827b54d1284SJohn Baldwin 			exf->update(ctx, inblk, blksz);
828b54d1284SJohn Baldwin 			exf->encrypt(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);
833c0341432SJohn Baldwin 		} else {
834c0341432SJohn Baldwin 			/*
835c0341432SJohn Baldwin 			 * One of the problems with CCM+CBC is that
836c0341432SJohn Baldwin 			 * the authentication is done on the
83726d292d3SJohn Baldwin 			 * unencrypted data.  As a result, we have to
838c0341432SJohn Baldwin 			 * decrypt the data twice: once to generate
839c0341432SJohn Baldwin 			 * the tag and a second time after the tag is
840c0341432SJohn Baldwin 			 * verified.
841c0341432SJohn Baldwin 			 */
842b54d1284SJohn Baldwin 			exf->decrypt(ctx, inblk, blk);
843b54d1284SJohn Baldwin 			exf->update(ctx, blk, blksz);
84426d292d3SJohn Baldwin 		}
84526d292d3SJohn Baldwin 	}
84626d292d3SJohn Baldwin 	if (resid > 0) {
84726d292d3SJohn Baldwin 		crypto_cursor_copydata(&cc_in, resid, blk);
84826d292d3SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
849b54d1284SJohn Baldwin 			exf->update(ctx, blk, resid);
850b54d1284SJohn Baldwin 			exf->encrypt_last(ctx, blk, blk, resid);
85126d292d3SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
85226d292d3SJohn Baldwin 		} else {
853b54d1284SJohn Baldwin 			exf->decrypt_last(ctx, blk, blk, resid);
854b54d1284SJohn Baldwin 			exf->update(ctx, blk, resid);
855c0341432SJohn Baldwin 		}
85608fca7a5SJohn-Mark Gurney 	}
85708fca7a5SJohn-Mark Gurney 
85808fca7a5SJohn-Mark Gurney 	/* Finalize MAC */
8597051c579SJohn Baldwin 	exf->final(s.tag, ctx);
86008fca7a5SJohn-Mark Gurney 
86108fca7a5SJohn-Mark Gurney 	/* Validate tag */
86220c128daSJohn Baldwin 	error = 0;
863c0341432SJohn Baldwin 	if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
864c0341432SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen,
8657051c579SJohn Baldwin 		    s.tag2);
8667051c579SJohn Baldwin 		r = timingsafe_bcmp(s.tag, s.tag2, swa->sw_mlen);
86720c128daSJohn Baldwin 		if (r != 0) {
86820c128daSJohn Baldwin 			error = EBADMSG;
86920c128daSJohn Baldwin 			goto out;
87020c128daSJohn Baldwin 		}
871c0341432SJohn Baldwin 
87208fca7a5SJohn-Mark Gurney 		/* tag matches, decrypt data */
873b54d1284SJohn Baldwin 		exf->reinit(ctx, crp->crp_iv, ivlen);
8749c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_in, &crp->crp_buf);
8759c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_in, crp->crp_payload_start);
87626d292d3SJohn Baldwin 		for (resid = crp->crp_payload_length; resid > blksz;
87726d292d3SJohn Baldwin 		     resid -= blksz) {
87886be314dSJohn Baldwin 			inblk = crypto_cursor_segment(&cc_in, &len);
87986be314dSJohn Baldwin 			if (len < blksz) {
88026d292d3SJohn Baldwin 				crypto_cursor_copydata(&cc_in, blksz, blk);
88126d292d3SJohn Baldwin 				inblk = blk;
88286be314dSJohn Baldwin 			} else
88326d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_in, blksz);
88486be314dSJohn Baldwin 			outblk = crypto_cursor_segment(&cc_out, &len);
88586be314dSJohn Baldwin 			if (len < blksz)
88626d292d3SJohn Baldwin 				outblk = blk;
887b54d1284SJohn Baldwin 			exf->decrypt(ctx, inblk, outblk);
88826d292d3SJohn Baldwin 			if (outblk == blk)
88926d292d3SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
89026d292d3SJohn Baldwin 			else
89126d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_out, blksz);
89226d292d3SJohn Baldwin 		}
89326d292d3SJohn Baldwin 		if (resid > 0) {
89426d292d3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, resid, blk);
895b54d1284SJohn Baldwin 			exf->decrypt_last(ctx, blk, blk, resid);
89626d292d3SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
89708fca7a5SJohn-Mark Gurney 		}
89808fca7a5SJohn-Mark Gurney 	} else {
89908fca7a5SJohn-Mark Gurney 		/* Inject the authentication data */
9007051c579SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen,
9017051c579SJohn Baldwin 		    s.tag);
90208fca7a5SJohn-Mark Gurney 	}
90308fca7a5SJohn-Mark Gurney 
90420c128daSJohn Baldwin out:
905b54d1284SJohn Baldwin 	explicit_bzero(ctx, exf->ctxsize);
9067051c579SJohn Baldwin 	explicit_bzero(&s, sizeof(s));
90720c128daSJohn Baldwin 	return (error);
90808fca7a5SJohn-Mark Gurney }
90908fca7a5SJohn-Mark Gurney 
910dd2e1352SJohn Baldwin static int
911dc475c9bSJohn Baldwin swcr_chacha20_poly1305(const struct swcr_session *ses, struct cryptop *crp)
912dd2e1352SJohn Baldwin {
913dd2e1352SJohn Baldwin 	const struct crypto_session_params *csp;
9147051c579SJohn Baldwin 	struct {
915dd2e1352SJohn Baldwin 		uint64_t blkbuf[howmany(CHACHA20_NATIVE_BLOCK_LEN, sizeof(uint64_t))];
916dd2e1352SJohn Baldwin 		u_char tag[POLY1305_HASH_LEN];
9177051c579SJohn Baldwin 		u_char tag2[POLY1305_HASH_LEN];
9187051c579SJohn Baldwin 	} s;
9197051c579SJohn Baldwin 	u_char *blk = (u_char *)s.blkbuf;
920dd2e1352SJohn Baldwin 	struct crypto_buffer_cursor cc_in, cc_out;
921dd2e1352SJohn Baldwin 	const u_char *inblk;
922dd2e1352SJohn Baldwin 	u_char *outblk;
923dd2e1352SJohn Baldwin 	uint64_t *blkp;
924b54d1284SJohn Baldwin 	const struct swcr_auth *swa;
925b54d1284SJohn Baldwin 	const struct swcr_encdec *swe;
926d8787d4fSMark Johnston 	const struct enc_xform *exf;
927b54d1284SJohn Baldwin 	void *ctx;
92886be314dSJohn Baldwin 	size_t len;
929dd2e1352SJohn Baldwin 	int blksz, error, r, resid;
930dd2e1352SJohn Baldwin 
931dd2e1352SJohn Baldwin 	swa = &ses->swcr_auth;
932dd2e1352SJohn Baldwin 	swe = &ses->swcr_encdec;
933dd2e1352SJohn Baldwin 	exf = swe->sw_exf;
934dd2e1352SJohn Baldwin 	blksz = exf->native_blocksize;
9357051c579SJohn Baldwin 	KASSERT(blksz <= sizeof(s.blkbuf), ("%s: blocksize mismatch", __func__));
936dd2e1352SJohn Baldwin 
937dd2e1352SJohn Baldwin 	if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0)
938dd2e1352SJohn Baldwin 		return (EINVAL);
939dd2e1352SJohn Baldwin 
940dd2e1352SJohn Baldwin 	csp = crypto_get_params(crp->crp_session);
941dd2e1352SJohn Baldwin 
942b54d1284SJohn Baldwin 	ctx = __builtin_alloca(exf->ctxsize);
943dd2e1352SJohn Baldwin 	if (crp->crp_cipher_key != NULL)
944b54d1284SJohn Baldwin 		exf->setkey(ctx, crp->crp_cipher_key,
945dd2e1352SJohn Baldwin 		    csp->csp_cipher_klen);
946b54d1284SJohn Baldwin 	else
947b54d1284SJohn Baldwin 		memcpy(ctx, swe->sw_ctx, exf->ctxsize);
948b54d1284SJohn Baldwin 	exf->reinit(ctx, crp->crp_iv, csp->csp_ivlen);
949dd2e1352SJohn Baldwin 
950ab91fb6cSJohn Baldwin 	/* Supply MAC with AAD */
951ab91fb6cSJohn Baldwin 	if (crp->crp_aad != NULL)
952b54d1284SJohn Baldwin 		exf->update(ctx, crp->crp_aad, crp->crp_aad_length);
953ab91fb6cSJohn Baldwin 	else
954b54d1284SJohn Baldwin 		crypto_apply(crp, crp->crp_aad_start, crp->crp_aad_length,
955b54d1284SJohn Baldwin 		    exf->update, ctx);
95604781697SJohn Baldwin 	if (crp->crp_aad_length % POLY1305_BLOCK_LEN != 0) {
957ab91fb6cSJohn Baldwin 		/* padding1 */
95804781697SJohn Baldwin 		memset(blk, 0, POLY1305_BLOCK_LEN);
95904781697SJohn Baldwin 		exf->update(ctx, blk, POLY1305_BLOCK_LEN -
96004781697SJohn Baldwin 		    crp->crp_aad_length % POLY1305_BLOCK_LEN);
961ab91fb6cSJohn Baldwin 	}
962ab91fb6cSJohn Baldwin 
963dd2e1352SJohn Baldwin 	/* Do encryption with MAC */
964dd2e1352SJohn Baldwin 	crypto_cursor_init(&cc_in, &crp->crp_buf);
965dd2e1352SJohn Baldwin 	crypto_cursor_advance(&cc_in, crp->crp_payload_start);
966dd2e1352SJohn Baldwin 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
967dd2e1352SJohn Baldwin 		crypto_cursor_init(&cc_out, &crp->crp_obuf);
968dd2e1352SJohn Baldwin 		crypto_cursor_advance(&cc_out, crp->crp_payload_output_start);
969dd2e1352SJohn Baldwin 	} else
970dd2e1352SJohn Baldwin 		cc_out = cc_in;
971dd2e1352SJohn Baldwin 	for (resid = crp->crp_payload_length; resid >= blksz; resid -= blksz) {
97286be314dSJohn Baldwin 		inblk = crypto_cursor_segment(&cc_in, &len);
97386be314dSJohn Baldwin 		if (len < blksz) {
974dd2e1352SJohn Baldwin 			crypto_cursor_copydata(&cc_in, blksz, blk);
975dd2e1352SJohn Baldwin 			inblk = blk;
97686be314dSJohn Baldwin 		} else
977dd2e1352SJohn Baldwin 			crypto_cursor_advance(&cc_in, blksz);
978dd2e1352SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
97986be314dSJohn Baldwin 			outblk = crypto_cursor_segment(&cc_out, &len);
98086be314dSJohn Baldwin 			if (len < blksz)
981dd2e1352SJohn Baldwin 				outblk = blk;
982b54d1284SJohn Baldwin 			exf->encrypt(ctx, inblk, outblk);
983b54d1284SJohn Baldwin 			exf->update(ctx, outblk, blksz);
984dd2e1352SJohn Baldwin 			if (outblk == blk)
985dd2e1352SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
986dd2e1352SJohn Baldwin 			else
987dd2e1352SJohn Baldwin 				crypto_cursor_advance(&cc_out, blksz);
988dd2e1352SJohn Baldwin 		} else {
989b54d1284SJohn Baldwin 			exf->update(ctx, inblk, blksz);
990dd2e1352SJohn Baldwin 		}
991dd2e1352SJohn Baldwin 	}
992dd2e1352SJohn Baldwin 	if (resid > 0) {
993dd2e1352SJohn Baldwin 		crypto_cursor_copydata(&cc_in, resid, blk);
994dd2e1352SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
995b54d1284SJohn Baldwin 			exf->encrypt_last(ctx, blk, blk, resid);
996dd2e1352SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
997dd2e1352SJohn Baldwin 		}
998b54d1284SJohn Baldwin 		exf->update(ctx, blk, resid);
99904781697SJohn Baldwin 		if (resid % POLY1305_BLOCK_LEN != 0) {
1000dd2e1352SJohn Baldwin 			/* padding2 */
100104781697SJohn Baldwin 			memset(blk, 0, POLY1305_BLOCK_LEN);
100204781697SJohn Baldwin 			exf->update(ctx, blk, POLY1305_BLOCK_LEN -
100304781697SJohn Baldwin 			    resid % POLY1305_BLOCK_LEN);
1004dd2e1352SJohn Baldwin 		}
1005dd2e1352SJohn Baldwin 	}
1006dd2e1352SJohn Baldwin 
1007dd2e1352SJohn Baldwin 	/* lengths */
1008dd2e1352SJohn Baldwin 	blkp = (uint64_t *)blk;
1009dd2e1352SJohn Baldwin 	blkp[0] = htole64(crp->crp_aad_length);
1010dd2e1352SJohn Baldwin 	blkp[1] = htole64(crp->crp_payload_length);
1011b54d1284SJohn Baldwin 	exf->update(ctx, blk, sizeof(uint64_t) * 2);
1012dd2e1352SJohn Baldwin 
1013dd2e1352SJohn Baldwin 	/* Finalize MAC */
10147051c579SJohn Baldwin 	exf->final(s.tag, ctx);
1015dd2e1352SJohn Baldwin 
1016dd2e1352SJohn Baldwin 	/* Validate tag */
1017dd2e1352SJohn Baldwin 	error = 0;
1018dd2e1352SJohn Baldwin 	if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
10197051c579SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen,
10207051c579SJohn Baldwin 		    s.tag2);
10217051c579SJohn Baldwin 		r = timingsafe_bcmp(s.tag, s.tag2, swa->sw_mlen);
1022dd2e1352SJohn Baldwin 		if (r != 0) {
1023dd2e1352SJohn Baldwin 			error = EBADMSG;
1024dd2e1352SJohn Baldwin 			goto out;
1025dd2e1352SJohn Baldwin 		}
1026dd2e1352SJohn Baldwin 
1027dd2e1352SJohn Baldwin 		/* tag matches, decrypt data */
1028dd2e1352SJohn Baldwin 		crypto_cursor_init(&cc_in, &crp->crp_buf);
1029dd2e1352SJohn Baldwin 		crypto_cursor_advance(&cc_in, crp->crp_payload_start);
1030dd2e1352SJohn Baldwin 		for (resid = crp->crp_payload_length; resid > blksz;
1031dd2e1352SJohn Baldwin 		     resid -= blksz) {
103286be314dSJohn Baldwin 			inblk = crypto_cursor_segment(&cc_in, &len);
103386be314dSJohn Baldwin 			if (len < blksz) {
1034dd2e1352SJohn Baldwin 				crypto_cursor_copydata(&cc_in, blksz, blk);
1035dd2e1352SJohn Baldwin 				inblk = blk;
103686be314dSJohn Baldwin 			} else
1037dd2e1352SJohn Baldwin 				crypto_cursor_advance(&cc_in, blksz);
103886be314dSJohn Baldwin 			outblk = crypto_cursor_segment(&cc_out, &len);
103986be314dSJohn Baldwin 			if (len < blksz)
1040dd2e1352SJohn Baldwin 				outblk = blk;
1041b54d1284SJohn Baldwin 			exf->decrypt(ctx, inblk, outblk);
1042dd2e1352SJohn Baldwin 			if (outblk == blk)
1043dd2e1352SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
1044dd2e1352SJohn Baldwin 			else
1045dd2e1352SJohn Baldwin 				crypto_cursor_advance(&cc_out, blksz);
1046dd2e1352SJohn Baldwin 		}
1047dd2e1352SJohn Baldwin 		if (resid > 0) {
1048dd2e1352SJohn Baldwin 			crypto_cursor_copydata(&cc_in, resid, blk);
1049b54d1284SJohn Baldwin 			exf->decrypt_last(ctx, blk, blk, resid);
1050dd2e1352SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
1051dd2e1352SJohn Baldwin 		}
1052dd2e1352SJohn Baldwin 	} else {
1053dd2e1352SJohn Baldwin 		/* Inject the authentication data */
10547051c579SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen,
10557051c579SJohn Baldwin 		    s.tag);
1056dd2e1352SJohn Baldwin 	}
1057dd2e1352SJohn Baldwin 
1058dd2e1352SJohn Baldwin out:
1059b54d1284SJohn Baldwin 	explicit_bzero(ctx, exf->ctxsize);
10607051c579SJohn Baldwin 	explicit_bzero(&s, sizeof(s));
1061dd2e1352SJohn Baldwin 	return (error);
1062dd2e1352SJohn Baldwin }
1063dd2e1352SJohn Baldwin 
1064091d81d1SSam Leffler /*
1065c0341432SJohn Baldwin  * Apply a cipher and a digest to perform EtA.
1066c0341432SJohn Baldwin  */
1067c0341432SJohn Baldwin static int
1068dc475c9bSJohn Baldwin swcr_eta(const struct swcr_session *ses, struct cryptop *crp)
1069c0341432SJohn Baldwin {
1070c0341432SJohn Baldwin 	int error;
1071c0341432SJohn Baldwin 
1072c0341432SJohn Baldwin 	if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
1073c0341432SJohn Baldwin 		error = swcr_encdec(ses, crp);
1074c0341432SJohn Baldwin 		if (error == 0)
1075c0341432SJohn Baldwin 			error = swcr_authcompute(ses, crp);
1076c0341432SJohn Baldwin 	} else {
1077c0341432SJohn Baldwin 		error = swcr_authcompute(ses, crp);
1078c0341432SJohn Baldwin 		if (error == 0)
1079c0341432SJohn Baldwin 			error = swcr_encdec(ses, crp);
1080c0341432SJohn Baldwin 	}
1081c0341432SJohn Baldwin 	return (error);
1082c0341432SJohn Baldwin }
1083c0341432SJohn Baldwin 
1084c0341432SJohn Baldwin /*
1085091d81d1SSam Leffler  * Apply a compression/decompression algorithm
1086091d81d1SSam Leffler  */
1087091d81d1SSam Leffler static int
1088dc475c9bSJohn Baldwin swcr_compdec(const struct swcr_session *ses, struct cryptop *crp)
1089091d81d1SSam Leffler {
1090d8787d4fSMark Johnston 	const struct comp_algo *cxf;
1091d3d79e96SJohn Baldwin 	uint8_t *data, *out;
1092091d81d1SSam Leffler 	int adj;
1093d3d79e96SJohn Baldwin 	uint32_t result;
1094091d81d1SSam Leffler 
1095c0341432SJohn Baldwin 	cxf = ses->swcr_compdec.sw_cxf;
1096091d81d1SSam Leffler 
1097091d81d1SSam Leffler 	/* We must handle the whole buffer of data in one time
1098091d81d1SSam Leffler 	 * then if there is not all the data in the mbuf, we must
1099091d81d1SSam Leffler 	 * copy in a buffer.
1100091d81d1SSam Leffler 	 */
1101091d81d1SSam Leffler 
1102c0341432SJohn Baldwin 	data = malloc(crp->crp_payload_length, M_CRYPTO_DATA,  M_NOWAIT);
1103091d81d1SSam Leffler 	if (data == NULL)
1104091d81d1SSam Leffler 		return (EINVAL);
1105c0341432SJohn Baldwin 	crypto_copydata(crp, crp->crp_payload_start, crp->crp_payload_length,
1106c0341432SJohn Baldwin 	    data);
1107091d81d1SSam Leffler 
1108c0341432SJohn Baldwin 	if (CRYPTO_OP_IS_COMPRESS(crp->crp_op))
1109c0341432SJohn Baldwin 		result = cxf->compress(data, crp->crp_payload_length, &out);
1110091d81d1SSam Leffler 	else
1111c0341432SJohn Baldwin 		result = cxf->decompress(data, crp->crp_payload_length, &out);
1112091d81d1SSam Leffler 
11131ede983cSDag-Erling Smørgrav 	free(data, M_CRYPTO_DATA);
1114091d81d1SSam Leffler 	if (result == 0)
1115c0341432SJohn Baldwin 		return (EINVAL);
1116c0341432SJohn Baldwin 	crp->crp_olen = result;
1117c0341432SJohn Baldwin 
1118c0341432SJohn Baldwin 	/* Check the compressed size when doing compression */
1119c0341432SJohn Baldwin 	if (CRYPTO_OP_IS_COMPRESS(crp->crp_op)) {
1120c0341432SJohn Baldwin 		if (result >= crp->crp_payload_length) {
1121c0341432SJohn Baldwin 			/* Compression was useless, we lost time */
1122c0341432SJohn Baldwin 			free(out, M_CRYPTO_DATA);
1123c0341432SJohn Baldwin 			return (0);
1124c0341432SJohn Baldwin 		}
1125c0341432SJohn Baldwin 	}
1126091d81d1SSam Leffler 
1127091d81d1SSam Leffler 	/* Copy back the (de)compressed data. m_copyback is
1128091d81d1SSam Leffler 	 * extending the mbuf as necessary.
1129091d81d1SSam Leffler 	 */
1130c0341432SJohn Baldwin 	crypto_copyback(crp, crp->crp_payload_start, result, out);
1131c0341432SJohn Baldwin 	if (result < crp->crp_payload_length) {
11329c0e3d3aSJohn Baldwin 		switch (crp->crp_buf.cb_type) {
1133c0341432SJohn Baldwin 		case CRYPTO_BUF_MBUF:
1134883a0196SJohn Baldwin 		case CRYPTO_BUF_SINGLE_MBUF:
1135c0341432SJohn Baldwin 			adj = result - crp->crp_payload_length;
11369c0e3d3aSJohn Baldwin 			m_adj(crp->crp_buf.cb_mbuf, adj);
1137c0341432SJohn Baldwin 			break;
1138c0341432SJohn Baldwin 		case CRYPTO_BUF_UIO: {
11399c0e3d3aSJohn Baldwin 			struct uio *uio = crp->crp_buf.cb_uio;
1140091d81d1SSam Leffler 			int ind;
1141091d81d1SSam Leffler 
1142c0341432SJohn Baldwin 			adj = crp->crp_payload_length - result;
1143091d81d1SSam Leffler 			ind = uio->uio_iovcnt - 1;
1144091d81d1SSam Leffler 
1145091d81d1SSam Leffler 			while (adj > 0 && ind >= 0) {
1146091d81d1SSam Leffler 				if (adj < uio->uio_iov[ind].iov_len) {
1147091d81d1SSam Leffler 					uio->uio_iov[ind].iov_len -= adj;
1148091d81d1SSam Leffler 					break;
1149091d81d1SSam Leffler 				}
1150091d81d1SSam Leffler 
1151091d81d1SSam Leffler 				adj -= uio->uio_iov[ind].iov_len;
1152091d81d1SSam Leffler 				uio->uio_iov[ind].iov_len = 0;
1153091d81d1SSam Leffler 				ind--;
1154091d81d1SSam Leffler 				uio->uio_iovcnt--;
1155091d81d1SSam Leffler 			}
1156091d81d1SSam Leffler 			}
1157c0341432SJohn Baldwin 			break;
1158e6f6d0c9SAlan Somers 		case CRYPTO_BUF_VMPAGE:
1159e6f6d0c9SAlan Somers 			adj = crp->crp_payload_length - result;
1160e6f6d0c9SAlan Somers 			crp->crp_buf.cb_vm_page_len -= adj;
1161e6f6d0c9SAlan Somers 			break;
11629c0e3d3aSJohn Baldwin 		default:
11639c0e3d3aSJohn Baldwin 			break;
1164c0341432SJohn Baldwin 		}
1165091d81d1SSam Leffler 	}
11661ede983cSDag-Erling Smørgrav 	free(out, M_CRYPTO_DATA);
1167091d81d1SSam Leffler 	return 0;
1168091d81d1SSam Leffler }
1169091d81d1SSam Leffler 
1170091d81d1SSam Leffler static int
11713e947048SJohn Baldwin swcr_setup_cipher(struct swcr_session *ses,
1172c0341432SJohn Baldwin     const struct crypto_session_params *csp)
1173091d81d1SSam Leffler {
1174c0341432SJohn Baldwin 	struct swcr_encdec *swe;
1175d8787d4fSMark Johnston 	const struct enc_xform *txf;
1176f6c4bc3bSPawel Jakub Dawidek 	int error;
1177091d81d1SSam Leffler 
1178c0341432SJohn Baldwin 	swe = &ses->swcr_encdec;
1179c0341432SJohn Baldwin 	txf = crypto_cipher(csp);
1180b54d1284SJohn Baldwin 	if (csp->csp_cipher_key != NULL) {
11813e947048SJohn Baldwin 		if (txf->ctxsize != 0) {
1182f313909aSJohn Baldwin 			swe->sw_ctx = malloc(txf->ctxsize, M_CRYPTO_DATA,
11833e947048SJohn Baldwin 			    M_NOWAIT);
1184f313909aSJohn Baldwin 			if (swe->sw_ctx == NULL)
11853e947048SJohn Baldwin 				return (ENOMEM);
11863e947048SJohn Baldwin 		}
1187f313909aSJohn Baldwin 		error = txf->setkey(swe->sw_ctx,
1188c0341432SJohn Baldwin 		    csp->csp_cipher_key, csp->csp_cipher_klen);
1189c0341432SJohn Baldwin 		if (error)
1190c0341432SJohn Baldwin 			return (error);
1191091d81d1SSam Leffler 	}
1192c0341432SJohn Baldwin 	swe->sw_exf = txf;
1193c0341432SJohn Baldwin 	return (0);
1194f6c4bc3bSPawel Jakub Dawidek }
1195091d81d1SSam Leffler 
1196c0341432SJohn Baldwin static int
1197c0341432SJohn Baldwin swcr_setup_auth(struct swcr_session *ses,
1198c0341432SJohn Baldwin     const struct crypto_session_params *csp)
1199c0341432SJohn Baldwin {
1200c0341432SJohn Baldwin 	struct swcr_auth *swa;
1201d8787d4fSMark Johnston 	const struct auth_hash *axf;
1202c0341432SJohn Baldwin 
1203c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
1204c0341432SJohn Baldwin 
1205c0341432SJohn Baldwin 	axf = crypto_auth_hash(csp);
1206c0341432SJohn Baldwin 	swa->sw_axf = axf;
1207c0341432SJohn Baldwin 	if (csp->csp_auth_mlen < 0 || csp->csp_auth_mlen > axf->hashsize)
1208c0341432SJohn Baldwin 		return (EINVAL);
1209c0341432SJohn Baldwin 	if (csp->csp_auth_mlen == 0)
1210c0341432SJohn Baldwin 		swa->sw_mlen = axf->hashsize;
1211c0341432SJohn Baldwin 	else
1212c0341432SJohn Baldwin 		swa->sw_mlen = csp->csp_auth_mlen;
12136113a08bSJohn Baldwin 	if (csp->csp_auth_klen == 0 || csp->csp_auth_key != NULL) {
12146113a08bSJohn Baldwin 		swa->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
12156113a08bSJohn Baldwin 		    M_NOWAIT);
1216c0341432SJohn Baldwin 		if (swa->sw_ictx == NULL)
1217c0341432SJohn Baldwin 			return (ENOBUFS);
12186113a08bSJohn Baldwin 	}
1219c0341432SJohn Baldwin 
1220c0341432SJohn Baldwin 	switch (csp->csp_auth_alg) {
1221091d81d1SSam Leffler 	case CRYPTO_SHA1_HMAC:
1222c97f39ceSConrad Meyer 	case CRYPTO_SHA2_224_HMAC:
1223f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_256_HMAC:
1224f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_384_HMAC:
1225f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_512_HMAC:
1226091d81d1SSam Leffler 	case CRYPTO_RIPEMD160_HMAC:
12276113a08bSJohn Baldwin 		swa->sw_hmac = true;
12286113a08bSJohn Baldwin 		if (csp->csp_auth_key != NULL) {
12293a0b6a93SJohn Baldwin 			swa->sw_octx = malloc(axf->ctxsize, M_CRYPTO_DATA,
1230091d81d1SSam Leffler 			    M_NOWAIT);
1231c0341432SJohn Baldwin 			if (swa->sw_octx == NULL)
1232c0341432SJohn Baldwin 				return (ENOBUFS);
12336113a08bSJohn Baldwin 			hmac_init_ipad(axf, csp->csp_auth_key,
12346113a08bSJohn Baldwin 			    csp->csp_auth_klen, swa->sw_ictx);
12356113a08bSJohn Baldwin 			hmac_init_opad(axf, csp->csp_auth_key,
12366113a08bSJohn Baldwin 			    csp->csp_auth_klen, swa->sw_octx);
1237091d81d1SSam Leffler 		}
1238091d81d1SSam Leffler 		break;
1239c3a688efSJohn Baldwin 	case CRYPTO_RIPEMD160:
1240091d81d1SSam Leffler 	case CRYPTO_SHA1:
1241c4729f6eSConrad Meyer 	case CRYPTO_SHA2_224:
1242c4729f6eSConrad Meyer 	case CRYPTO_SHA2_256:
1243c4729f6eSConrad Meyer 	case CRYPTO_SHA2_384:
1244c4729f6eSConrad Meyer 	case CRYPTO_SHA2_512:
1245aa268175SJohn Baldwin 	case CRYPTO_NULL_HMAC:
1246c0341432SJohn Baldwin 		axf->Init(swa->sw_ictx);
1247c0341432SJohn Baldwin 		break;
1248c0341432SJohn Baldwin 	case CRYPTO_AES_NIST_GMAC:
12496113a08bSJohn Baldwin 	case CRYPTO_AES_CCM_CBC_MAC:
12506113a08bSJohn Baldwin 	case CRYPTO_POLY1305:
12516113a08bSJohn Baldwin 		if (csp->csp_auth_key != NULL) {
1252c0341432SJohn Baldwin 			axf->Init(swa->sw_ictx);
1253c0341432SJohn Baldwin 			axf->Setkey(swa->sw_ictx, csp->csp_auth_key,
1254c0341432SJohn Baldwin 			    csp->csp_auth_klen);
12556113a08bSJohn Baldwin 		}
1256c0341432SJohn Baldwin 		break;
1257c0341432SJohn Baldwin 	case CRYPTO_BLAKE2B:
1258c0341432SJohn Baldwin 	case CRYPTO_BLAKE2S:
1259c0341432SJohn Baldwin 		/*
1260c0341432SJohn Baldwin 		 * Blake2b and Blake2s support an optional key but do
1261c0341432SJohn Baldwin 		 * not require one.
1262c0341432SJohn Baldwin 		 */
12636113a08bSJohn Baldwin 		if (csp->csp_auth_klen == 0)
12646113a08bSJohn Baldwin 			axf->Init(swa->sw_ictx);
12656113a08bSJohn Baldwin 		else if (csp->csp_auth_key != NULL)
1266c0341432SJohn Baldwin 			axf->Setkey(swa->sw_ictx, csp->csp_auth_key,
1267c0341432SJohn Baldwin 			    csp->csp_auth_klen);
12686113a08bSJohn Baldwin 		break;
12696113a08bSJohn Baldwin 	}
12706113a08bSJohn Baldwin 
12716113a08bSJohn Baldwin 	if (csp->csp_mode == CSP_MODE_DIGEST) {
12726113a08bSJohn Baldwin 		switch (csp->csp_auth_alg) {
12736113a08bSJohn Baldwin 		case CRYPTO_AES_NIST_GMAC:
12746113a08bSJohn Baldwin 			ses->swcr_process = swcr_gmac;
1275c0341432SJohn Baldwin 			break;
1276c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_CBC_MAC:
1277c0341432SJohn Baldwin 			ses->swcr_process = swcr_ccm_cbc_mac;
1278c0341432SJohn Baldwin 			break;
12796113a08bSJohn Baldwin 		default:
12806113a08bSJohn Baldwin 			ses->swcr_process = swcr_authcompute;
12816113a08bSJohn Baldwin 		}
1282091d81d1SSam Leffler 	}
1283091d81d1SSam Leffler 
1284c0341432SJohn Baldwin 	return (0);
1285c0341432SJohn Baldwin }
128608fca7a5SJohn-Mark Gurney 
1287c0341432SJohn Baldwin static int
1288ab91fb6cSJohn Baldwin swcr_setup_aead(struct swcr_session *ses,
1289c0341432SJohn Baldwin     const struct crypto_session_params *csp)
1290c0341432SJohn Baldwin {
1291c0341432SJohn Baldwin 	struct swcr_auth *swa;
1292ab91fb6cSJohn Baldwin 	int error;
1293c0341432SJohn Baldwin 
1294ab91fb6cSJohn Baldwin 	error = swcr_setup_cipher(ses, csp);
1295ab91fb6cSJohn Baldwin 	if (error)
1296ab91fb6cSJohn Baldwin 		return (error);
1297ab91fb6cSJohn Baldwin 
1298c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
1299c0341432SJohn Baldwin 	if (csp->csp_auth_mlen == 0)
1300ab91fb6cSJohn Baldwin 		swa->sw_mlen = ses->swcr_encdec.sw_exf->macsize;
1301c0341432SJohn Baldwin 	else
1302c0341432SJohn Baldwin 		swa->sw_mlen = csp->csp_auth_mlen;
1303ab91fb6cSJohn Baldwin 	return (0);
1304dd2e1352SJohn Baldwin }
1305dd2e1352SJohn Baldwin 
1306c0341432SJohn Baldwin static bool
1307c0341432SJohn Baldwin swcr_auth_supported(const struct crypto_session_params *csp)
1308109919c6SBenno Rice {
1309d8787d4fSMark Johnston 	const struct auth_hash *axf;
1310091d81d1SSam Leffler 
1311c0341432SJohn Baldwin 	axf = crypto_auth_hash(csp);
1312c0341432SJohn Baldwin 	if (axf == NULL)
1313c0341432SJohn Baldwin 		return (false);
1314c0341432SJohn Baldwin 	switch (csp->csp_auth_alg) {
1315091d81d1SSam Leffler 	case CRYPTO_SHA1_HMAC:
1316c97f39ceSConrad Meyer 	case CRYPTO_SHA2_224_HMAC:
1317f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_256_HMAC:
1318f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_384_HMAC:
1319f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_512_HMAC:
1320091d81d1SSam Leffler 	case CRYPTO_NULL_HMAC:
1321c0341432SJohn Baldwin 	case CRYPTO_RIPEMD160_HMAC:
1322091d81d1SSam Leffler 		break;
1323c0341432SJohn Baldwin 	case CRYPTO_AES_NIST_GMAC:
1324c0341432SJohn Baldwin 		switch (csp->csp_auth_klen * 8) {
1325c0341432SJohn Baldwin 		case 128:
1326c0341432SJohn Baldwin 		case 192:
1327c0341432SJohn Baldwin 		case 256:
1328c0341432SJohn Baldwin 			break;
1329c0341432SJohn Baldwin 		default:
1330c0341432SJohn Baldwin 			return (false);
1331c0341432SJohn Baldwin 		}
1332c0341432SJohn Baldwin 		if (csp->csp_auth_key == NULL)
1333c0341432SJohn Baldwin 			return (false);
1334c0341432SJohn Baldwin 		if (csp->csp_ivlen != AES_GCM_IV_LEN)
1335c0341432SJohn Baldwin 			return (false);
1336c0341432SJohn Baldwin 		break;
133725b7033bSConrad Meyer 	case CRYPTO_POLY1305:
1338c0341432SJohn Baldwin 		if (csp->csp_auth_klen != POLY1305_KEY_LEN)
1339c0341432SJohn Baldwin 			return (false);
1340c0341432SJohn Baldwin 		break;
1341c0341432SJohn Baldwin 	case CRYPTO_AES_CCM_CBC_MAC:
1342c0341432SJohn Baldwin 		switch (csp->csp_auth_klen * 8) {
1343c0341432SJohn Baldwin 		case 128:
1344c0341432SJohn Baldwin 		case 192:
1345c0341432SJohn Baldwin 		case 256:
1346c0341432SJohn Baldwin 			break;
1347c0341432SJohn Baldwin 		default:
1348c0341432SJohn Baldwin 			return (false);
1349c0341432SJohn Baldwin 		}
1350c0341432SJohn Baldwin 		if (csp->csp_auth_key == NULL)
1351c0341432SJohn Baldwin 			return (false);
1352c0341432SJohn Baldwin 		break;
1353c0341432SJohn Baldwin 	}
1354c0341432SJohn Baldwin 	return (true);
1355c0341432SJohn Baldwin }
1356091d81d1SSam Leffler 
1357c0341432SJohn Baldwin static bool
1358c0341432SJohn Baldwin swcr_cipher_supported(const struct crypto_session_params *csp)
1359c0341432SJohn Baldwin {
1360d8787d4fSMark Johnston 	const struct enc_xform *txf;
1361c0341432SJohn Baldwin 
1362c0341432SJohn Baldwin 	txf = crypto_cipher(csp);
1363c0341432SJohn Baldwin 	if (txf == NULL)
1364c0341432SJohn Baldwin 		return (false);
1365c0341432SJohn Baldwin 	if (csp->csp_cipher_alg != CRYPTO_NULL_CBC &&
1366c0341432SJohn Baldwin 	    txf->ivsize != csp->csp_ivlen)
1367c0341432SJohn Baldwin 		return (false);
1368c0341432SJohn Baldwin 	return (true);
1369c0341432SJohn Baldwin }
1370c0341432SJohn Baldwin 
13716038018aSMarcin Wojtas #define SUPPORTED_SES (CSP_F_SEPARATE_OUTPUT | CSP_F_SEPARATE_AAD | CSP_F_ESN)
13726038018aSMarcin Wojtas 
1373c0341432SJohn Baldwin static int
1374c0341432SJohn Baldwin swcr_probesession(device_t dev, const struct crypto_session_params *csp)
1375c0341432SJohn Baldwin {
13766038018aSMarcin Wojtas 	if ((csp->csp_flags & ~(SUPPORTED_SES)) != 0)
1377c0341432SJohn Baldwin 		return (EINVAL);
1378c0341432SJohn Baldwin 	switch (csp->csp_mode) {
1379c0341432SJohn Baldwin 	case CSP_MODE_COMPRESS:
1380c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1381c0341432SJohn Baldwin 		case CRYPTO_DEFLATE_COMP:
1382c0341432SJohn Baldwin 			break;
1383c0341432SJohn Baldwin 		default:
1384c0341432SJohn Baldwin 			return (EINVAL);
13855fbc5b5aSConrad Meyer 		}
1386091d81d1SSam Leffler 		break;
1387c0341432SJohn Baldwin 	case CSP_MODE_CIPHER:
1388c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1389c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1390c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1391dd2e1352SJohn Baldwin 		case CRYPTO_CHACHA20_POLY1305:
13928f35841fSJohn Baldwin 		case CRYPTO_XCHACHA20_POLY1305:
1393c0341432SJohn Baldwin 			return (EINVAL);
1394c0341432SJohn Baldwin 		default:
1395c0341432SJohn Baldwin 			if (!swcr_cipher_supported(csp))
1396c0341432SJohn Baldwin 				return (EINVAL);
1397091d81d1SSam Leffler 			break;
1398091d81d1SSam Leffler 		}
1399c0341432SJohn Baldwin 		break;
1400c0341432SJohn Baldwin 	case CSP_MODE_DIGEST:
1401c0341432SJohn Baldwin 		if (!swcr_auth_supported(csp))
1402c0341432SJohn Baldwin 			return (EINVAL);
1403c0341432SJohn Baldwin 		break;
1404c0341432SJohn Baldwin 	case CSP_MODE_AEAD:
1405c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1406c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1407c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1408c172a407SJohn Baldwin 			switch (csp->csp_cipher_klen * 8) {
1409c172a407SJohn Baldwin 			case 128:
1410c172a407SJohn Baldwin 			case 192:
1411c172a407SJohn Baldwin 			case 256:
1412c172a407SJohn Baldwin 				break;
1413c172a407SJohn Baldwin 			default:
1414c172a407SJohn Baldwin 				return (EINVAL);
1415c172a407SJohn Baldwin 			}
1416c172a407SJohn Baldwin 			break;
1417dd2e1352SJohn Baldwin 		case CRYPTO_CHACHA20_POLY1305:
14188f35841fSJohn Baldwin 		case CRYPTO_XCHACHA20_POLY1305:
1419c0341432SJohn Baldwin 			break;
1420c0341432SJohn Baldwin 		default:
1421c0341432SJohn Baldwin 			return (EINVAL);
1422c0341432SJohn Baldwin 		}
1423c0341432SJohn Baldwin 		break;
1424c0341432SJohn Baldwin 	case CSP_MODE_ETA:
1425c0341432SJohn Baldwin 		/* AEAD algorithms cannot be used for EtA. */
1426c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1427c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1428c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1429dd2e1352SJohn Baldwin 		case CRYPTO_CHACHA20_POLY1305:
14308f35841fSJohn Baldwin 		case CRYPTO_XCHACHA20_POLY1305:
1431c0341432SJohn Baldwin 			return (EINVAL);
1432c0341432SJohn Baldwin 		}
1433c0341432SJohn Baldwin 		switch (csp->csp_auth_alg) {
1434c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GMAC:
1435c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_CBC_MAC:
1436c0341432SJohn Baldwin 			return (EINVAL);
1437c0341432SJohn Baldwin 		}
1438c0341432SJohn Baldwin 
1439c0341432SJohn Baldwin 		if (!swcr_cipher_supported(csp) ||
1440c0341432SJohn Baldwin 		    !swcr_auth_supported(csp))
1441c0341432SJohn Baldwin 			return (EINVAL);
1442c0341432SJohn Baldwin 		break;
1443c0341432SJohn Baldwin 	default:
1444c0341432SJohn Baldwin 		return (EINVAL);
1445c0341432SJohn Baldwin 	}
1446c0341432SJohn Baldwin 
1447c0341432SJohn Baldwin 	return (CRYPTODEV_PROBE_SOFTWARE);
1448c0341432SJohn Baldwin }
1449c0341432SJohn Baldwin 
1450c0341432SJohn Baldwin /*
1451c0341432SJohn Baldwin  * Generate a new software session.
1452c0341432SJohn Baldwin  */
1453c0341432SJohn Baldwin static int
1454c0341432SJohn Baldwin swcr_newsession(device_t dev, crypto_session_t cses,
1455c0341432SJohn Baldwin     const struct crypto_session_params *csp)
1456c0341432SJohn Baldwin {
1457c0341432SJohn Baldwin 	struct swcr_session *ses;
1458d8787d4fSMark Johnston 	const struct comp_algo *cxf;
1459c0341432SJohn Baldwin 	int error;
1460c0341432SJohn Baldwin 
1461c0341432SJohn Baldwin 	ses = crypto_get_driver_session(cses);
1462c0341432SJohn Baldwin 
1463c0341432SJohn Baldwin 	error = 0;
1464c0341432SJohn Baldwin 	switch (csp->csp_mode) {
1465c0341432SJohn Baldwin 	case CSP_MODE_COMPRESS:
1466c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1467c0341432SJohn Baldwin 		case CRYPTO_DEFLATE_COMP:
1468c0341432SJohn Baldwin 			cxf = &comp_algo_deflate;
1469c0341432SJohn Baldwin 			break;
1470c0341432SJohn Baldwin #ifdef INVARIANTS
1471c0341432SJohn Baldwin 		default:
1472c0341432SJohn Baldwin 			panic("bad compression algo");
1473c0341432SJohn Baldwin #endif
1474c0341432SJohn Baldwin 		}
1475c0341432SJohn Baldwin 		ses->swcr_compdec.sw_cxf = cxf;
1476c0341432SJohn Baldwin 		ses->swcr_process = swcr_compdec;
1477c0341432SJohn Baldwin 		break;
1478c0341432SJohn Baldwin 	case CSP_MODE_CIPHER:
1479c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1480c0341432SJohn Baldwin 		case CRYPTO_NULL_CBC:
1481c0341432SJohn Baldwin 			ses->swcr_process = swcr_null;
1482c0341432SJohn Baldwin 			break;
1483c0341432SJohn Baldwin #ifdef INVARIANTS
1484c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1485c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1486dd2e1352SJohn Baldwin 		case CRYPTO_CHACHA20_POLY1305:
14878f35841fSJohn Baldwin 		case CRYPTO_XCHACHA20_POLY1305:
1488c0341432SJohn Baldwin 			panic("bad cipher algo");
1489c0341432SJohn Baldwin #endif
1490c0341432SJohn Baldwin 		default:
14913e947048SJohn Baldwin 			error = swcr_setup_cipher(ses, csp);
1492c0341432SJohn Baldwin 			if (error == 0)
1493c0341432SJohn Baldwin 				ses->swcr_process = swcr_encdec;
1494c0341432SJohn Baldwin 		}
1495c0341432SJohn Baldwin 		break;
1496c0341432SJohn Baldwin 	case CSP_MODE_DIGEST:
1497c0341432SJohn Baldwin 		error = swcr_setup_auth(ses, csp);
1498c0341432SJohn Baldwin 		break;
1499c0341432SJohn Baldwin 	case CSP_MODE_AEAD:
1500c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1501c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1502ab91fb6cSJohn Baldwin 			error = swcr_setup_aead(ses, csp);
1503c0341432SJohn Baldwin 			if (error == 0)
1504c0341432SJohn Baldwin 				ses->swcr_process = swcr_gcm;
1505c0341432SJohn Baldwin 			break;
1506c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1507ab91fb6cSJohn Baldwin 			error = swcr_setup_aead(ses, csp);
1508c0341432SJohn Baldwin 			if (error == 0)
1509c0341432SJohn Baldwin 				ses->swcr_process = swcr_ccm;
1510c0341432SJohn Baldwin 			break;
1511dd2e1352SJohn Baldwin 		case CRYPTO_CHACHA20_POLY1305:
15128f35841fSJohn Baldwin 		case CRYPTO_XCHACHA20_POLY1305:
1513ab91fb6cSJohn Baldwin 			error = swcr_setup_aead(ses, csp);
1514dd2e1352SJohn Baldwin 			if (error == 0)
1515dd2e1352SJohn Baldwin 				ses->swcr_process = swcr_chacha20_poly1305;
1516dd2e1352SJohn Baldwin 			break;
1517c0341432SJohn Baldwin #ifdef INVARIANTS
1518c0341432SJohn Baldwin 		default:
1519c0341432SJohn Baldwin 			panic("bad aead algo");
1520c0341432SJohn Baldwin #endif
1521c0341432SJohn Baldwin 		}
1522c0341432SJohn Baldwin 		break;
1523c0341432SJohn Baldwin 	case CSP_MODE_ETA:
1524c0341432SJohn Baldwin #ifdef INVARIANTS
1525c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1526c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1527c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1528dd2e1352SJohn Baldwin 		case CRYPTO_CHACHA20_POLY1305:
15298f35841fSJohn Baldwin 		case CRYPTO_XCHACHA20_POLY1305:
1530c0341432SJohn Baldwin 			panic("bad eta cipher algo");
1531c0341432SJohn Baldwin 		}
1532c0341432SJohn Baldwin 		switch (csp->csp_auth_alg) {
1533c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GMAC:
1534c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_CBC_MAC:
1535c0341432SJohn Baldwin 			panic("bad eta auth algo");
1536c0341432SJohn Baldwin 		}
1537c0341432SJohn Baldwin #endif
1538c0341432SJohn Baldwin 
1539c0341432SJohn Baldwin 		error = swcr_setup_auth(ses, csp);
1540c0341432SJohn Baldwin 		if (error)
1541c0341432SJohn Baldwin 			break;
1542c0341432SJohn Baldwin 		if (csp->csp_cipher_alg == CRYPTO_NULL_CBC) {
1543c0341432SJohn Baldwin 			/* Effectively degrade to digest mode. */
1544c0341432SJohn Baldwin 			ses->swcr_process = swcr_authcompute;
1545c0341432SJohn Baldwin 			break;
1546c0341432SJohn Baldwin 		}
1547c0341432SJohn Baldwin 
15483e947048SJohn Baldwin 		error = swcr_setup_cipher(ses, csp);
1549c0341432SJohn Baldwin 		if (error == 0)
1550c0341432SJohn Baldwin 			ses->swcr_process = swcr_eta;
1551c0341432SJohn Baldwin 		break;
1552c0341432SJohn Baldwin 	default:
1553c0341432SJohn Baldwin 		error = EINVAL;
1554c0341432SJohn Baldwin 	}
1555c0341432SJohn Baldwin 
1556c0341432SJohn Baldwin 	if (error)
1557c0341432SJohn Baldwin 		swcr_freesession(dev, cses);
1558c0341432SJohn Baldwin 	return (error);
1559c0341432SJohn Baldwin }
1560c0341432SJohn Baldwin 
1561c0341432SJohn Baldwin static void
1562c0341432SJohn Baldwin swcr_freesession(device_t dev, crypto_session_t cses)
1563c0341432SJohn Baldwin {
1564c0341432SJohn Baldwin 	struct swcr_session *ses;
1565c0341432SJohn Baldwin 
1566c0341432SJohn Baldwin 	ses = crypto_get_driver_session(cses);
1567c0341432SJohn Baldwin 
1568f313909aSJohn Baldwin 	zfree(ses->swcr_encdec.sw_ctx, M_CRYPTO_DATA);
15694a711b8dSJohn Baldwin 	zfree(ses->swcr_auth.sw_ictx, M_CRYPTO_DATA);
15704a711b8dSJohn Baldwin 	zfree(ses->swcr_auth.sw_octx, M_CRYPTO_DATA);
1571091d81d1SSam Leffler }
1572091d81d1SSam Leffler 
1573091d81d1SSam Leffler /*
1574091d81d1SSam Leffler  * Process a software request.
1575091d81d1SSam Leffler  */
1576091d81d1SSam Leffler static int
15776810ad6fSSam Leffler swcr_process(device_t dev, struct cryptop *crp, int hint)
1578091d81d1SSam Leffler {
1579c0341432SJohn Baldwin 	struct swcr_session *ses;
1580091d81d1SSam Leffler 
15811b0909d5SConrad Meyer 	ses = crypto_get_driver_session(crp->crp_session);
1582091d81d1SSam Leffler 
1583c0341432SJohn Baldwin 	crp->crp_etype = ses->swcr_process(ses, crp);
1584091d81d1SSam Leffler 
1585091d81d1SSam Leffler 	crypto_done(crp);
1586c0341432SJohn Baldwin 	return (0);
1587091d81d1SSam Leffler }
1588091d81d1SSam Leffler 
1589091d81d1SSam Leffler static void
15903f147ab2SWarner Losh swcr_identify(driver_t *drv, device_t parent)
1591091d81d1SSam Leffler {
15926810ad6fSSam Leffler 	/* NB: order 10 is so we get attached after h/w devices */
15936810ad6fSSam Leffler 	if (device_find_child(parent, "cryptosoft", -1) == NULL &&
159486c585d9SMarius Strobl 	    BUS_ADD_CHILD(parent, 10, "cryptosoft", 0) == 0)
15956810ad6fSSam Leffler 		panic("cryptosoft: could not attach");
15966810ad6fSSam Leffler }
1597f6c4bc3bSPawel Jakub Dawidek 
15986810ad6fSSam Leffler static int
15996810ad6fSSam Leffler swcr_probe(device_t dev)
16006810ad6fSSam Leffler {
16016810ad6fSSam Leffler 	device_set_desc(dev, "software crypto");
16024fc60fa9SMark Johnston 	device_quiet(dev);
160386c585d9SMarius Strobl 	return (BUS_PROBE_NOWILDCARD);
16046810ad6fSSam Leffler }
1605f6c4bc3bSPawel Jakub Dawidek 
16066810ad6fSSam Leffler static int
16076810ad6fSSam Leffler swcr_attach(device_t dev)
16086810ad6fSSam Leffler {
16096810ad6fSSam Leffler 
16109ebbebe4SConrad Meyer 	swcr_id = crypto_get_driverid(dev, sizeof(struct swcr_session),
16116810ad6fSSam Leffler 			CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC);
16126810ad6fSSam Leffler 	if (swcr_id < 0) {
16136810ad6fSSam Leffler 		device_printf(dev, "cannot initialize!");
1614c0341432SJohn Baldwin 		return (ENXIO);
16156810ad6fSSam Leffler 	}
16166810ad6fSSam Leffler 
1617c0341432SJohn Baldwin 	return (0);
1618091d81d1SSam Leffler }
16194b465da2SPawel Jakub Dawidek 
16203f147ab2SWarner Losh static int
16216810ad6fSSam Leffler swcr_detach(device_t dev)
16224b465da2SPawel Jakub Dawidek {
16236810ad6fSSam Leffler 	crypto_unregister_all(swcr_id);
16243f147ab2SWarner Losh 	return 0;
16254b465da2SPawel Jakub Dawidek }
16266810ad6fSSam Leffler 
16276810ad6fSSam Leffler static device_method_t swcr_methods[] = {
16286810ad6fSSam Leffler 	DEVMETHOD(device_identify,	swcr_identify),
16296810ad6fSSam Leffler 	DEVMETHOD(device_probe,		swcr_probe),
16306810ad6fSSam Leffler 	DEVMETHOD(device_attach,	swcr_attach),
16316810ad6fSSam Leffler 	DEVMETHOD(device_detach,	swcr_detach),
16326810ad6fSSam Leffler 
1633c0341432SJohn Baldwin 	DEVMETHOD(cryptodev_probesession, swcr_probesession),
16346810ad6fSSam Leffler 	DEVMETHOD(cryptodev_newsession,	swcr_newsession),
16356810ad6fSSam Leffler 	DEVMETHOD(cryptodev_freesession,swcr_freesession),
16366810ad6fSSam Leffler 	DEVMETHOD(cryptodev_process,	swcr_process),
16376810ad6fSSam Leffler 
16386810ad6fSSam Leffler 	{0, 0},
16396810ad6fSSam Leffler };
16406810ad6fSSam Leffler 
16416810ad6fSSam Leffler static driver_t swcr_driver = {
16426810ad6fSSam Leffler 	"cryptosoft",
16436810ad6fSSam Leffler 	swcr_methods,
16446810ad6fSSam Leffler 	0,		/* NB: no softc */
16456810ad6fSSam Leffler };
16466810ad6fSSam Leffler static devclass_t swcr_devclass;
16476810ad6fSSam Leffler 
16486810ad6fSSam Leffler /*
16496810ad6fSSam Leffler  * NB: We explicitly reference the crypto module so we
16506810ad6fSSam Leffler  * get the necessary ordering when built as a loadable
16516810ad6fSSam Leffler  * module.  This is required because we bundle the crypto
16526810ad6fSSam Leffler  * module code together with the cryptosoft driver (otherwise
16536810ad6fSSam Leffler  * normal module dependencies would handle things).
16546810ad6fSSam Leffler  */
16556810ad6fSSam Leffler extern int crypto_modevent(struct module *, int, void *);
16566810ad6fSSam Leffler /* XXX where to attach */
16576810ad6fSSam Leffler DRIVER_MODULE(cryptosoft, nexus, swcr_driver, swcr_devclass, crypto_modevent,0);
16586810ad6fSSam Leffler MODULE_VERSION(cryptosoft, 1);
16596810ad6fSSam Leffler MODULE_DEPEND(cryptosoft, crypto, 1, 1, 1);
1660