xref: /freebsd/sys/opencrypto/cryptosoft.c (revision 4361c4eb6e3620e68d005c1671fdbf60b1fe83c6)
1091d81d1SSam Leffler /*	$OpenBSD: cryptosoft.c,v 1.35 2002/04/26 08:43:50 deraadt Exp $	*/
2091d81d1SSam Leffler 
360727d8bSWarner Losh /*-
4091d81d1SSam Leffler  * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
56810ad6fSSam Leffler  * Copyright (c) 2002-2006 Sam Leffler, Errno Consulting
6091d81d1SSam Leffler  *
7091d81d1SSam Leffler  * This code was written by Angelos D. Keromytis in Athens, Greece, in
8091d81d1SSam Leffler  * February 2000. Network Security Technologies Inc. (NSTI) kindly
9091d81d1SSam Leffler  * supported the development of this code.
10091d81d1SSam Leffler  *
11091d81d1SSam Leffler  * Copyright (c) 2000, 2001 Angelos D. Keromytis
121833d604SJohn Baldwin  * Copyright (c) 2014-2021 The FreeBSD Foundation
1308fca7a5SJohn-Mark Gurney  * All rights reserved.
1408fca7a5SJohn-Mark Gurney  *
1508fca7a5SJohn-Mark Gurney  * Portions of this software were developed by John-Mark Gurney
1608fca7a5SJohn-Mark Gurney  * under sponsorship of the FreeBSD Foundation and
1708fca7a5SJohn-Mark Gurney  * Rubicon Communications, LLC (Netgate).
18091d81d1SSam Leffler  *
191833d604SJohn Baldwin  * Portions of this software were developed by Ararat River
201833d604SJohn Baldwin  * Consulting, LLC under sponsorship of the FreeBSD Foundation.
211833d604SJohn Baldwin  *
22091d81d1SSam Leffler  * Permission to use, copy, and modify this software with or without fee
23091d81d1SSam Leffler  * is hereby granted, provided that this entire notice is included in
24091d81d1SSam Leffler  * all source code copies of any software which is or includes a copy or
25091d81d1SSam Leffler  * modification of this software.
26091d81d1SSam Leffler  *
27091d81d1SSam Leffler  * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
28091d81d1SSam Leffler  * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
29091d81d1SSam Leffler  * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
30091d81d1SSam Leffler  * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
31091d81d1SSam Leffler  * PURPOSE.
32091d81d1SSam Leffler  */
33091d81d1SSam Leffler 
342c446514SDavid E. O'Brien #include <sys/cdefs.h>
352c446514SDavid E. O'Brien __FBSDID("$FreeBSD$");
362c446514SDavid E. O'Brien 
37091d81d1SSam Leffler #include <sys/param.h>
38091d81d1SSam Leffler #include <sys/systm.h>
39091d81d1SSam Leffler #include <sys/malloc.h>
40091d81d1SSam Leffler #include <sys/mbuf.h>
416810ad6fSSam Leffler #include <sys/module.h>
42091d81d1SSam Leffler #include <sys/sysctl.h>
43091d81d1SSam Leffler #include <sys/errno.h>
44091d81d1SSam Leffler #include <sys/random.h>
45091d81d1SSam Leffler #include <sys/kernel.h>
46091d81d1SSam Leffler #include <sys/uio.h>
47109919c6SBenno Rice #include <sys/lock.h>
48109919c6SBenno Rice #include <sys/rwlock.h>
4908fca7a5SJohn-Mark Gurney #include <sys/endian.h>
5008fca7a5SJohn-Mark Gurney #include <sys/limits.h>
51a7fcb1afSSean Eric Fagan #include <sys/mutex.h>
52091d81d1SSam Leffler 
53091d81d1SSam Leffler #include <crypto/sha1.h>
54091d81d1SSam Leffler #include <opencrypto/rmd160.h>
55091d81d1SSam Leffler 
56091d81d1SSam Leffler #include <opencrypto/cryptodev.h>
57091d81d1SSam Leffler #include <opencrypto/xform.h>
58091d81d1SSam Leffler 
596810ad6fSSam Leffler #include <sys/kobj.h>
606810ad6fSSam Leffler #include <sys/bus.h>
616810ad6fSSam Leffler #include "cryptodev_if.h"
62091d81d1SSam Leffler 
63c0341432SJohn Baldwin struct swcr_auth {
64c0341432SJohn Baldwin 	void		*sw_ictx;
65c0341432SJohn Baldwin 	void		*sw_octx;
66d8787d4fSMark Johnston 	const struct auth_hash *sw_axf;
67c0341432SJohn Baldwin 	uint16_t	sw_mlen;
68c0341432SJohn Baldwin };
69c0341432SJohn Baldwin 
70c0341432SJohn Baldwin struct swcr_encdec {
713e947048SJohn Baldwin 	void		*sw_kschedule;
72d8787d4fSMark Johnston 	const struct enc_xform *sw_exf;
73c0341432SJohn Baldwin };
74c0341432SJohn Baldwin 
75c0341432SJohn Baldwin struct swcr_compdec {
76d8787d4fSMark Johnston 	const struct comp_algo *sw_cxf;
77c0341432SJohn Baldwin };
78c0341432SJohn Baldwin 
79c0341432SJohn Baldwin struct swcr_session {
80c0341432SJohn Baldwin 	struct mtx	swcr_lock;
81c0341432SJohn Baldwin 	int	(*swcr_process)(struct swcr_session *, struct cryptop *);
82c0341432SJohn Baldwin 
83c0341432SJohn Baldwin 	struct swcr_auth swcr_auth;
84c0341432SJohn Baldwin 	struct swcr_encdec swcr_encdec;
85c0341432SJohn Baldwin 	struct swcr_compdec swcr_compdec;
86c0341432SJohn Baldwin };
87507281e5SSean Eric Fagan 
886810ad6fSSam Leffler static	int32_t swcr_id;
896810ad6fSSam Leffler 
901b0909d5SConrad Meyer static	void swcr_freesession(device_t dev, crypto_session_t cses);
91091d81d1SSam Leffler 
92c0341432SJohn Baldwin /* Used for CRYPTO_NULL_CBC. */
93c0341432SJohn Baldwin static int
94c0341432SJohn Baldwin swcr_null(struct swcr_session *ses, struct cryptop *crp)
95c0341432SJohn Baldwin {
96c0341432SJohn Baldwin 
97c0341432SJohn Baldwin 	return (0);
98c0341432SJohn Baldwin }
99c0341432SJohn Baldwin 
100091d81d1SSam Leffler /*
101091d81d1SSam Leffler  * Apply a symmetric encryption/decryption algorithm.
102091d81d1SSam Leffler  */
103091d81d1SSam Leffler static int
104c0341432SJohn Baldwin swcr_encdec(struct swcr_session *ses, struct cryptop *crp)
105091d81d1SSam Leffler {
1065d7ae54aSConrad Meyer 	unsigned char iv[EALG_MAX_BLOCK_LEN], blk[EALG_MAX_BLOCK_LEN];
10708fca7a5SJohn-Mark Gurney 	unsigned char *ivp, *nivp, iv2[EALG_MAX_BLOCK_LEN];
108c0341432SJohn Baldwin 	const struct crypto_session_params *csp;
109d8787d4fSMark Johnston 	const struct enc_xform *exf;
110c0341432SJohn Baldwin 	struct swcr_encdec *sw;
11186be314dSJohn Baldwin 	size_t inlen, outlen;
1121833d604SJohn Baldwin 	int i, blks, resid;
1139c0e3d3aSJohn Baldwin 	struct crypto_buffer_cursor cc_in, cc_out;
11426d292d3SJohn Baldwin 	const unsigned char *inblk;
11526d292d3SJohn Baldwin 	unsigned char *outblk;
11608fca7a5SJohn-Mark Gurney 	int error;
117c0341432SJohn Baldwin 	bool encrypting;
11808fca7a5SJohn-Mark Gurney 
11908fca7a5SJohn-Mark Gurney 	error = 0;
120091d81d1SSam Leffler 
121c0341432SJohn Baldwin 	sw = &ses->swcr_encdec;
122091d81d1SSam Leffler 	exf = sw->sw_exf;
1231833d604SJohn Baldwin 	csp = crypto_get_params(crp->crp_session);
124091d81d1SSam Leffler 
125723d8764SJohn Baldwin 	if (exf->native_blocksize == 0) {
126091d81d1SSam Leffler 		/* Check for non-padded data */
127723d8764SJohn Baldwin 		if ((crp->crp_payload_length % exf->blocksize) != 0)
128723d8764SJohn Baldwin 			return (EINVAL);
129723d8764SJohn Baldwin 
130723d8764SJohn Baldwin 		blks = exf->blocksize;
131723d8764SJohn Baldwin 	} else
132723d8764SJohn Baldwin 		blks = exf->native_blocksize;
133091d81d1SSam Leffler 
134c0341432SJohn Baldwin 	if (exf == &enc_xform_aes_icm &&
135c0341432SJohn Baldwin 	    (crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0)
13608fca7a5SJohn-Mark Gurney 		return (EINVAL);
13708fca7a5SJohn-Mark Gurney 
138c0341432SJohn Baldwin 	if (crp->crp_cipher_key != NULL) {
1393e947048SJohn Baldwin 		error = exf->setkey(sw->sw_kschedule,
140c0341432SJohn Baldwin 		    crp->crp_cipher_key, csp->csp_cipher_klen);
141c740ae4bSPoul-Henning Kamp 		if (error)
142c740ae4bSPoul-Henning Kamp 			return (error);
143c740ae4bSPoul-Henning Kamp 	}
144d295bdeeSPawel Jakub Dawidek 
14520c128daSJohn Baldwin 	crypto_read_iv(crp, iv);
14620c128daSJohn Baldwin 
14708fca7a5SJohn-Mark Gurney 	if (exf->reinit) {
148d295bdeeSPawel Jakub Dawidek 		/*
149d295bdeeSPawel Jakub Dawidek 		 * xforms that provide a reinit method perform all IV
150d295bdeeSPawel Jakub Dawidek 		 * handling themselves.
151d295bdeeSPawel Jakub Dawidek 		 */
1521833d604SJohn Baldwin 		exf->reinit(sw->sw_kschedule, iv, csp->csp_ivlen);
153091d81d1SSam Leffler 	}
154091d81d1SSam Leffler 
1559c0e3d3aSJohn Baldwin 	ivp = iv;
156091d81d1SSam Leffler 
1579c0e3d3aSJohn Baldwin 	crypto_cursor_init(&cc_in, &crp->crp_buf);
1589c0e3d3aSJohn Baldwin 	crypto_cursor_advance(&cc_in, crp->crp_payload_start);
15986be314dSJohn Baldwin 	inblk = crypto_cursor_segment(&cc_in, &inlen);
1609c0e3d3aSJohn Baldwin 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
1619c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_out, &crp->crp_obuf);
1629c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_out, crp->crp_payload_output_start);
1639c0e3d3aSJohn Baldwin 	} else
1649c0e3d3aSJohn Baldwin 		cc_out = cc_in;
16586be314dSJohn Baldwin 	outblk = crypto_cursor_segment(&cc_out, &outlen);
1669c0e3d3aSJohn Baldwin 
1679c0e3d3aSJohn Baldwin 	resid = crp->crp_payload_length;
168c0341432SJohn Baldwin 	encrypting = CRYPTO_OP_IS_ENCRYPT(crp->crp_op);
169091d81d1SSam Leffler 
170091d81d1SSam Leffler 	/*
1719c0e3d3aSJohn Baldwin 	 * Loop through encrypting blocks.  'inlen' is the remaining
1729c0e3d3aSJohn Baldwin 	 * length of the current segment in the input buffer.
1739c0e3d3aSJohn Baldwin 	 * 'outlen' is the remaining length of current segment in the
1749c0e3d3aSJohn Baldwin 	 * output buffer.
175091d81d1SSam Leffler 	 */
1769c0e3d3aSJohn Baldwin 	while (resid >= blks) {
1779c0e3d3aSJohn Baldwin 		/*
1789c0e3d3aSJohn Baldwin 		 * If the current block is not contained within the
1799c0e3d3aSJohn Baldwin 		 * current input/output segment, use 'blk' as a local
1809c0e3d3aSJohn Baldwin 		 * buffer.
1819c0e3d3aSJohn Baldwin 		 */
1829c0e3d3aSJohn Baldwin 		if (inlen < blks) {
1839c0e3d3aSJohn Baldwin 			crypto_cursor_copydata(&cc_in, blks, blk);
1849c0e3d3aSJohn Baldwin 			inblk = blk;
185d295bdeeSPawel Jakub Dawidek 		}
1869c0e3d3aSJohn Baldwin 		if (outlen < blks)
1879c0e3d3aSJohn Baldwin 			outblk = blk;
1889c0e3d3aSJohn Baldwin 
1899c0e3d3aSJohn Baldwin 		/*
1909c0e3d3aSJohn Baldwin 		 * Ciphers without a 'reinit' hook are assumed to be
1919c0e3d3aSJohn Baldwin 		 * used in CBC mode where the chaining is done here.
1929c0e3d3aSJohn Baldwin 		 */
1939c0e3d3aSJohn Baldwin 		if (exf->reinit != NULL) {
1949c0e3d3aSJohn Baldwin 			if (encrypting)
1959c0e3d3aSJohn Baldwin 				exf->encrypt(sw->sw_kschedule, inblk, outblk);
1969c0e3d3aSJohn Baldwin 			else
1979c0e3d3aSJohn Baldwin 				exf->decrypt(sw->sw_kschedule, inblk, outblk);
198c0341432SJohn Baldwin 		} else if (encrypting) {
199091d81d1SSam Leffler 			/* XOR with previous block */
2009c0e3d3aSJohn Baldwin 			for (i = 0; i < blks; i++)
2019c0e3d3aSJohn Baldwin 				outblk[i] = inblk[i] ^ ivp[i];
202091d81d1SSam Leffler 
2039c0e3d3aSJohn Baldwin 			exf->encrypt(sw->sw_kschedule, outblk, outblk);
204091d81d1SSam Leffler 
205091d81d1SSam Leffler 			/*
206091d81d1SSam Leffler 			 * Keep encrypted block for XOR'ing
207091d81d1SSam Leffler 			 * with next block
208091d81d1SSam Leffler 			 */
2099c0e3d3aSJohn Baldwin 			memcpy(iv, outblk, blks);
210091d81d1SSam Leffler 			ivp = iv;
211091d81d1SSam Leffler 		} else {	/* decrypt */
212091d81d1SSam Leffler 			/*
213091d81d1SSam Leffler 			 * Keep encrypted block for XOR'ing
214091d81d1SSam Leffler 			 * with next block
215091d81d1SSam Leffler 			 */
21608fca7a5SJohn-Mark Gurney 			nivp = (ivp == iv) ? iv2 : iv;
2179c0e3d3aSJohn Baldwin 			memcpy(nivp, inblk, blks);
218091d81d1SSam Leffler 
2199c0e3d3aSJohn Baldwin 			exf->decrypt(sw->sw_kschedule, inblk, outblk);
220091d81d1SSam Leffler 
221091d81d1SSam Leffler 			/* XOR with previous block */
2229c0e3d3aSJohn Baldwin 			for (i = 0; i < blks; i++)
2239c0e3d3aSJohn Baldwin 				outblk[i] ^= ivp[i];
224091d81d1SSam Leffler 
22508fca7a5SJohn-Mark Gurney 			ivp = nivp;
226091d81d1SSam Leffler 		}
227091d81d1SSam Leffler 
2289c0e3d3aSJohn Baldwin 		if (inlen < blks) {
22986be314dSJohn Baldwin 			inblk = crypto_cursor_segment(&cc_in, &inlen);
2309c0e3d3aSJohn Baldwin 		} else {
2319c0e3d3aSJohn Baldwin 			crypto_cursor_advance(&cc_in, blks);
2329c0e3d3aSJohn Baldwin 			inlen -= blks;
2339c0e3d3aSJohn Baldwin 			inblk += blks;
23408fca7a5SJohn-Mark Gurney 		}
235091d81d1SSam Leffler 
2369c0e3d3aSJohn Baldwin 		if (outlen < blks) {
2379c0e3d3aSJohn Baldwin 			crypto_cursor_copyback(&cc_out, blks, blk);
23886be314dSJohn Baldwin 			outblk = crypto_cursor_segment(&cc_out, &outlen);
2399c0e3d3aSJohn Baldwin 		} else {
2409c0e3d3aSJohn Baldwin 			crypto_cursor_advance(&cc_out, blks);
2419c0e3d3aSJohn Baldwin 			outlen -= blks;
2429c0e3d3aSJohn Baldwin 			outblk += blks;
243091d81d1SSam Leffler 		}
244091d81d1SSam Leffler 
2459c0e3d3aSJohn Baldwin 		resid -= blks;
246f34a967bSPawel Jakub Dawidek 	}
247f34a967bSPawel Jakub Dawidek 
248723d8764SJohn Baldwin 	/* Handle trailing partial block for stream ciphers. */
2499c0e3d3aSJohn Baldwin 	if (resid > 0) {
250723d8764SJohn Baldwin 		KASSERT(exf->native_blocksize != 0,
251723d8764SJohn Baldwin 		    ("%s: partial block of %d bytes for cipher %s",
252723d8764SJohn Baldwin 		    __func__, i, exf->name));
253723d8764SJohn Baldwin 		KASSERT(exf->reinit != NULL,
254723d8764SJohn Baldwin 		    ("%s: partial block cipher %s without reinit hook",
255723d8764SJohn Baldwin 		    __func__, exf->name));
2569c0e3d3aSJohn Baldwin 		KASSERT(resid < blks, ("%s: partial block too big", __func__));
257723d8764SJohn Baldwin 
25886be314dSJohn Baldwin 		inblk = crypto_cursor_segment(&cc_in, &inlen);
25986be314dSJohn Baldwin 		outblk = crypto_cursor_segment(&cc_out, &outlen);
2609c0e3d3aSJohn Baldwin 		if (inlen < resid) {
2619c0e3d3aSJohn Baldwin 			crypto_cursor_copydata(&cc_in, resid, blk);
2629c0e3d3aSJohn Baldwin 			inblk = blk;
26386be314dSJohn Baldwin 		}
2649c0e3d3aSJohn Baldwin 		if (outlen < resid)
2659c0e3d3aSJohn Baldwin 			outblk = blk;
2669c0e3d3aSJohn Baldwin 		if (encrypting)
2679c0e3d3aSJohn Baldwin 			exf->encrypt_last(sw->sw_kschedule, inblk, outblk,
2689c0e3d3aSJohn Baldwin 			    resid);
2699c0e3d3aSJohn Baldwin 		else
2709c0e3d3aSJohn Baldwin 			exf->decrypt_last(sw->sw_kschedule, inblk, outblk,
2719c0e3d3aSJohn Baldwin 			    resid);
2729c0e3d3aSJohn Baldwin 		if (outlen < resid)
2739c0e3d3aSJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
274723d8764SJohn Baldwin 	}
275723d8764SJohn Baldwin 
27620c128daSJohn Baldwin 	explicit_bzero(blk, sizeof(blk));
27720c128daSJohn Baldwin 	explicit_bzero(iv, sizeof(iv));
27820c128daSJohn Baldwin 	explicit_bzero(iv2, sizeof(iv2));
2799c0e3d3aSJohn Baldwin 	return (0);
280091d81d1SSam Leffler }
281091d81d1SSam Leffler 
282c0341432SJohn Baldwin static void
283d8787d4fSMark Johnston swcr_authprepare(const struct auth_hash *axf, struct swcr_auth *sw,
284c0341432SJohn Baldwin     const uint8_t *key, int klen)
285f6c4bc3bSPawel Jakub Dawidek {
286f6c4bc3bSPawel Jakub Dawidek 
287f6c4bc3bSPawel Jakub Dawidek 	switch (axf->type) {
288f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA1_HMAC:
289c97f39ceSConrad Meyer 	case CRYPTO_SHA2_224_HMAC:
290f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_256_HMAC:
291f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_384_HMAC:
292f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_512_HMAC:
293f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_NULL_HMAC:
294f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_RIPEMD160_HMAC:
295c0341432SJohn Baldwin 		hmac_init_ipad(axf, key, klen, sw->sw_ictx);
296c0341432SJohn Baldwin 		hmac_init_opad(axf, key, klen, sw->sw_octx);
297f6c4bc3bSPawel Jakub Dawidek 		break;
29825b7033bSConrad Meyer 	case CRYPTO_POLY1305:
2990e33efe4SConrad Meyer 	case CRYPTO_BLAKE2B:
3000e33efe4SConrad Meyer 	case CRYPTO_BLAKE2S:
3010e33efe4SConrad Meyer 		axf->Setkey(sw->sw_ictx, key, klen);
3020e33efe4SConrad Meyer 		axf->Init(sw->sw_ictx);
3030e33efe4SConrad Meyer 		break;
304f6c4bc3bSPawel Jakub Dawidek 	default:
305c0341432SJohn Baldwin 		panic("%s: algorithm %d doesn't use keys", __func__, axf->type);
306f6c4bc3bSPawel Jakub Dawidek 	}
307f6c4bc3bSPawel Jakub Dawidek }
308f6c4bc3bSPawel Jakub Dawidek 
309091d81d1SSam Leffler /*
310c0341432SJohn Baldwin  * Compute or verify hash.
311091d81d1SSam Leffler  */
312091d81d1SSam Leffler static int
313c0341432SJohn Baldwin swcr_authcompute(struct swcr_session *ses, struct cryptop *crp)
314091d81d1SSam Leffler {
315c0341432SJohn Baldwin 	u_char aalg[HASH_MAX_LEN];
316c0341432SJohn Baldwin 	const struct crypto_session_params *csp;
317c0341432SJohn Baldwin 	struct swcr_auth *sw;
318d8787d4fSMark Johnston 	const struct auth_hash *axf;
319091d81d1SSam Leffler 	union authctx ctx;
320091d81d1SSam Leffler 	int err;
321091d81d1SSam Leffler 
322c0341432SJohn Baldwin 	sw = &ses->swcr_auth;
323091d81d1SSam Leffler 
324091d81d1SSam Leffler 	axf = sw->sw_axf;
325091d81d1SSam Leffler 
326c0341432SJohn Baldwin 	csp = crypto_get_params(crp->crp_session);
3276038018aSMarcin Wojtas 	if (crp->crp_auth_key != NULL) {
328c0341432SJohn Baldwin 		swcr_authprepare(axf, sw, crp->crp_auth_key,
329c0341432SJohn Baldwin 		    csp->csp_auth_klen);
33025b7033bSConrad Meyer 	}
331f6c4bc3bSPawel Jakub Dawidek 
332091d81d1SSam Leffler 	bcopy(sw->sw_ictx, &ctx, axf->ctxsize);
333091d81d1SSam Leffler 
3349b774dc0SJohn Baldwin 	if (crp->crp_aad != NULL)
3359b774dc0SJohn Baldwin 		err = axf->Update(&ctx, crp->crp_aad, crp->crp_aad_length);
3369b774dc0SJohn Baldwin 	else
337c0341432SJohn Baldwin 		err = crypto_apply(crp, crp->crp_aad_start, crp->crp_aad_length,
3389b6b2f86SJohn Baldwin 		    axf->Update, &ctx);
339091d81d1SSam Leffler 	if (err)
340e0b155feSJohn Baldwin 		goto out;
341091d81d1SSam Leffler 
3429c0e3d3aSJohn Baldwin 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp) &&
3439c0e3d3aSJohn Baldwin 	    CRYPTO_OP_IS_ENCRYPT(crp->crp_op))
3449c0e3d3aSJohn Baldwin 		err = crypto_apply_buf(&crp->crp_obuf,
3459c0e3d3aSJohn Baldwin 		    crp->crp_payload_output_start, crp->crp_payload_length,
3469b6b2f86SJohn Baldwin 		    axf->Update, &ctx);
3479c0e3d3aSJohn Baldwin 	else
3489c0e3d3aSJohn Baldwin 		err = crypto_apply(crp, crp->crp_payload_start,
3499b6b2f86SJohn Baldwin 		    crp->crp_payload_length, axf->Update, &ctx);
350c0341432SJohn Baldwin 	if (err)
351e0b155feSJohn Baldwin 		goto out;
352091d81d1SSam Leffler 
3536038018aSMarcin Wojtas 	if (csp->csp_flags & CSP_F_ESN)
3546038018aSMarcin Wojtas 		axf->Update(&ctx, crp->crp_esn, 4);
3556038018aSMarcin Wojtas 
356091d81d1SSam Leffler 	axf->Final(aalg, &ctx);
357e0b155feSJohn Baldwin 	if (sw->sw_octx != NULL) {
358091d81d1SSam Leffler 		bcopy(sw->sw_octx, &ctx, axf->ctxsize);
359091d81d1SSam Leffler 		axf->Update(&ctx, aalg, axf->hashsize);
360091d81d1SSam Leffler 		axf->Final(aalg, &ctx);
361091d81d1SSam Leffler 	}
362091d81d1SSam Leffler 
363c0341432SJohn Baldwin 	if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
36420c128daSJohn Baldwin 		u_char uaalg[HASH_MAX_LEN];
36520c128daSJohn Baldwin 
366c0341432SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, sw->sw_mlen, uaalg);
367c0341432SJohn Baldwin 		if (timingsafe_bcmp(aalg, uaalg, sw->sw_mlen) != 0)
36820c128daSJohn Baldwin 			err = EBADMSG;
36920c128daSJohn Baldwin 		explicit_bzero(uaalg, sizeof(uaalg));
370c0341432SJohn Baldwin 	} else {
371091d81d1SSam Leffler 		/* Inject the authentication data */
372c0341432SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, sw->sw_mlen, aalg);
373c0341432SJohn Baldwin 	}
37420c128daSJohn Baldwin 	explicit_bzero(aalg, sizeof(aalg));
375e0b155feSJohn Baldwin out:
376e0b155feSJohn Baldwin 	explicit_bzero(&ctx, sizeof(ctx));
37720c128daSJohn Baldwin 	return (err);
378091d81d1SSam Leffler }
379091d81d1SSam Leffler 
38008fca7a5SJohn-Mark Gurney CTASSERT(INT_MAX <= (1ll<<39) - 256);	/* GCM: plain text < 2^39-256 */
38108fca7a5SJohn-Mark Gurney CTASSERT(INT_MAX <= (uint64_t)-1);	/* GCM: associated data <= 2^64-1 */
38208fca7a5SJohn-Mark Gurney 
38308fca7a5SJohn-Mark Gurney static int
384c0341432SJohn Baldwin swcr_gmac(struct swcr_session *ses, struct cryptop *crp)
38508fca7a5SJohn-Mark Gurney {
38626d292d3SJohn Baldwin 	uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))];
38708fca7a5SJohn-Mark Gurney 	u_char *blk = (u_char *)blkbuf;
38826d292d3SJohn Baldwin 	u_char tag[GMAC_DIGEST_LEN];
38926d292d3SJohn Baldwin 	u_char iv[AES_BLOCK_LEN];
3909c0e3d3aSJohn Baldwin 	struct crypto_buffer_cursor cc;
39126d292d3SJohn Baldwin 	const u_char *inblk;
39208fca7a5SJohn-Mark Gurney 	union authctx ctx;
393c0341432SJohn Baldwin 	struct swcr_auth *swa;
394d8787d4fSMark Johnston 	const struct auth_hash *axf;
39508fca7a5SJohn-Mark Gurney 	uint32_t *blkp;
39686be314dSJohn Baldwin 	size_t len;
39786be314dSJohn Baldwin 	int blksz, error, ivlen, resid;
39808fca7a5SJohn-Mark Gurney 
399c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
40008fca7a5SJohn-Mark Gurney 	axf = swa->sw_axf;
401c0341432SJohn Baldwin 
40208fca7a5SJohn-Mark Gurney 	bcopy(swa->sw_ictx, &ctx, axf->ctxsize);
40326d292d3SJohn Baldwin 	blksz = GMAC_BLOCK_LEN;
40426d292d3SJohn Baldwin 	KASSERT(axf->blocksize == blksz, ("%s: axf block size mismatch",
40526d292d3SJohn Baldwin 	    __func__));
40608fca7a5SJohn-Mark Gurney 
40708fca7a5SJohn-Mark Gurney 	/* Initialize the IV */
408c0341432SJohn Baldwin 	ivlen = AES_GCM_IV_LEN;
40929fe41ddSJohn Baldwin 	crypto_read_iv(crp, iv);
41008fca7a5SJohn-Mark Gurney 
41108fca7a5SJohn-Mark Gurney 	axf->Reinit(&ctx, iv, ivlen);
4129c0e3d3aSJohn Baldwin 	crypto_cursor_init(&cc, &crp->crp_buf);
4139c0e3d3aSJohn Baldwin 	crypto_cursor_advance(&cc, crp->crp_payload_start);
41426d292d3SJohn Baldwin 	for (resid = crp->crp_payload_length; resid >= blksz; resid -= len) {
41586be314dSJohn Baldwin 		inblk = crypto_cursor_segment(&cc, &len);
41626d292d3SJohn Baldwin 		if (len >= blksz) {
41726d292d3SJohn Baldwin 			len = rounddown(MIN(len, resid), blksz);
41826d292d3SJohn Baldwin 			crypto_cursor_advance(&cc, len);
41926d292d3SJohn Baldwin 		} else {
42026d292d3SJohn Baldwin 			len = blksz;
4219c0e3d3aSJohn Baldwin 			crypto_cursor_copydata(&cc, len, blk);
42226d292d3SJohn Baldwin 			inblk = blk;
42326d292d3SJohn Baldwin 		}
42426d292d3SJohn Baldwin 		axf->Update(&ctx, inblk, len);
42526d292d3SJohn Baldwin 	}
42626d292d3SJohn Baldwin 	if (resid > 0) {
42726d292d3SJohn Baldwin 		memset(blk, 0, blksz);
42826d292d3SJohn Baldwin 		crypto_cursor_copydata(&cc, resid, blk);
42908fca7a5SJohn-Mark Gurney 		axf->Update(&ctx, blk, blksz);
43008fca7a5SJohn-Mark Gurney 	}
43108fca7a5SJohn-Mark Gurney 
43208fca7a5SJohn-Mark Gurney 	/* length block */
43326d292d3SJohn Baldwin 	memset(blk, 0, blksz);
43408fca7a5SJohn-Mark Gurney 	blkp = (uint32_t *)blk + 1;
435c0341432SJohn Baldwin 	*blkp = htobe32(crp->crp_payload_length * 8);
43608fca7a5SJohn-Mark Gurney 	axf->Update(&ctx, blk, blksz);
437c0341432SJohn Baldwin 
438c0341432SJohn Baldwin 	/* Finalize MAC */
43926d292d3SJohn Baldwin 	axf->Final(tag, &ctx);
440c0341432SJohn Baldwin 
44120c128daSJohn Baldwin 	error = 0;
442c0341432SJohn Baldwin 	if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
44326d292d3SJohn Baldwin 		u_char tag2[GMAC_DIGEST_LEN];
44420c128daSJohn Baldwin 
445c0341432SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen,
44626d292d3SJohn Baldwin 		    tag2);
44726d292d3SJohn Baldwin 		if (timingsafe_bcmp(tag, tag2, swa->sw_mlen) != 0)
44820c128daSJohn Baldwin 			error = EBADMSG;
44926d292d3SJohn Baldwin 		explicit_bzero(tag2, sizeof(tag2));
450c0341432SJohn Baldwin 	} else {
451c0341432SJohn Baldwin 		/* Inject the authentication data */
45226d292d3SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag);
453c0341432SJohn Baldwin 	}
45420c128daSJohn Baldwin 	explicit_bzero(blkbuf, sizeof(blkbuf));
45526d292d3SJohn Baldwin 	explicit_bzero(tag, sizeof(tag));
45620c128daSJohn Baldwin 	explicit_bzero(iv, sizeof(iv));
45720c128daSJohn Baldwin 	return (error);
458c0341432SJohn Baldwin }
459c0341432SJohn Baldwin 
460c0341432SJohn Baldwin static int
461c0341432SJohn Baldwin swcr_gcm(struct swcr_session *ses, struct cryptop *crp)
462c0341432SJohn Baldwin {
46326d292d3SJohn Baldwin 	uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))];
464c0341432SJohn Baldwin 	u_char *blk = (u_char *)blkbuf;
46526d292d3SJohn Baldwin 	u_char tag[GMAC_DIGEST_LEN];
4669c0e3d3aSJohn Baldwin 	struct crypto_buffer_cursor cc_in, cc_out;
46726d292d3SJohn Baldwin 	const u_char *inblk;
46826d292d3SJohn Baldwin 	u_char *outblk;
469c0341432SJohn Baldwin 	union authctx ctx;
470c0341432SJohn Baldwin 	struct swcr_auth *swa;
471c0341432SJohn Baldwin 	struct swcr_encdec *swe;
472d8787d4fSMark Johnston 	const struct auth_hash *axf;
473d8787d4fSMark Johnston 	const struct enc_xform *exf;
474c0341432SJohn Baldwin 	uint32_t *blkp;
47586be314dSJohn Baldwin 	size_t len;
47686be314dSJohn Baldwin 	int blksz, error, ivlen, r, resid;
477c0341432SJohn Baldwin 
478c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
479c0341432SJohn Baldwin 	axf = swa->sw_axf;
480c0341432SJohn Baldwin 
481c0341432SJohn Baldwin 	bcopy(swa->sw_ictx, &ctx, axf->ctxsize);
48226d292d3SJohn Baldwin 	blksz = GMAC_BLOCK_LEN;
48326d292d3SJohn Baldwin 	KASSERT(axf->blocksize == blksz, ("%s: axf block size mismatch",
48426d292d3SJohn Baldwin 	    __func__));
485c0341432SJohn Baldwin 
486c0341432SJohn Baldwin 	swe = &ses->swcr_encdec;
487c0341432SJohn Baldwin 	exf = swe->sw_exf;
488723d8764SJohn Baldwin 	KASSERT(axf->blocksize == exf->native_blocksize,
489723d8764SJohn Baldwin 	    ("%s: blocksize mismatch", __func__));
490c0341432SJohn Baldwin 
491c0341432SJohn Baldwin 	if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0)
492c0341432SJohn Baldwin 		return (EINVAL);
493c0341432SJohn Baldwin 
494c0341432SJohn Baldwin 	ivlen = AES_GCM_IV_LEN;
495c0341432SJohn Baldwin 
496c0341432SJohn Baldwin 	/* Supply MAC with IV */
4975ae5ed5bSJohn Baldwin 	axf->Reinit(&ctx, crp->crp_iv, ivlen);
498c0341432SJohn Baldwin 
499c0341432SJohn Baldwin 	/* Supply MAC with AAD */
5009b774dc0SJohn Baldwin 	if (crp->crp_aad != NULL) {
5019b774dc0SJohn Baldwin 		len = rounddown(crp->crp_aad_length, blksz);
5029b774dc0SJohn Baldwin 		if (len != 0)
5039b774dc0SJohn Baldwin 			axf->Update(&ctx, crp->crp_aad, len);
5049b774dc0SJohn Baldwin 		if (crp->crp_aad_length != len) {
5059b774dc0SJohn Baldwin 			memset(blk, 0, blksz);
5069b774dc0SJohn Baldwin 			memcpy(blk, (char *)crp->crp_aad + len,
5079b774dc0SJohn Baldwin 			    crp->crp_aad_length - len);
5089b774dc0SJohn Baldwin 			axf->Update(&ctx, blk, blksz);
5099b774dc0SJohn Baldwin 		}
5109b774dc0SJohn Baldwin 	} else {
5119c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_in, &crp->crp_buf);
5129c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_in, crp->crp_aad_start);
5139b774dc0SJohn Baldwin 		for (resid = crp->crp_aad_length; resid >= blksz;
5149b774dc0SJohn Baldwin 		     resid -= len) {
51586be314dSJohn Baldwin 			inblk = crypto_cursor_segment(&cc_in, &len);
51626d292d3SJohn Baldwin 			if (len >= blksz) {
51726d292d3SJohn Baldwin 				len = rounddown(MIN(len, resid), blksz);
51826d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_in, len);
51926d292d3SJohn Baldwin 			} else {
52026d292d3SJohn Baldwin 				len = blksz;
5219c0e3d3aSJohn Baldwin 				crypto_cursor_copydata(&cc_in, len, blk);
52226d292d3SJohn Baldwin 				inblk = blk;
52326d292d3SJohn Baldwin 			}
52426d292d3SJohn Baldwin 			axf->Update(&ctx, inblk, len);
52526d292d3SJohn Baldwin 		}
52626d292d3SJohn Baldwin 		if (resid > 0) {
52726d292d3SJohn Baldwin 			memset(blk, 0, blksz);
52826d292d3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, resid, blk);
529c0341432SJohn Baldwin 			axf->Update(&ctx, blk, blksz);
530c0341432SJohn Baldwin 		}
5319b774dc0SJohn Baldwin 	}
532c0341432SJohn Baldwin 
533a10020cfSJohn Baldwin 	if (crp->crp_cipher_key != NULL)
534a10020cfSJohn Baldwin 		exf->setkey(swe->sw_kschedule, crp->crp_cipher_key,
535a10020cfSJohn Baldwin 		    crypto_get_params(crp->crp_session)->csp_cipher_klen);
5365ae5ed5bSJohn Baldwin 	exf->reinit(swe->sw_kschedule, crp->crp_iv, ivlen);
537c0341432SJohn Baldwin 
538c0341432SJohn Baldwin 	/* Do encryption with MAC */
5399c0e3d3aSJohn Baldwin 	crypto_cursor_init(&cc_in, &crp->crp_buf);
5409c0e3d3aSJohn Baldwin 	crypto_cursor_advance(&cc_in, crp->crp_payload_start);
5419c0e3d3aSJohn Baldwin 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
5429c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_out, &crp->crp_obuf);
5439c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_out, crp->crp_payload_output_start);
5449c0e3d3aSJohn Baldwin 	} else
5459c0e3d3aSJohn Baldwin 		cc_out = cc_in;
54626d292d3SJohn Baldwin 	for (resid = crp->crp_payload_length; resid >= blksz; resid -= blksz) {
54786be314dSJohn Baldwin 		inblk = crypto_cursor_segment(&cc_in, &len);
54886be314dSJohn Baldwin 		if (len < blksz) {
54926d292d3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, blksz, blk);
55026d292d3SJohn Baldwin 			inblk = blk;
551c0341432SJohn Baldwin 		} else {
55226d292d3SJohn Baldwin 			crypto_cursor_advance(&cc_in, blksz);
553c0341432SJohn Baldwin 		}
55426d292d3SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
55586be314dSJohn Baldwin 			outblk = crypto_cursor_segment(&cc_out, &len);
55686be314dSJohn Baldwin 			if (len < blksz)
55726d292d3SJohn Baldwin 				outblk = blk;
55826d292d3SJohn Baldwin 			exf->encrypt(swe->sw_kschedule, inblk, outblk);
55926d292d3SJohn Baldwin 			axf->Update(&ctx, outblk, blksz);
56026d292d3SJohn Baldwin 			if (outblk == blk)
56126d292d3SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
56226d292d3SJohn Baldwin 			else
56326d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_out, blksz);
56426d292d3SJohn Baldwin 		} else {
56526d292d3SJohn Baldwin 			axf->Update(&ctx, inblk, blksz);
56626d292d3SJohn Baldwin 		}
56726d292d3SJohn Baldwin 	}
56826d292d3SJohn Baldwin 	if (resid > 0) {
56926d292d3SJohn Baldwin 		crypto_cursor_copydata(&cc_in, resid, blk);
57026d292d3SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
57126d292d3SJohn Baldwin 			exf->encrypt_last(swe->sw_kschedule, blk, blk, resid);
57226d292d3SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
57326d292d3SJohn Baldwin 		}
57426d292d3SJohn Baldwin 		axf->Update(&ctx, blk, resid);
575c0341432SJohn Baldwin 	}
576c0341432SJohn Baldwin 
577c0341432SJohn Baldwin 	/* length block */
57826d292d3SJohn Baldwin 	memset(blk, 0, blksz);
579c0341432SJohn Baldwin 	blkp = (uint32_t *)blk + 1;
580c0341432SJohn Baldwin 	*blkp = htobe32(crp->crp_aad_length * 8);
581c0341432SJohn Baldwin 	blkp = (uint32_t *)blk + 3;
582c0341432SJohn Baldwin 	*blkp = htobe32(crp->crp_payload_length * 8);
583c0341432SJohn Baldwin 	axf->Update(&ctx, blk, blksz);
584c0341432SJohn Baldwin 
585c0341432SJohn Baldwin 	/* Finalize MAC */
58626d292d3SJohn Baldwin 	axf->Final(tag, &ctx);
587c0341432SJohn Baldwin 
588c0341432SJohn Baldwin 	/* Validate tag */
58920c128daSJohn Baldwin 	error = 0;
590c0341432SJohn Baldwin 	if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
59126d292d3SJohn Baldwin 		u_char tag2[GMAC_DIGEST_LEN];
59220c128daSJohn Baldwin 
59326d292d3SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, tag2);
594c0341432SJohn Baldwin 
59526d292d3SJohn Baldwin 		r = timingsafe_bcmp(tag, tag2, swa->sw_mlen);
59626d292d3SJohn Baldwin 		explicit_bzero(tag2, sizeof(tag2));
59720c128daSJohn Baldwin 		if (r != 0) {
59820c128daSJohn Baldwin 			error = EBADMSG;
59920c128daSJohn Baldwin 			goto out;
60020c128daSJohn Baldwin 		}
601c0341432SJohn Baldwin 
602c0341432SJohn Baldwin 		/* tag matches, decrypt data */
6039c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_in, &crp->crp_buf);
6049c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_in, crp->crp_payload_start);
60526d292d3SJohn Baldwin 		for (resid = crp->crp_payload_length; resid > blksz;
60626d292d3SJohn Baldwin 		     resid -= blksz) {
60786be314dSJohn Baldwin 			inblk = crypto_cursor_segment(&cc_in, &len);
60886be314dSJohn Baldwin 			if (len < blksz) {
60926d292d3SJohn Baldwin 				crypto_cursor_copydata(&cc_in, blksz, blk);
61026d292d3SJohn Baldwin 				inblk = blk;
61186be314dSJohn Baldwin 			} else
61226d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_in, blksz);
61386be314dSJohn Baldwin 			outblk = crypto_cursor_segment(&cc_out, &len);
61486be314dSJohn Baldwin 			if (len < blksz)
61526d292d3SJohn Baldwin 				outblk = blk;
61626d292d3SJohn Baldwin 			exf->decrypt(swe->sw_kschedule, inblk, outblk);
61726d292d3SJohn Baldwin 			if (outblk == blk)
61826d292d3SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
61926d292d3SJohn Baldwin 			else
62026d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_out, blksz);
62126d292d3SJohn Baldwin 		}
62226d292d3SJohn Baldwin 		if (resid > 0) {
62326d292d3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, resid, blk);
62426d292d3SJohn Baldwin 			exf->decrypt_last(swe->sw_kschedule, blk, blk, resid);
62526d292d3SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
626c0341432SJohn Baldwin 		}
627c0341432SJohn Baldwin 	} else {
628c0341432SJohn Baldwin 		/* Inject the authentication data */
62926d292d3SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag);
630c0341432SJohn Baldwin 	}
631c0341432SJohn Baldwin 
63220c128daSJohn Baldwin out:
63320c128daSJohn Baldwin 	explicit_bzero(blkbuf, sizeof(blkbuf));
63426d292d3SJohn Baldwin 	explicit_bzero(tag, sizeof(tag));
63520c128daSJohn Baldwin 
63620c128daSJohn Baldwin 	return (error);
637c0341432SJohn Baldwin }
638c0341432SJohn Baldwin 
639*4361c4ebSJohn Baldwin static void
640*4361c4ebSJohn Baldwin build_ccm_b0(const char *nonce, u_int nonce_length, u_int aad_length,
641*4361c4ebSJohn Baldwin     u_int data_length, u_int tag_length, uint8_t *b0)
642*4361c4ebSJohn Baldwin {
643*4361c4ebSJohn Baldwin 	uint8_t *bp;
644*4361c4ebSJohn Baldwin 	uint8_t flags, L;
645*4361c4ebSJohn Baldwin 
646*4361c4ebSJohn Baldwin 	KASSERT(nonce_length >= 7 && nonce_length <= 13,
647*4361c4ebSJohn Baldwin 	    ("nonce_length must be between 7 and 13 bytes"));
648*4361c4ebSJohn Baldwin 
649*4361c4ebSJohn Baldwin 	/*
650*4361c4ebSJohn Baldwin 	 * Need to determine the L field value.  This is the number of
651*4361c4ebSJohn Baldwin 	 * bytes needed to specify the length of the message; the length
652*4361c4ebSJohn Baldwin 	 * is whatever is left in the 16 bytes after specifying flags and
653*4361c4ebSJohn Baldwin 	 * the nonce.
654*4361c4ebSJohn Baldwin 	 */
655*4361c4ebSJohn Baldwin 	L = 15 - nonce_length;
656*4361c4ebSJohn Baldwin 
657*4361c4ebSJohn Baldwin 	flags = ((aad_length > 0) << 6) +
658*4361c4ebSJohn Baldwin 	    (((tag_length - 2) / 2) << 3) +
659*4361c4ebSJohn Baldwin 	    L - 1;
660*4361c4ebSJohn Baldwin 
661*4361c4ebSJohn Baldwin 	/*
662*4361c4ebSJohn Baldwin 	 * Now we need to set up the first block, which has flags, nonce,
663*4361c4ebSJohn Baldwin 	 * and the message length.
664*4361c4ebSJohn Baldwin 	 */
665*4361c4ebSJohn Baldwin 	b0[0] = flags;
666*4361c4ebSJohn Baldwin 	memcpy(b0 + 1, nonce, nonce_length);
667*4361c4ebSJohn Baldwin 	bp = b0 + 1 + nonce_length;
668*4361c4ebSJohn Baldwin 
669*4361c4ebSJohn Baldwin 	/* Need to copy L' [aka L-1] bytes of data_length */
670*4361c4ebSJohn Baldwin 	for (uint8_t *dst = b0 + CCM_CBC_BLOCK_LEN - 1; dst >= bp; dst--) {
671*4361c4ebSJohn Baldwin 		*dst = data_length;
672*4361c4ebSJohn Baldwin 		data_length >>= 8;
673*4361c4ebSJohn Baldwin 	}
674*4361c4ebSJohn Baldwin }
675*4361c4ebSJohn Baldwin 
676*4361c4ebSJohn Baldwin /* NB: OCF only supports AAD lengths < 2^32. */
677*4361c4ebSJohn Baldwin static int
678*4361c4ebSJohn Baldwin build_ccm_aad_length(u_int aad_length, uint8_t *blk)
679*4361c4ebSJohn Baldwin {
680*4361c4ebSJohn Baldwin 	if (aad_length < ((1 << 16) - (1 << 8))) {
681*4361c4ebSJohn Baldwin 		be16enc(blk, aad_length);
682*4361c4ebSJohn Baldwin 		return (sizeof(uint16_t));
683*4361c4ebSJohn Baldwin 	} else {
684*4361c4ebSJohn Baldwin 		blk[0] = 0xff;
685*4361c4ebSJohn Baldwin 		blk[1] = 0xfe;
686*4361c4ebSJohn Baldwin 		be32enc(blk + 2, aad_length);
687*4361c4ebSJohn Baldwin 		return (2 + sizeof(uint32_t));
688*4361c4ebSJohn Baldwin 	}
689*4361c4ebSJohn Baldwin }
690*4361c4ebSJohn Baldwin 
691c0341432SJohn Baldwin static int
692c0341432SJohn Baldwin swcr_ccm_cbc_mac(struct swcr_session *ses, struct cryptop *crp)
693c0341432SJohn Baldwin {
69426d292d3SJohn Baldwin 	u_char iv[AES_BLOCK_LEN];
695*4361c4ebSJohn Baldwin 	u_char blk[CCM_CBC_BLOCK_LEN];
696*4361c4ebSJohn Baldwin 	u_char tag[AES_CBC_MAC_HASH_LEN];
697c0341432SJohn Baldwin 	union authctx ctx;
698ae18720dSJohn Baldwin 	const struct crypto_session_params *csp;
699c0341432SJohn Baldwin 	struct swcr_auth *swa;
700d8787d4fSMark Johnston 	const struct auth_hash *axf;
701*4361c4ebSJohn Baldwin 	int error, ivlen, len;
702c0341432SJohn Baldwin 
703ae18720dSJohn Baldwin 	csp = crypto_get_params(crp->crp_session);
704c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
705c0341432SJohn Baldwin 	axf = swa->sw_axf;
706c0341432SJohn Baldwin 
707c0341432SJohn Baldwin 	bcopy(swa->sw_ictx, &ctx, axf->ctxsize);
708c0341432SJohn Baldwin 
709c0341432SJohn Baldwin 	/* Initialize the IV */
710ae18720dSJohn Baldwin 	ivlen = csp->csp_ivlen;
71129fe41ddSJohn Baldwin 	crypto_read_iv(crp, iv);
712c0341432SJohn Baldwin 
713*4361c4ebSJohn Baldwin 	/* Supply MAC with IV */
714*4361c4ebSJohn Baldwin 	axf->Reinit(&ctx, crp->crp_iv, ivlen);
715c0341432SJohn Baldwin 
716*4361c4ebSJohn Baldwin 	/* Supply MAC with b0. */
717*4361c4ebSJohn Baldwin 	build_ccm_b0(crp->crp_iv, ivlen, crp->crp_payload_length, 0,
718*4361c4ebSJohn Baldwin 	    swa->sw_mlen, blk);
719*4361c4ebSJohn Baldwin 	axf->Update(&ctx, blk, CCM_CBC_BLOCK_LEN);
720*4361c4ebSJohn Baldwin 
721*4361c4ebSJohn Baldwin 	len = build_ccm_aad_length(crp->crp_payload_length, blk);
722*4361c4ebSJohn Baldwin 	axf->Update(&ctx, blk, len);
723*4361c4ebSJohn Baldwin 
724*4361c4ebSJohn Baldwin 	crypto_apply(crp, crp->crp_payload_start, crp->crp_payload_length,
725*4361c4ebSJohn Baldwin 	    axf->Update, &ctx);
726c0341432SJohn Baldwin 
727c0341432SJohn Baldwin 	/* Finalize MAC */
72826d292d3SJohn Baldwin 	axf->Final(tag, &ctx);
729c0341432SJohn Baldwin 
730*4361c4ebSJohn Baldwin 	error = 0;
731c0341432SJohn Baldwin 	if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
73226d292d3SJohn Baldwin 		u_char tag2[AES_CBC_MAC_HASH_LEN];
73320c128daSJohn Baldwin 
734c0341432SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen,
73526d292d3SJohn Baldwin 		    tag2);
73626d292d3SJohn Baldwin 		if (timingsafe_bcmp(tag, tag2, swa->sw_mlen) != 0)
73720c128daSJohn Baldwin 			error = EBADMSG;
73826d292d3SJohn Baldwin 		explicit_bzero(tag2, sizeof(tag));
739c0341432SJohn Baldwin 	} else {
740c0341432SJohn Baldwin 		/* Inject the authentication data */
74126d292d3SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag);
742c0341432SJohn Baldwin 	}
74326d292d3SJohn Baldwin 	explicit_bzero(tag, sizeof(tag));
744*4361c4ebSJohn Baldwin 	explicit_bzero(blk, sizeof(blk));
74520c128daSJohn Baldwin 	explicit_bzero(iv, sizeof(iv));
74620c128daSJohn Baldwin 	return (error);
747c0341432SJohn Baldwin }
748c0341432SJohn Baldwin 
749c0341432SJohn Baldwin static int
750c0341432SJohn Baldwin swcr_ccm(struct swcr_session *ses, struct cryptop *crp)
751c0341432SJohn Baldwin {
752ae18720dSJohn Baldwin 	const struct crypto_session_params *csp;
75326d292d3SJohn Baldwin 	uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))];
754c0341432SJohn Baldwin 	u_char *blk = (u_char *)blkbuf;
75526d292d3SJohn Baldwin 	u_char tag[AES_CBC_MAC_HASH_LEN];
7569c0e3d3aSJohn Baldwin 	struct crypto_buffer_cursor cc_in, cc_out;
75726d292d3SJohn Baldwin 	const u_char *inblk;
75826d292d3SJohn Baldwin 	u_char *outblk;
759c0341432SJohn Baldwin 	union authctx ctx;
760c0341432SJohn Baldwin 	struct swcr_auth *swa;
761c0341432SJohn Baldwin 	struct swcr_encdec *swe;
762d8787d4fSMark Johnston 	const struct auth_hash *axf;
763d8787d4fSMark Johnston 	const struct enc_xform *exf;
76486be314dSJohn Baldwin 	size_t len;
76526d292d3SJohn Baldwin 	int blksz, error, ivlen, r, resid;
766c0341432SJohn Baldwin 
767ae18720dSJohn Baldwin 	csp = crypto_get_params(crp->crp_session);
768c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
769c0341432SJohn Baldwin 	axf = swa->sw_axf;
770c0341432SJohn Baldwin 
771c0341432SJohn Baldwin 	bcopy(swa->sw_ictx, &ctx, axf->ctxsize);
77226d292d3SJohn Baldwin 	blksz = AES_BLOCK_LEN;
77326d292d3SJohn Baldwin 	KASSERT(axf->blocksize == blksz, ("%s: axf block size mismatch",
77426d292d3SJohn Baldwin 	    __func__));
775c0341432SJohn Baldwin 
776c0341432SJohn Baldwin 	swe = &ses->swcr_encdec;
777c0341432SJohn Baldwin 	exf = swe->sw_exf;
778723d8764SJohn Baldwin 	KASSERT(axf->blocksize == exf->native_blocksize,
779723d8764SJohn Baldwin 	    ("%s: blocksize mismatch", __func__));
780c0341432SJohn Baldwin 
781ae18720dSJohn Baldwin 	if (crp->crp_payload_length > ccm_max_payload_length(csp))
782ae18720dSJohn Baldwin 		return (EMSGSIZE);
783ae18720dSJohn Baldwin 
784c0341432SJohn Baldwin 	if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0)
785c0341432SJohn Baldwin 		return (EINVAL);
786c0341432SJohn Baldwin 
787ae18720dSJohn Baldwin 	ivlen = csp->csp_ivlen;
788c0341432SJohn Baldwin 
789c0341432SJohn Baldwin 	/* Supply MAC with IV */
7905ae5ed5bSJohn Baldwin 	axf->Reinit(&ctx, crp->crp_iv, ivlen);
791c0341432SJohn Baldwin 
792*4361c4ebSJohn Baldwin 	/* Supply MAC with b0. */
793*4361c4ebSJohn Baldwin 	_Static_assert(sizeof(blkbuf) >= CCM_CBC_BLOCK_LEN,
794*4361c4ebSJohn Baldwin 	    "blkbuf too small for b0");
795*4361c4ebSJohn Baldwin 	build_ccm_b0(crp->crp_iv, ivlen, crp->crp_aad_length,
796*4361c4ebSJohn Baldwin 	    crp->crp_payload_length, swa->sw_mlen, blk);
797*4361c4ebSJohn Baldwin 	axf->Update(&ctx, blk, CCM_CBC_BLOCK_LEN);
798*4361c4ebSJohn Baldwin 
799c0341432SJohn Baldwin 	/* Supply MAC with AAD */
800*4361c4ebSJohn Baldwin 	if (crp->crp_aad_length != 0) {
801*4361c4ebSJohn Baldwin 		len = build_ccm_aad_length(crp->crp_aad_length, blk);
802*4361c4ebSJohn Baldwin 		axf->Update(&ctx, blk, len);
8039b774dc0SJohn Baldwin 		if (crp->crp_aad != NULL)
804*4361c4ebSJohn Baldwin 			axf->Update(&ctx, crp->crp_aad,
805*4361c4ebSJohn Baldwin 			    crp->crp_aad_length);
8069b774dc0SJohn Baldwin 		else
807*4361c4ebSJohn Baldwin 			crypto_apply(crp, crp->crp_aad_start,
8089b774dc0SJohn Baldwin 			    crp->crp_aad_length, axf->Update, &ctx);
809*4361c4ebSJohn Baldwin 
810*4361c4ebSJohn Baldwin 		/* Pad the AAD (including length field) to a full block. */
811*4361c4ebSJohn Baldwin 		len = (len + crp->crp_aad_length) % CCM_CBC_BLOCK_LEN;
812*4361c4ebSJohn Baldwin 		if (len != 0) {
813*4361c4ebSJohn Baldwin 			len = CCM_CBC_BLOCK_LEN - len;
814*4361c4ebSJohn Baldwin 			memset(blk, 0, CCM_CBC_BLOCK_LEN);
815*4361c4ebSJohn Baldwin 			axf->Update(&ctx, blk, len);
816*4361c4ebSJohn Baldwin 		}
817*4361c4ebSJohn Baldwin 	}
818c0341432SJohn Baldwin 
819a10020cfSJohn Baldwin 	if (crp->crp_cipher_key != NULL)
820a10020cfSJohn Baldwin 		exf->setkey(swe->sw_kschedule, crp->crp_cipher_key,
821a10020cfSJohn Baldwin 		    crypto_get_params(crp->crp_session)->csp_cipher_klen);
8225ae5ed5bSJohn Baldwin 	exf->reinit(swe->sw_kschedule, crp->crp_iv, ivlen);
823c0341432SJohn Baldwin 
824c0341432SJohn Baldwin 	/* Do encryption/decryption with MAC */
8259c0e3d3aSJohn Baldwin 	crypto_cursor_init(&cc_in, &crp->crp_buf);
8269c0e3d3aSJohn Baldwin 	crypto_cursor_advance(&cc_in, crp->crp_payload_start);
8279c0e3d3aSJohn Baldwin 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
8289c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_out, &crp->crp_obuf);
8299c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_out, crp->crp_payload_output_start);
8309c0e3d3aSJohn Baldwin 	} else
8319c0e3d3aSJohn Baldwin 		cc_out = cc_in;
83226d292d3SJohn Baldwin 	for (resid = crp->crp_payload_length; resid >= blksz; resid -= blksz) {
83386be314dSJohn Baldwin 		inblk = crypto_cursor_segment(&cc_in, &len);
83486be314dSJohn Baldwin 		if (len < blksz) {
83526d292d3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, blksz, blk);
83626d292d3SJohn Baldwin 			inblk = blk;
83786be314dSJohn Baldwin 		} else
83826d292d3SJohn Baldwin 			crypto_cursor_advance(&cc_in, blksz);
839c0341432SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
84086be314dSJohn Baldwin 			outblk = crypto_cursor_segment(&cc_out, &len);
84186be314dSJohn Baldwin 			if (len < blksz)
84226d292d3SJohn Baldwin 				outblk = blk;
84326d292d3SJohn Baldwin 			axf->Update(&ctx, inblk, blksz);
84426d292d3SJohn Baldwin 			exf->encrypt(swe->sw_kschedule, inblk, outblk);
84526d292d3SJohn Baldwin 			if (outblk == blk)
84626d292d3SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
84726d292d3SJohn Baldwin 			else
84826d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_out, blksz);
849c0341432SJohn Baldwin 		} else {
850c0341432SJohn Baldwin 			/*
851c0341432SJohn Baldwin 			 * One of the problems with CCM+CBC is that
852c0341432SJohn Baldwin 			 * the authentication is done on the
85326d292d3SJohn Baldwin 			 * unencrypted data.  As a result, we have to
854c0341432SJohn Baldwin 			 * decrypt the data twice: once to generate
855c0341432SJohn Baldwin 			 * the tag and a second time after the tag is
856c0341432SJohn Baldwin 			 * verified.
857c0341432SJohn Baldwin 			 */
85826d292d3SJohn Baldwin 			exf->decrypt(swe->sw_kschedule, inblk, blk);
85926d292d3SJohn Baldwin 			axf->Update(&ctx, blk, blksz);
86026d292d3SJohn Baldwin 		}
86126d292d3SJohn Baldwin 	}
86226d292d3SJohn Baldwin 	if (resid > 0) {
86326d292d3SJohn Baldwin 		crypto_cursor_copydata(&cc_in, resid, blk);
86426d292d3SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
86526d292d3SJohn Baldwin 			axf->Update(&ctx, blk, resid);
86626d292d3SJohn Baldwin 			exf->encrypt_last(swe->sw_kschedule, blk, blk, resid);
86726d292d3SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
86826d292d3SJohn Baldwin 		} else {
86926d292d3SJohn Baldwin 			exf->decrypt_last(swe->sw_kschedule, blk, blk, resid);
87026d292d3SJohn Baldwin 			axf->Update(&ctx, blk, resid);
871c0341432SJohn Baldwin 		}
87208fca7a5SJohn-Mark Gurney 	}
87308fca7a5SJohn-Mark Gurney 
87408fca7a5SJohn-Mark Gurney 	/* Finalize MAC */
87526d292d3SJohn Baldwin 	axf->Final(tag, &ctx);
87608fca7a5SJohn-Mark Gurney 
87708fca7a5SJohn-Mark Gurney 	/* Validate tag */
87820c128daSJohn Baldwin 	error = 0;
879c0341432SJohn Baldwin 	if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
88026d292d3SJohn Baldwin 		u_char tag2[AES_CBC_MAC_HASH_LEN];
88120c128daSJohn Baldwin 
882c0341432SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen,
88326d292d3SJohn Baldwin 		    tag2);
88408fca7a5SJohn-Mark Gurney 
88526d292d3SJohn Baldwin 		r = timingsafe_bcmp(tag, tag2, swa->sw_mlen);
88626d292d3SJohn Baldwin 		explicit_bzero(tag2, sizeof(tag2));
88720c128daSJohn Baldwin 		if (r != 0) {
88820c128daSJohn Baldwin 			error = EBADMSG;
88920c128daSJohn Baldwin 			goto out;
89020c128daSJohn Baldwin 		}
891c0341432SJohn Baldwin 
89208fca7a5SJohn-Mark Gurney 		/* tag matches, decrypt data */
8935ae5ed5bSJohn Baldwin 		exf->reinit(swe->sw_kschedule, crp->crp_iv, ivlen);
8949c0e3d3aSJohn Baldwin 		crypto_cursor_init(&cc_in, &crp->crp_buf);
8959c0e3d3aSJohn Baldwin 		crypto_cursor_advance(&cc_in, crp->crp_payload_start);
89626d292d3SJohn Baldwin 		for (resid = crp->crp_payload_length; resid > blksz;
89726d292d3SJohn Baldwin 		     resid -= blksz) {
89886be314dSJohn Baldwin 			inblk = crypto_cursor_segment(&cc_in, &len);
89986be314dSJohn Baldwin 			if (len < blksz) {
90026d292d3SJohn Baldwin 				crypto_cursor_copydata(&cc_in, blksz, blk);
90126d292d3SJohn Baldwin 				inblk = blk;
90286be314dSJohn Baldwin 			} else
90326d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_in, blksz);
90486be314dSJohn Baldwin 			outblk = crypto_cursor_segment(&cc_out, &len);
90586be314dSJohn Baldwin 			if (len < blksz)
90626d292d3SJohn Baldwin 				outblk = blk;
90726d292d3SJohn Baldwin 			exf->decrypt(swe->sw_kschedule, inblk, outblk);
90826d292d3SJohn Baldwin 			if (outblk == blk)
90926d292d3SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
91026d292d3SJohn Baldwin 			else
91126d292d3SJohn Baldwin 				crypto_cursor_advance(&cc_out, blksz);
91226d292d3SJohn Baldwin 		}
91326d292d3SJohn Baldwin 		if (resid > 0) {
91426d292d3SJohn Baldwin 			crypto_cursor_copydata(&cc_in, resid, blk);
91526d292d3SJohn Baldwin 			exf->decrypt_last(swe->sw_kschedule, blk, blk, resid);
91626d292d3SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
91708fca7a5SJohn-Mark Gurney 		}
91808fca7a5SJohn-Mark Gurney 	} else {
91908fca7a5SJohn-Mark Gurney 		/* Inject the authentication data */
92026d292d3SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag);
92108fca7a5SJohn-Mark Gurney 	}
92208fca7a5SJohn-Mark Gurney 
92320c128daSJohn Baldwin out:
92420c128daSJohn Baldwin 	explicit_bzero(blkbuf, sizeof(blkbuf));
92526d292d3SJohn Baldwin 	explicit_bzero(tag, sizeof(tag));
92620c128daSJohn Baldwin 	return (error);
92708fca7a5SJohn-Mark Gurney }
92808fca7a5SJohn-Mark Gurney 
929dd2e1352SJohn Baldwin static int
930dd2e1352SJohn Baldwin swcr_chacha20_poly1305(struct swcr_session *ses, struct cryptop *crp)
931dd2e1352SJohn Baldwin {
932dd2e1352SJohn Baldwin 	const struct crypto_session_params *csp;
933dd2e1352SJohn Baldwin 	uint64_t blkbuf[howmany(CHACHA20_NATIVE_BLOCK_LEN, sizeof(uint64_t))];
934dd2e1352SJohn Baldwin 	u_char *blk = (u_char *)blkbuf;
935dd2e1352SJohn Baldwin 	u_char tag[POLY1305_HASH_LEN];
936dd2e1352SJohn Baldwin 	struct crypto_buffer_cursor cc_in, cc_out;
937dd2e1352SJohn Baldwin 	const u_char *inblk;
938dd2e1352SJohn Baldwin 	u_char *outblk;
939dd2e1352SJohn Baldwin 	uint64_t *blkp;
940dd2e1352SJohn Baldwin 	union authctx ctx;
941dd2e1352SJohn Baldwin 	struct swcr_auth *swa;
942dd2e1352SJohn Baldwin 	struct swcr_encdec *swe;
943d8787d4fSMark Johnston 	const struct auth_hash *axf;
944d8787d4fSMark Johnston 	const struct enc_xform *exf;
94586be314dSJohn Baldwin 	size_t len;
946dd2e1352SJohn Baldwin 	int blksz, error, r, resid;
947dd2e1352SJohn Baldwin 
948dd2e1352SJohn Baldwin 	swa = &ses->swcr_auth;
949dd2e1352SJohn Baldwin 	axf = swa->sw_axf;
950dd2e1352SJohn Baldwin 
951dd2e1352SJohn Baldwin 	swe = &ses->swcr_encdec;
952dd2e1352SJohn Baldwin 	exf = swe->sw_exf;
953dd2e1352SJohn Baldwin 	blksz = exf->native_blocksize;
954dd2e1352SJohn Baldwin 	KASSERT(blksz <= sizeof(blkbuf), ("%s: blocksize mismatch", __func__));
955dd2e1352SJohn Baldwin 
956dd2e1352SJohn Baldwin 	if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0)
957dd2e1352SJohn Baldwin 		return (EINVAL);
958dd2e1352SJohn Baldwin 
959dd2e1352SJohn Baldwin 	csp = crypto_get_params(crp->crp_session);
960dd2e1352SJohn Baldwin 
961dd2e1352SJohn Baldwin 	/* Generate Poly1305 key. */
962dd2e1352SJohn Baldwin 	if (crp->crp_cipher_key != NULL)
963dd2e1352SJohn Baldwin 		axf->Setkey(&ctx, crp->crp_cipher_key, csp->csp_cipher_klen);
964dd2e1352SJohn Baldwin 	else
965dd2e1352SJohn Baldwin 		axf->Setkey(&ctx, csp->csp_cipher_key, csp->csp_cipher_klen);
966dd2e1352SJohn Baldwin 	axf->Reinit(&ctx, crp->crp_iv, csp->csp_ivlen);
967dd2e1352SJohn Baldwin 
968dd2e1352SJohn Baldwin 	/* Supply MAC with AAD */
969dd2e1352SJohn Baldwin 	if (crp->crp_aad != NULL)
970dd2e1352SJohn Baldwin 		axf->Update(&ctx, crp->crp_aad, crp->crp_aad_length);
971dd2e1352SJohn Baldwin 	else
972dd2e1352SJohn Baldwin 		crypto_apply(crp, crp->crp_aad_start,
973dd2e1352SJohn Baldwin 		    crp->crp_aad_length, axf->Update, &ctx);
974dd2e1352SJohn Baldwin 	if (crp->crp_aad_length % 16 != 0) {
975dd2e1352SJohn Baldwin 		/* padding1 */
976dd2e1352SJohn Baldwin 		memset(blk, 0, 16);
977dd2e1352SJohn Baldwin 		axf->Update(&ctx, blk, 16 - crp->crp_aad_length % 16);
978dd2e1352SJohn Baldwin 	}
979dd2e1352SJohn Baldwin 
980dd2e1352SJohn Baldwin 	if (crp->crp_cipher_key != NULL)
981dd2e1352SJohn Baldwin 		exf->setkey(swe->sw_kschedule, crp->crp_cipher_key,
982dd2e1352SJohn Baldwin 		    csp->csp_cipher_klen);
9831833d604SJohn Baldwin 	exf->reinit(swe->sw_kschedule, crp->crp_iv, csp->csp_ivlen);
984dd2e1352SJohn Baldwin 
985dd2e1352SJohn Baldwin 	/* Do encryption with MAC */
986dd2e1352SJohn Baldwin 	crypto_cursor_init(&cc_in, &crp->crp_buf);
987dd2e1352SJohn Baldwin 	crypto_cursor_advance(&cc_in, crp->crp_payload_start);
988dd2e1352SJohn Baldwin 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
989dd2e1352SJohn Baldwin 		crypto_cursor_init(&cc_out, &crp->crp_obuf);
990dd2e1352SJohn Baldwin 		crypto_cursor_advance(&cc_out, crp->crp_payload_output_start);
991dd2e1352SJohn Baldwin 	} else
992dd2e1352SJohn Baldwin 		cc_out = cc_in;
993dd2e1352SJohn Baldwin 	for (resid = crp->crp_payload_length; resid >= blksz; resid -= blksz) {
99486be314dSJohn Baldwin 		inblk = crypto_cursor_segment(&cc_in, &len);
99586be314dSJohn Baldwin 		if (len < blksz) {
996dd2e1352SJohn Baldwin 			crypto_cursor_copydata(&cc_in, blksz, blk);
997dd2e1352SJohn Baldwin 			inblk = blk;
99886be314dSJohn Baldwin 		} else
999dd2e1352SJohn Baldwin 			crypto_cursor_advance(&cc_in, blksz);
1000dd2e1352SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
100186be314dSJohn Baldwin 			outblk = crypto_cursor_segment(&cc_out, &len);
100286be314dSJohn Baldwin 			if (len < blksz)
1003dd2e1352SJohn Baldwin 				outblk = blk;
1004dd2e1352SJohn Baldwin 			exf->encrypt(swe->sw_kschedule, inblk, outblk);
1005dd2e1352SJohn Baldwin 			axf->Update(&ctx, outblk, blksz);
1006dd2e1352SJohn Baldwin 			if (outblk == blk)
1007dd2e1352SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
1008dd2e1352SJohn Baldwin 			else
1009dd2e1352SJohn Baldwin 				crypto_cursor_advance(&cc_out, blksz);
1010dd2e1352SJohn Baldwin 		} else {
1011dd2e1352SJohn Baldwin 			axf->Update(&ctx, inblk, blksz);
1012dd2e1352SJohn Baldwin 		}
1013dd2e1352SJohn Baldwin 	}
1014dd2e1352SJohn Baldwin 	if (resid > 0) {
1015dd2e1352SJohn Baldwin 		crypto_cursor_copydata(&cc_in, resid, blk);
1016dd2e1352SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
1017dd2e1352SJohn Baldwin 			exf->encrypt_last(swe->sw_kschedule, blk, blk, resid);
1018dd2e1352SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
1019dd2e1352SJohn Baldwin 		}
1020dd2e1352SJohn Baldwin 		axf->Update(&ctx, blk, resid);
1021dd2e1352SJohn Baldwin 		if (resid % 16 != 0) {
1022dd2e1352SJohn Baldwin 			/* padding2 */
1023dd2e1352SJohn Baldwin 			memset(blk, 0, 16);
1024dd2e1352SJohn Baldwin 			axf->Update(&ctx, blk, 16 - resid % 16);
1025dd2e1352SJohn Baldwin 		}
1026dd2e1352SJohn Baldwin 	}
1027dd2e1352SJohn Baldwin 
1028dd2e1352SJohn Baldwin 	/* lengths */
1029dd2e1352SJohn Baldwin 	blkp = (uint64_t *)blk;
1030dd2e1352SJohn Baldwin 	blkp[0] = htole64(crp->crp_aad_length);
1031dd2e1352SJohn Baldwin 	blkp[1] = htole64(crp->crp_payload_length);
1032dd2e1352SJohn Baldwin 	axf->Update(&ctx, blk, sizeof(uint64_t) * 2);
1033dd2e1352SJohn Baldwin 
1034dd2e1352SJohn Baldwin 	/* Finalize MAC */
1035dd2e1352SJohn Baldwin 	axf->Final(tag, &ctx);
1036dd2e1352SJohn Baldwin 
1037dd2e1352SJohn Baldwin 	/* Validate tag */
1038dd2e1352SJohn Baldwin 	error = 0;
1039dd2e1352SJohn Baldwin 	if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
1040dd2e1352SJohn Baldwin 		u_char tag2[POLY1305_HASH_LEN];
1041dd2e1352SJohn Baldwin 
1042dd2e1352SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, tag2);
1043dd2e1352SJohn Baldwin 
1044dd2e1352SJohn Baldwin 		r = timingsafe_bcmp(tag, tag2, swa->sw_mlen);
1045dd2e1352SJohn Baldwin 		explicit_bzero(tag2, sizeof(tag2));
1046dd2e1352SJohn Baldwin 		if (r != 0) {
1047dd2e1352SJohn Baldwin 			error = EBADMSG;
1048dd2e1352SJohn Baldwin 			goto out;
1049dd2e1352SJohn Baldwin 		}
1050dd2e1352SJohn Baldwin 
1051dd2e1352SJohn Baldwin 		/* tag matches, decrypt data */
1052dd2e1352SJohn Baldwin 		crypto_cursor_init(&cc_in, &crp->crp_buf);
1053dd2e1352SJohn Baldwin 		crypto_cursor_advance(&cc_in, crp->crp_payload_start);
1054dd2e1352SJohn Baldwin 		for (resid = crp->crp_payload_length; resid > blksz;
1055dd2e1352SJohn Baldwin 		     resid -= blksz) {
105686be314dSJohn Baldwin 			inblk = crypto_cursor_segment(&cc_in, &len);
105786be314dSJohn Baldwin 			if (len < blksz) {
1058dd2e1352SJohn Baldwin 				crypto_cursor_copydata(&cc_in, blksz, blk);
1059dd2e1352SJohn Baldwin 				inblk = blk;
106086be314dSJohn Baldwin 			} else
1061dd2e1352SJohn Baldwin 				crypto_cursor_advance(&cc_in, blksz);
106286be314dSJohn Baldwin 			outblk = crypto_cursor_segment(&cc_out, &len);
106386be314dSJohn Baldwin 			if (len < blksz)
1064dd2e1352SJohn Baldwin 				outblk = blk;
1065dd2e1352SJohn Baldwin 			exf->decrypt(swe->sw_kschedule, inblk, outblk);
1066dd2e1352SJohn Baldwin 			if (outblk == blk)
1067dd2e1352SJohn Baldwin 				crypto_cursor_copyback(&cc_out, blksz, blk);
1068dd2e1352SJohn Baldwin 			else
1069dd2e1352SJohn Baldwin 				crypto_cursor_advance(&cc_out, blksz);
1070dd2e1352SJohn Baldwin 		}
1071dd2e1352SJohn Baldwin 		if (resid > 0) {
1072dd2e1352SJohn Baldwin 			crypto_cursor_copydata(&cc_in, resid, blk);
1073dd2e1352SJohn Baldwin 			exf->decrypt_last(swe->sw_kschedule, blk, blk, resid);
1074dd2e1352SJohn Baldwin 			crypto_cursor_copyback(&cc_out, resid, blk);
1075dd2e1352SJohn Baldwin 		}
1076dd2e1352SJohn Baldwin 	} else {
1077dd2e1352SJohn Baldwin 		/* Inject the authentication data */
1078dd2e1352SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag);
1079dd2e1352SJohn Baldwin 	}
1080dd2e1352SJohn Baldwin 
1081dd2e1352SJohn Baldwin out:
1082dd2e1352SJohn Baldwin 	explicit_bzero(blkbuf, sizeof(blkbuf));
1083dd2e1352SJohn Baldwin 	explicit_bzero(tag, sizeof(tag));
1084dd2e1352SJohn Baldwin 	explicit_bzero(&ctx, sizeof(ctx));
1085dd2e1352SJohn Baldwin 	return (error);
1086dd2e1352SJohn Baldwin }
1087dd2e1352SJohn Baldwin 
1088091d81d1SSam Leffler /*
1089c0341432SJohn Baldwin  * Apply a cipher and a digest to perform EtA.
1090c0341432SJohn Baldwin  */
1091c0341432SJohn Baldwin static int
1092c0341432SJohn Baldwin swcr_eta(struct swcr_session *ses, struct cryptop *crp)
1093c0341432SJohn Baldwin {
1094c0341432SJohn Baldwin 	int error;
1095c0341432SJohn Baldwin 
1096c0341432SJohn Baldwin 	if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
1097c0341432SJohn Baldwin 		error = swcr_encdec(ses, crp);
1098c0341432SJohn Baldwin 		if (error == 0)
1099c0341432SJohn Baldwin 			error = swcr_authcompute(ses, crp);
1100c0341432SJohn Baldwin 	} else {
1101c0341432SJohn Baldwin 		error = swcr_authcompute(ses, crp);
1102c0341432SJohn Baldwin 		if (error == 0)
1103c0341432SJohn Baldwin 			error = swcr_encdec(ses, crp);
1104c0341432SJohn Baldwin 	}
1105c0341432SJohn Baldwin 	return (error);
1106c0341432SJohn Baldwin }
1107c0341432SJohn Baldwin 
1108c0341432SJohn Baldwin /*
1109091d81d1SSam Leffler  * Apply a compression/decompression algorithm
1110091d81d1SSam Leffler  */
1111091d81d1SSam Leffler static int
1112c0341432SJohn Baldwin swcr_compdec(struct swcr_session *ses, struct cryptop *crp)
1113091d81d1SSam Leffler {
1114d8787d4fSMark Johnston 	const struct comp_algo *cxf;
1115d3d79e96SJohn Baldwin 	uint8_t *data, *out;
1116091d81d1SSam Leffler 	int adj;
1117d3d79e96SJohn Baldwin 	uint32_t result;
1118091d81d1SSam Leffler 
1119c0341432SJohn Baldwin 	cxf = ses->swcr_compdec.sw_cxf;
1120091d81d1SSam Leffler 
1121091d81d1SSam Leffler 	/* We must handle the whole buffer of data in one time
1122091d81d1SSam Leffler 	 * then if there is not all the data in the mbuf, we must
1123091d81d1SSam Leffler 	 * copy in a buffer.
1124091d81d1SSam Leffler 	 */
1125091d81d1SSam Leffler 
1126c0341432SJohn Baldwin 	data = malloc(crp->crp_payload_length, M_CRYPTO_DATA,  M_NOWAIT);
1127091d81d1SSam Leffler 	if (data == NULL)
1128091d81d1SSam Leffler 		return (EINVAL);
1129c0341432SJohn Baldwin 	crypto_copydata(crp, crp->crp_payload_start, crp->crp_payload_length,
1130c0341432SJohn Baldwin 	    data);
1131091d81d1SSam Leffler 
1132c0341432SJohn Baldwin 	if (CRYPTO_OP_IS_COMPRESS(crp->crp_op))
1133c0341432SJohn Baldwin 		result = cxf->compress(data, crp->crp_payload_length, &out);
1134091d81d1SSam Leffler 	else
1135c0341432SJohn Baldwin 		result = cxf->decompress(data, crp->crp_payload_length, &out);
1136091d81d1SSam Leffler 
11371ede983cSDag-Erling Smørgrav 	free(data, M_CRYPTO_DATA);
1138091d81d1SSam Leffler 	if (result == 0)
1139c0341432SJohn Baldwin 		return (EINVAL);
1140c0341432SJohn Baldwin 	crp->crp_olen = result;
1141c0341432SJohn Baldwin 
1142c0341432SJohn Baldwin 	/* Check the compressed size when doing compression */
1143c0341432SJohn Baldwin 	if (CRYPTO_OP_IS_COMPRESS(crp->crp_op)) {
1144c0341432SJohn Baldwin 		if (result >= crp->crp_payload_length) {
1145c0341432SJohn Baldwin 			/* Compression was useless, we lost time */
1146c0341432SJohn Baldwin 			free(out, M_CRYPTO_DATA);
1147c0341432SJohn Baldwin 			return (0);
1148c0341432SJohn Baldwin 		}
1149c0341432SJohn Baldwin 	}
1150091d81d1SSam Leffler 
1151091d81d1SSam Leffler 	/* Copy back the (de)compressed data. m_copyback is
1152091d81d1SSam Leffler 	 * extending the mbuf as necessary.
1153091d81d1SSam Leffler 	 */
1154c0341432SJohn Baldwin 	crypto_copyback(crp, crp->crp_payload_start, result, out);
1155c0341432SJohn Baldwin 	if (result < crp->crp_payload_length) {
11569c0e3d3aSJohn Baldwin 		switch (crp->crp_buf.cb_type) {
1157c0341432SJohn Baldwin 		case CRYPTO_BUF_MBUF:
1158883a0196SJohn Baldwin 		case CRYPTO_BUF_SINGLE_MBUF:
1159c0341432SJohn Baldwin 			adj = result - crp->crp_payload_length;
11609c0e3d3aSJohn Baldwin 			m_adj(crp->crp_buf.cb_mbuf, adj);
1161c0341432SJohn Baldwin 			break;
1162c0341432SJohn Baldwin 		case CRYPTO_BUF_UIO: {
11639c0e3d3aSJohn Baldwin 			struct uio *uio = crp->crp_buf.cb_uio;
1164091d81d1SSam Leffler 			int ind;
1165091d81d1SSam Leffler 
1166c0341432SJohn Baldwin 			adj = crp->crp_payload_length - result;
1167091d81d1SSam Leffler 			ind = uio->uio_iovcnt - 1;
1168091d81d1SSam Leffler 
1169091d81d1SSam Leffler 			while (adj > 0 && ind >= 0) {
1170091d81d1SSam Leffler 				if (adj < uio->uio_iov[ind].iov_len) {
1171091d81d1SSam Leffler 					uio->uio_iov[ind].iov_len -= adj;
1172091d81d1SSam Leffler 					break;
1173091d81d1SSam Leffler 				}
1174091d81d1SSam Leffler 
1175091d81d1SSam Leffler 				adj -= uio->uio_iov[ind].iov_len;
1176091d81d1SSam Leffler 				uio->uio_iov[ind].iov_len = 0;
1177091d81d1SSam Leffler 				ind--;
1178091d81d1SSam Leffler 				uio->uio_iovcnt--;
1179091d81d1SSam Leffler 			}
1180091d81d1SSam Leffler 			}
1181c0341432SJohn Baldwin 			break;
1182e6f6d0c9SAlan Somers 		case CRYPTO_BUF_VMPAGE:
1183e6f6d0c9SAlan Somers 			adj = crp->crp_payload_length - result;
1184e6f6d0c9SAlan Somers 			crp->crp_buf.cb_vm_page_len -= adj;
1185e6f6d0c9SAlan Somers 			break;
11869c0e3d3aSJohn Baldwin 		default:
11879c0e3d3aSJohn Baldwin 			break;
1188c0341432SJohn Baldwin 		}
1189091d81d1SSam Leffler 	}
11901ede983cSDag-Erling Smørgrav 	free(out, M_CRYPTO_DATA);
1191091d81d1SSam Leffler 	return 0;
1192091d81d1SSam Leffler }
1193091d81d1SSam Leffler 
1194091d81d1SSam Leffler static int
11953e947048SJohn Baldwin swcr_setup_cipher(struct swcr_session *ses,
1196c0341432SJohn Baldwin     const struct crypto_session_params *csp)
1197091d81d1SSam Leffler {
1198c0341432SJohn Baldwin 	struct swcr_encdec *swe;
1199d8787d4fSMark Johnston 	const struct enc_xform *txf;
1200f6c4bc3bSPawel Jakub Dawidek 	int error;
1201091d81d1SSam Leffler 
1202c0341432SJohn Baldwin 	swe = &ses->swcr_encdec;
1203c0341432SJohn Baldwin 	txf = crypto_cipher(csp);
12043e947048SJohn Baldwin 	if (txf->ctxsize != 0) {
12053e947048SJohn Baldwin 		swe->sw_kschedule = malloc(txf->ctxsize, M_CRYPTO_DATA,
12063e947048SJohn Baldwin 		    M_NOWAIT);
12073e947048SJohn Baldwin 		if (swe->sw_kschedule == NULL)
12083e947048SJohn Baldwin 			return (ENOMEM);
12093e947048SJohn Baldwin 	}
1210c0341432SJohn Baldwin 	if (csp->csp_cipher_key != NULL) {
12113e947048SJohn Baldwin 		error = txf->setkey(swe->sw_kschedule,
1212c0341432SJohn Baldwin 		    csp->csp_cipher_key, csp->csp_cipher_klen);
1213c0341432SJohn Baldwin 		if (error)
1214c0341432SJohn Baldwin 			return (error);
1215091d81d1SSam Leffler 	}
1216c0341432SJohn Baldwin 	swe->sw_exf = txf;
1217c0341432SJohn Baldwin 	return (0);
1218f6c4bc3bSPawel Jakub Dawidek }
1219091d81d1SSam Leffler 
1220c0341432SJohn Baldwin static int
1221c0341432SJohn Baldwin swcr_setup_auth(struct swcr_session *ses,
1222c0341432SJohn Baldwin     const struct crypto_session_params *csp)
1223c0341432SJohn Baldwin {
1224c0341432SJohn Baldwin 	struct swcr_auth *swa;
1225d8787d4fSMark Johnston 	const struct auth_hash *axf;
1226c0341432SJohn Baldwin 
1227c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
1228c0341432SJohn Baldwin 
1229c0341432SJohn Baldwin 	axf = crypto_auth_hash(csp);
1230c0341432SJohn Baldwin 	swa->sw_axf = axf;
1231c0341432SJohn Baldwin 	if (csp->csp_auth_mlen < 0 || csp->csp_auth_mlen > axf->hashsize)
1232c0341432SJohn Baldwin 		return (EINVAL);
1233c0341432SJohn Baldwin 	if (csp->csp_auth_mlen == 0)
1234c0341432SJohn Baldwin 		swa->sw_mlen = axf->hashsize;
1235c0341432SJohn Baldwin 	else
1236c0341432SJohn Baldwin 		swa->sw_mlen = csp->csp_auth_mlen;
1237c0341432SJohn Baldwin 	swa->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, M_NOWAIT);
1238c0341432SJohn Baldwin 	if (swa->sw_ictx == NULL)
1239c0341432SJohn Baldwin 		return (ENOBUFS);
1240c0341432SJohn Baldwin 
1241c0341432SJohn Baldwin 	switch (csp->csp_auth_alg) {
1242091d81d1SSam Leffler 	case CRYPTO_SHA1_HMAC:
1243c97f39ceSConrad Meyer 	case CRYPTO_SHA2_224_HMAC:
1244f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_256_HMAC:
1245f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_384_HMAC:
1246f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_512_HMAC:
1247091d81d1SSam Leffler 	case CRYPTO_NULL_HMAC:
1248091d81d1SSam Leffler 	case CRYPTO_RIPEMD160_HMAC:
12493a0b6a93SJohn Baldwin 		swa->sw_octx = malloc(axf->ctxsize, M_CRYPTO_DATA,
1250091d81d1SSam Leffler 		    M_NOWAIT);
1251c0341432SJohn Baldwin 		if (swa->sw_octx == NULL)
1252c0341432SJohn Baldwin 			return (ENOBUFS);
1253c0341432SJohn Baldwin 
1254c0341432SJohn Baldwin 		if (csp->csp_auth_key != NULL) {
1255c0341432SJohn Baldwin 			swcr_authprepare(axf, swa, csp->csp_auth_key,
1256c0341432SJohn Baldwin 			    csp->csp_auth_klen);
1257091d81d1SSam Leffler 		}
1258091d81d1SSam Leffler 
1259c0341432SJohn Baldwin 		if (csp->csp_mode == CSP_MODE_DIGEST)
1260c0341432SJohn Baldwin 			ses->swcr_process = swcr_authcompute;
1261091d81d1SSam Leffler 		break;
1262091d81d1SSam Leffler 	case CRYPTO_SHA1:
1263c4729f6eSConrad Meyer 	case CRYPTO_SHA2_224:
1264c4729f6eSConrad Meyer 	case CRYPTO_SHA2_256:
1265c4729f6eSConrad Meyer 	case CRYPTO_SHA2_384:
1266c4729f6eSConrad Meyer 	case CRYPTO_SHA2_512:
1267c0341432SJohn Baldwin 		axf->Init(swa->sw_ictx);
1268c0341432SJohn Baldwin 		if (csp->csp_mode == CSP_MODE_DIGEST)
1269c0341432SJohn Baldwin 			ses->swcr_process = swcr_authcompute;
1270c0341432SJohn Baldwin 		break;
1271c0341432SJohn Baldwin 	case CRYPTO_AES_NIST_GMAC:
1272c0341432SJohn Baldwin 		axf->Init(swa->sw_ictx);
1273c0341432SJohn Baldwin 		axf->Setkey(swa->sw_ictx, csp->csp_auth_key,
1274c0341432SJohn Baldwin 		    csp->csp_auth_klen);
1275c0341432SJohn Baldwin 		if (csp->csp_mode == CSP_MODE_DIGEST)
1276c0341432SJohn Baldwin 			ses->swcr_process = swcr_gmac;
1277c0341432SJohn Baldwin 		break;
1278c0341432SJohn Baldwin 	case CRYPTO_POLY1305:
1279c0341432SJohn Baldwin 	case CRYPTO_BLAKE2B:
1280c0341432SJohn Baldwin 	case CRYPTO_BLAKE2S:
1281c0341432SJohn Baldwin 		/*
1282c0341432SJohn Baldwin 		 * Blake2b and Blake2s support an optional key but do
1283c0341432SJohn Baldwin 		 * not require one.
1284c0341432SJohn Baldwin 		 */
1285c0341432SJohn Baldwin 		if (csp->csp_auth_klen == 0 || csp->csp_auth_key != NULL)
1286c0341432SJohn Baldwin 			axf->Setkey(swa->sw_ictx, csp->csp_auth_key,
1287c0341432SJohn Baldwin 			    csp->csp_auth_klen);
1288c0341432SJohn Baldwin 		axf->Init(swa->sw_ictx);
1289c0341432SJohn Baldwin 		if (csp->csp_mode == CSP_MODE_DIGEST)
1290c0341432SJohn Baldwin 			ses->swcr_process = swcr_authcompute;
1291c0341432SJohn Baldwin 		break;
1292c0341432SJohn Baldwin 	case CRYPTO_AES_CCM_CBC_MAC:
1293c0341432SJohn Baldwin 		axf->Init(swa->sw_ictx);
1294c0341432SJohn Baldwin 		axf->Setkey(swa->sw_ictx, csp->csp_auth_key,
1295c0341432SJohn Baldwin 		    csp->csp_auth_klen);
1296c0341432SJohn Baldwin 		if (csp->csp_mode == CSP_MODE_DIGEST)
1297c0341432SJohn Baldwin 			ses->swcr_process = swcr_ccm_cbc_mac;
1298c0341432SJohn Baldwin 		break;
1299091d81d1SSam Leffler 	}
1300091d81d1SSam Leffler 
1301c0341432SJohn Baldwin 	return (0);
1302c0341432SJohn Baldwin }
130308fca7a5SJohn-Mark Gurney 
1304c0341432SJohn Baldwin static int
1305c0341432SJohn Baldwin swcr_setup_gcm(struct swcr_session *ses,
1306c0341432SJohn Baldwin     const struct crypto_session_params *csp)
1307c0341432SJohn Baldwin {
1308c0341432SJohn Baldwin 	struct swcr_auth *swa;
1309d8787d4fSMark Johnston 	const struct auth_hash *axf;
1310c0341432SJohn Baldwin 
1311c0341432SJohn Baldwin 	if (csp->csp_ivlen != AES_GCM_IV_LEN)
1312c0341432SJohn Baldwin 		return (EINVAL);
1313c0341432SJohn Baldwin 
1314c0341432SJohn Baldwin 	/* First, setup the auth side. */
1315c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
1316c0341432SJohn Baldwin 	switch (csp->csp_cipher_klen * 8) {
1317c0341432SJohn Baldwin 	case 128:
1318c0341432SJohn Baldwin 		axf = &auth_hash_nist_gmac_aes_128;
1319c0341432SJohn Baldwin 		break;
1320c0341432SJohn Baldwin 	case 192:
1321c0341432SJohn Baldwin 		axf = &auth_hash_nist_gmac_aes_192;
1322c0341432SJohn Baldwin 		break;
1323c0341432SJohn Baldwin 	case 256:
1324c0341432SJohn Baldwin 		axf = &auth_hash_nist_gmac_aes_256;
1325c0341432SJohn Baldwin 		break;
1326c0341432SJohn Baldwin 	default:
1327c0341432SJohn Baldwin 		return (EINVAL);
1328c0341432SJohn Baldwin 	}
1329c0341432SJohn Baldwin 	swa->sw_axf = axf;
1330c0341432SJohn Baldwin 	if (csp->csp_auth_mlen < 0 || csp->csp_auth_mlen > axf->hashsize)
1331c0341432SJohn Baldwin 		return (EINVAL);
1332c0341432SJohn Baldwin 	if (csp->csp_auth_mlen == 0)
1333c0341432SJohn Baldwin 		swa->sw_mlen = axf->hashsize;
1334c0341432SJohn Baldwin 	else
1335c0341432SJohn Baldwin 		swa->sw_mlen = csp->csp_auth_mlen;
1336c0341432SJohn Baldwin 	swa->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, M_NOWAIT);
1337c0341432SJohn Baldwin 	if (swa->sw_ictx == NULL)
1338c0341432SJohn Baldwin 		return (ENOBUFS);
1339c0341432SJohn Baldwin 	axf->Init(swa->sw_ictx);
1340c0341432SJohn Baldwin 	if (csp->csp_cipher_key != NULL)
1341c0341432SJohn Baldwin 		axf->Setkey(swa->sw_ictx, csp->csp_cipher_key,
1342c0341432SJohn Baldwin 		    csp->csp_cipher_klen);
1343c0341432SJohn Baldwin 
1344c0341432SJohn Baldwin 	/* Second, setup the cipher side. */
13453e947048SJohn Baldwin 	return (swcr_setup_cipher(ses, csp));
1346c0341432SJohn Baldwin }
1347c0341432SJohn Baldwin 
1348c0341432SJohn Baldwin static int
1349c0341432SJohn Baldwin swcr_setup_ccm(struct swcr_session *ses,
1350c0341432SJohn Baldwin     const struct crypto_session_params *csp)
1351c0341432SJohn Baldwin {
1352c0341432SJohn Baldwin 	struct swcr_auth *swa;
1353d8787d4fSMark Johnston 	const struct auth_hash *axf;
1354c0341432SJohn Baldwin 
1355c0341432SJohn Baldwin 	/* First, setup the auth side. */
1356c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
1357c0341432SJohn Baldwin 	switch (csp->csp_cipher_klen * 8) {
1358507281e5SSean Eric Fagan 	case 128:
1359507281e5SSean Eric Fagan 		axf = &auth_hash_ccm_cbc_mac_128;
1360507281e5SSean Eric Fagan 		break;
1361507281e5SSean Eric Fagan 	case 192:
1362507281e5SSean Eric Fagan 		axf = &auth_hash_ccm_cbc_mac_192;
1363507281e5SSean Eric Fagan 		break;
1364507281e5SSean Eric Fagan 	case 256:
1365507281e5SSean Eric Fagan 		axf = &auth_hash_ccm_cbc_mac_256;
1366507281e5SSean Eric Fagan 		break;
1367507281e5SSean Eric Fagan 	default:
1368c0341432SJohn Baldwin 		return (EINVAL);
1369507281e5SSean Eric Fagan 	}
1370c0341432SJohn Baldwin 	swa->sw_axf = axf;
1371c0341432SJohn Baldwin 	if (csp->csp_auth_mlen < 0 || csp->csp_auth_mlen > axf->hashsize)
1372c0341432SJohn Baldwin 		return (EINVAL);
1373c0341432SJohn Baldwin 	if (csp->csp_auth_mlen == 0)
1374c0341432SJohn Baldwin 		swa->sw_mlen = axf->hashsize;
1375c0341432SJohn Baldwin 	else
1376c0341432SJohn Baldwin 		swa->sw_mlen = csp->csp_auth_mlen;
1377c0341432SJohn Baldwin 	swa->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, M_NOWAIT);
1378c0341432SJohn Baldwin 	if (swa->sw_ictx == NULL)
1379c0341432SJohn Baldwin 		return (ENOBUFS);
1380c0341432SJohn Baldwin 	axf->Init(swa->sw_ictx);
1381c0341432SJohn Baldwin 	if (csp->csp_cipher_key != NULL)
1382c0341432SJohn Baldwin 		axf->Setkey(swa->sw_ictx, csp->csp_cipher_key,
1383c0341432SJohn Baldwin 		    csp->csp_cipher_klen);
138408fca7a5SJohn-Mark Gurney 
1385c0341432SJohn Baldwin 	/* Second, setup the cipher side. */
13863e947048SJohn Baldwin 	return (swcr_setup_cipher(ses, csp));
13872e2e26d1SJohn Baldwin }
1388a2bc81bfSJohn-Mark Gurney 
1389dd2e1352SJohn Baldwin static int
1390dd2e1352SJohn Baldwin swcr_setup_chacha20_poly1305(struct swcr_session *ses,
1391dd2e1352SJohn Baldwin     const struct crypto_session_params *csp)
1392dd2e1352SJohn Baldwin {
1393dd2e1352SJohn Baldwin 	struct swcr_auth *swa;
1394d8787d4fSMark Johnston 	const struct auth_hash *axf;
1395dd2e1352SJohn Baldwin 
1396dd2e1352SJohn Baldwin 	if (csp->csp_ivlen != CHACHA20_POLY1305_IV_LEN)
1397dd2e1352SJohn Baldwin 		return (EINVAL);
1398dd2e1352SJohn Baldwin 
1399dd2e1352SJohn Baldwin 	/* First, setup the auth side. */
1400dd2e1352SJohn Baldwin 	swa = &ses->swcr_auth;
1401dd2e1352SJohn Baldwin 	axf = &auth_hash_chacha20_poly1305;
1402dd2e1352SJohn Baldwin 	swa->sw_axf = axf;
1403dd2e1352SJohn Baldwin 	if (csp->csp_auth_mlen < 0 || csp->csp_auth_mlen > axf->hashsize)
1404dd2e1352SJohn Baldwin 		return (EINVAL);
1405dd2e1352SJohn Baldwin 	if (csp->csp_auth_mlen == 0)
1406dd2e1352SJohn Baldwin 		swa->sw_mlen = axf->hashsize;
1407dd2e1352SJohn Baldwin 	else
1408dd2e1352SJohn Baldwin 		swa->sw_mlen = csp->csp_auth_mlen;
1409dd2e1352SJohn Baldwin 
1410dd2e1352SJohn Baldwin 	/* The auth state is regenerated for each nonce. */
1411dd2e1352SJohn Baldwin 
1412dd2e1352SJohn Baldwin 	/* Second, setup the cipher side. */
1413dd2e1352SJohn Baldwin 	return (swcr_setup_cipher(ses, csp));
1414dd2e1352SJohn Baldwin }
1415dd2e1352SJohn Baldwin 
1416c0341432SJohn Baldwin static bool
1417c0341432SJohn Baldwin swcr_auth_supported(const struct crypto_session_params *csp)
1418109919c6SBenno Rice {
1419d8787d4fSMark Johnston 	const struct auth_hash *axf;
1420091d81d1SSam Leffler 
1421c0341432SJohn Baldwin 	axf = crypto_auth_hash(csp);
1422c0341432SJohn Baldwin 	if (axf == NULL)
1423c0341432SJohn Baldwin 		return (false);
1424c0341432SJohn Baldwin 	switch (csp->csp_auth_alg) {
1425091d81d1SSam Leffler 	case CRYPTO_SHA1_HMAC:
1426c97f39ceSConrad Meyer 	case CRYPTO_SHA2_224_HMAC:
1427f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_256_HMAC:
1428f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_384_HMAC:
1429f6c4bc3bSPawel Jakub Dawidek 	case CRYPTO_SHA2_512_HMAC:
1430091d81d1SSam Leffler 	case CRYPTO_NULL_HMAC:
1431c0341432SJohn Baldwin 	case CRYPTO_RIPEMD160_HMAC:
1432091d81d1SSam Leffler 		break;
1433c0341432SJohn Baldwin 	case CRYPTO_AES_NIST_GMAC:
1434c0341432SJohn Baldwin 		switch (csp->csp_auth_klen * 8) {
1435c0341432SJohn Baldwin 		case 128:
1436c0341432SJohn Baldwin 		case 192:
1437c0341432SJohn Baldwin 		case 256:
1438c0341432SJohn Baldwin 			break;
1439c0341432SJohn Baldwin 		default:
1440c0341432SJohn Baldwin 			return (false);
1441c0341432SJohn Baldwin 		}
1442c0341432SJohn Baldwin 		if (csp->csp_auth_key == NULL)
1443c0341432SJohn Baldwin 			return (false);
1444c0341432SJohn Baldwin 		if (csp->csp_ivlen != AES_GCM_IV_LEN)
1445c0341432SJohn Baldwin 			return (false);
1446c0341432SJohn Baldwin 		break;
144725b7033bSConrad Meyer 	case CRYPTO_POLY1305:
1448c0341432SJohn Baldwin 		if (csp->csp_auth_klen != POLY1305_KEY_LEN)
1449c0341432SJohn Baldwin 			return (false);
1450c0341432SJohn Baldwin 		break;
1451c0341432SJohn Baldwin 	case CRYPTO_AES_CCM_CBC_MAC:
1452c0341432SJohn Baldwin 		switch (csp->csp_auth_klen * 8) {
1453c0341432SJohn Baldwin 		case 128:
1454c0341432SJohn Baldwin 		case 192:
1455c0341432SJohn Baldwin 		case 256:
1456c0341432SJohn Baldwin 			break;
1457c0341432SJohn Baldwin 		default:
1458c0341432SJohn Baldwin 			return (false);
1459c0341432SJohn Baldwin 		}
1460c0341432SJohn Baldwin 		if (csp->csp_auth_key == NULL)
1461c0341432SJohn Baldwin 			return (false);
1462c0341432SJohn Baldwin 		break;
1463c0341432SJohn Baldwin 	}
1464c0341432SJohn Baldwin 	return (true);
1465c0341432SJohn Baldwin }
1466091d81d1SSam Leffler 
1467c0341432SJohn Baldwin static bool
1468c0341432SJohn Baldwin swcr_cipher_supported(const struct crypto_session_params *csp)
1469c0341432SJohn Baldwin {
1470d8787d4fSMark Johnston 	const struct enc_xform *txf;
1471c0341432SJohn Baldwin 
1472c0341432SJohn Baldwin 	txf = crypto_cipher(csp);
1473c0341432SJohn Baldwin 	if (txf == NULL)
1474c0341432SJohn Baldwin 		return (false);
1475c0341432SJohn Baldwin 	if (csp->csp_cipher_alg != CRYPTO_NULL_CBC &&
1476c0341432SJohn Baldwin 	    txf->ivsize != csp->csp_ivlen)
1477c0341432SJohn Baldwin 		return (false);
1478c0341432SJohn Baldwin 	return (true);
1479c0341432SJohn Baldwin }
1480c0341432SJohn Baldwin 
14816038018aSMarcin Wojtas #define SUPPORTED_SES (CSP_F_SEPARATE_OUTPUT | CSP_F_SEPARATE_AAD | CSP_F_ESN)
14826038018aSMarcin Wojtas 
1483c0341432SJohn Baldwin static int
1484c0341432SJohn Baldwin swcr_probesession(device_t dev, const struct crypto_session_params *csp)
1485c0341432SJohn Baldwin {
14866038018aSMarcin Wojtas 	if ((csp->csp_flags & ~(SUPPORTED_SES)) != 0)
1487c0341432SJohn Baldwin 		return (EINVAL);
1488c0341432SJohn Baldwin 	switch (csp->csp_mode) {
1489c0341432SJohn Baldwin 	case CSP_MODE_COMPRESS:
1490c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1491c0341432SJohn Baldwin 		case CRYPTO_DEFLATE_COMP:
1492c0341432SJohn Baldwin 			break;
1493c0341432SJohn Baldwin 		default:
1494c0341432SJohn Baldwin 			return (EINVAL);
14955fbc5b5aSConrad Meyer 		}
1496091d81d1SSam Leffler 		break;
1497c0341432SJohn Baldwin 	case CSP_MODE_CIPHER:
1498c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1499c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1500c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1501dd2e1352SJohn Baldwin 		case CRYPTO_CHACHA20_POLY1305:
1502c0341432SJohn Baldwin 			return (EINVAL);
1503c0341432SJohn Baldwin 		default:
1504c0341432SJohn Baldwin 			if (!swcr_cipher_supported(csp))
1505c0341432SJohn Baldwin 				return (EINVAL);
1506091d81d1SSam Leffler 			break;
1507091d81d1SSam Leffler 		}
1508c0341432SJohn Baldwin 		break;
1509c0341432SJohn Baldwin 	case CSP_MODE_DIGEST:
1510c0341432SJohn Baldwin 		if (!swcr_auth_supported(csp))
1511c0341432SJohn Baldwin 			return (EINVAL);
1512c0341432SJohn Baldwin 		break;
1513c0341432SJohn Baldwin 	case CSP_MODE_AEAD:
1514c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1515c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1516c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1517dd2e1352SJohn Baldwin 		case CRYPTO_CHACHA20_POLY1305:
1518c0341432SJohn Baldwin 			break;
1519c0341432SJohn Baldwin 		default:
1520c0341432SJohn Baldwin 			return (EINVAL);
1521c0341432SJohn Baldwin 		}
1522c0341432SJohn Baldwin 		break;
1523c0341432SJohn Baldwin 	case CSP_MODE_ETA:
1524c0341432SJohn Baldwin 		/* AEAD algorithms cannot be used for EtA. */
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:
1529c0341432SJohn Baldwin 			return (EINVAL);
1530c0341432SJohn Baldwin 		}
1531c0341432SJohn Baldwin 		switch (csp->csp_auth_alg) {
1532c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GMAC:
1533c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_CBC_MAC:
1534c0341432SJohn Baldwin 			return (EINVAL);
1535c0341432SJohn Baldwin 		}
1536c0341432SJohn Baldwin 
1537c0341432SJohn Baldwin 		if (!swcr_cipher_supported(csp) ||
1538c0341432SJohn Baldwin 		    !swcr_auth_supported(csp))
1539c0341432SJohn Baldwin 			return (EINVAL);
1540c0341432SJohn Baldwin 		break;
1541c0341432SJohn Baldwin 	default:
1542c0341432SJohn Baldwin 		return (EINVAL);
1543c0341432SJohn Baldwin 	}
1544c0341432SJohn Baldwin 
1545c0341432SJohn Baldwin 	return (CRYPTODEV_PROBE_SOFTWARE);
1546c0341432SJohn Baldwin }
1547c0341432SJohn Baldwin 
1548c0341432SJohn Baldwin /*
1549c0341432SJohn Baldwin  * Generate a new software session.
1550c0341432SJohn Baldwin  */
1551c0341432SJohn Baldwin static int
1552c0341432SJohn Baldwin swcr_newsession(device_t dev, crypto_session_t cses,
1553c0341432SJohn Baldwin     const struct crypto_session_params *csp)
1554c0341432SJohn Baldwin {
1555c0341432SJohn Baldwin 	struct swcr_session *ses;
1556c0341432SJohn Baldwin 	struct swcr_encdec *swe;
1557c0341432SJohn Baldwin 	struct swcr_auth *swa;
1558d8787d4fSMark Johnston 	const struct comp_algo *cxf;
1559c0341432SJohn Baldwin 	int error;
1560c0341432SJohn Baldwin 
1561c0341432SJohn Baldwin 	ses = crypto_get_driver_session(cses);
1562c0341432SJohn Baldwin 	mtx_init(&ses->swcr_lock, "swcr session lock", NULL, MTX_DEF);
1563c0341432SJohn Baldwin 
1564c0341432SJohn Baldwin 	error = 0;
1565c0341432SJohn Baldwin 	swe = &ses->swcr_encdec;
1566c0341432SJohn Baldwin 	swa = &ses->swcr_auth;
1567c0341432SJohn Baldwin 	switch (csp->csp_mode) {
1568c0341432SJohn Baldwin 	case CSP_MODE_COMPRESS:
1569c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1570c0341432SJohn Baldwin 		case CRYPTO_DEFLATE_COMP:
1571c0341432SJohn Baldwin 			cxf = &comp_algo_deflate;
1572c0341432SJohn Baldwin 			break;
1573c0341432SJohn Baldwin #ifdef INVARIANTS
1574c0341432SJohn Baldwin 		default:
1575c0341432SJohn Baldwin 			panic("bad compression algo");
1576c0341432SJohn Baldwin #endif
1577c0341432SJohn Baldwin 		}
1578c0341432SJohn Baldwin 		ses->swcr_compdec.sw_cxf = cxf;
1579c0341432SJohn Baldwin 		ses->swcr_process = swcr_compdec;
1580c0341432SJohn Baldwin 		break;
1581c0341432SJohn Baldwin 	case CSP_MODE_CIPHER:
1582c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1583c0341432SJohn Baldwin 		case CRYPTO_NULL_CBC:
1584c0341432SJohn Baldwin 			ses->swcr_process = swcr_null;
1585c0341432SJohn Baldwin 			break;
1586c0341432SJohn Baldwin #ifdef INVARIANTS
1587c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1588c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1589dd2e1352SJohn Baldwin 		case CRYPTO_CHACHA20_POLY1305:
1590c0341432SJohn Baldwin 			panic("bad cipher algo");
1591c0341432SJohn Baldwin #endif
1592c0341432SJohn Baldwin 		default:
15933e947048SJohn Baldwin 			error = swcr_setup_cipher(ses, csp);
1594c0341432SJohn Baldwin 			if (error == 0)
1595c0341432SJohn Baldwin 				ses->swcr_process = swcr_encdec;
1596c0341432SJohn Baldwin 		}
1597c0341432SJohn Baldwin 		break;
1598c0341432SJohn Baldwin 	case CSP_MODE_DIGEST:
1599c0341432SJohn Baldwin 		error = swcr_setup_auth(ses, csp);
1600c0341432SJohn Baldwin 		break;
1601c0341432SJohn Baldwin 	case CSP_MODE_AEAD:
1602c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1603c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1604c0341432SJohn Baldwin 			error = swcr_setup_gcm(ses, csp);
1605c0341432SJohn Baldwin 			if (error == 0)
1606c0341432SJohn Baldwin 				ses->swcr_process = swcr_gcm;
1607c0341432SJohn Baldwin 			break;
1608c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1609c0341432SJohn Baldwin 			error = swcr_setup_ccm(ses, csp);
1610c0341432SJohn Baldwin 			if (error == 0)
1611c0341432SJohn Baldwin 				ses->swcr_process = swcr_ccm;
1612c0341432SJohn Baldwin 			break;
1613dd2e1352SJohn Baldwin 		case CRYPTO_CHACHA20_POLY1305:
1614dd2e1352SJohn Baldwin 			error = swcr_setup_chacha20_poly1305(ses, csp);
1615dd2e1352SJohn Baldwin 			if (error == 0)
1616dd2e1352SJohn Baldwin 				ses->swcr_process = swcr_chacha20_poly1305;
1617dd2e1352SJohn Baldwin 			break;
1618c0341432SJohn Baldwin #ifdef INVARIANTS
1619c0341432SJohn Baldwin 		default:
1620c0341432SJohn Baldwin 			panic("bad aead algo");
1621c0341432SJohn Baldwin #endif
1622c0341432SJohn Baldwin 		}
1623c0341432SJohn Baldwin 		break;
1624c0341432SJohn Baldwin 	case CSP_MODE_ETA:
1625c0341432SJohn Baldwin #ifdef INVARIANTS
1626c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
1627c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
1628c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
1629dd2e1352SJohn Baldwin 		case CRYPTO_CHACHA20_POLY1305:
1630c0341432SJohn Baldwin 			panic("bad eta cipher algo");
1631c0341432SJohn Baldwin 		}
1632c0341432SJohn Baldwin 		switch (csp->csp_auth_alg) {
1633c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GMAC:
1634c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_CBC_MAC:
1635c0341432SJohn Baldwin 			panic("bad eta auth algo");
1636c0341432SJohn Baldwin 		}
1637c0341432SJohn Baldwin #endif
1638c0341432SJohn Baldwin 
1639c0341432SJohn Baldwin 		error = swcr_setup_auth(ses, csp);
1640c0341432SJohn Baldwin 		if (error)
1641c0341432SJohn Baldwin 			break;
1642c0341432SJohn Baldwin 		if (csp->csp_cipher_alg == CRYPTO_NULL_CBC) {
1643c0341432SJohn Baldwin 			/* Effectively degrade to digest mode. */
1644c0341432SJohn Baldwin 			ses->swcr_process = swcr_authcompute;
1645c0341432SJohn Baldwin 			break;
1646c0341432SJohn Baldwin 		}
1647c0341432SJohn Baldwin 
16483e947048SJohn Baldwin 		error = swcr_setup_cipher(ses, csp);
1649c0341432SJohn Baldwin 		if (error == 0)
1650c0341432SJohn Baldwin 			ses->swcr_process = swcr_eta;
1651c0341432SJohn Baldwin 		break;
1652c0341432SJohn Baldwin 	default:
1653c0341432SJohn Baldwin 		error = EINVAL;
1654c0341432SJohn Baldwin 	}
1655c0341432SJohn Baldwin 
1656c0341432SJohn Baldwin 	if (error)
1657c0341432SJohn Baldwin 		swcr_freesession(dev, cses);
1658c0341432SJohn Baldwin 	return (error);
1659c0341432SJohn Baldwin }
1660c0341432SJohn Baldwin 
1661c0341432SJohn Baldwin static void
1662c0341432SJohn Baldwin swcr_freesession(device_t dev, crypto_session_t cses)
1663c0341432SJohn Baldwin {
1664c0341432SJohn Baldwin 	struct swcr_session *ses;
1665c0341432SJohn Baldwin 
1666c0341432SJohn Baldwin 	ses = crypto_get_driver_session(cses);
1667c0341432SJohn Baldwin 
1668c0341432SJohn Baldwin 	mtx_destroy(&ses->swcr_lock);
1669c0341432SJohn Baldwin 
16703e947048SJohn Baldwin 	zfree(ses->swcr_encdec.sw_kschedule, M_CRYPTO_DATA);
16714a711b8dSJohn Baldwin 	zfree(ses->swcr_auth.sw_ictx, M_CRYPTO_DATA);
16724a711b8dSJohn Baldwin 	zfree(ses->swcr_auth.sw_octx, M_CRYPTO_DATA);
1673091d81d1SSam Leffler }
1674091d81d1SSam Leffler 
1675091d81d1SSam Leffler /*
1676091d81d1SSam Leffler  * Process a software request.
1677091d81d1SSam Leffler  */
1678091d81d1SSam Leffler static int
16796810ad6fSSam Leffler swcr_process(device_t dev, struct cryptop *crp, int hint)
1680091d81d1SSam Leffler {
1681c0341432SJohn Baldwin 	struct swcr_session *ses;
1682091d81d1SSam Leffler 
16831b0909d5SConrad Meyer 	ses = crypto_get_driver_session(crp->crp_session);
1684a7fcb1afSSean Eric Fagan 	mtx_lock(&ses->swcr_lock);
1685091d81d1SSam Leffler 
1686c0341432SJohn Baldwin 	crp->crp_etype = ses->swcr_process(ses, crp);
1687091d81d1SSam Leffler 
1688a7fcb1afSSean Eric Fagan 	mtx_unlock(&ses->swcr_lock);
1689091d81d1SSam Leffler 	crypto_done(crp);
1690c0341432SJohn Baldwin 	return (0);
1691091d81d1SSam Leffler }
1692091d81d1SSam Leffler 
1693091d81d1SSam Leffler static void
16943f147ab2SWarner Losh swcr_identify(driver_t *drv, device_t parent)
1695091d81d1SSam Leffler {
16966810ad6fSSam Leffler 	/* NB: order 10 is so we get attached after h/w devices */
16976810ad6fSSam Leffler 	if (device_find_child(parent, "cryptosoft", -1) == NULL &&
169886c585d9SMarius Strobl 	    BUS_ADD_CHILD(parent, 10, "cryptosoft", 0) == 0)
16996810ad6fSSam Leffler 		panic("cryptosoft: could not attach");
17006810ad6fSSam Leffler }
1701f6c4bc3bSPawel Jakub Dawidek 
17026810ad6fSSam Leffler static int
17036810ad6fSSam Leffler swcr_probe(device_t dev)
17046810ad6fSSam Leffler {
17056810ad6fSSam Leffler 	device_set_desc(dev, "software crypto");
17064fc60fa9SMark Johnston 	device_quiet(dev);
170786c585d9SMarius Strobl 	return (BUS_PROBE_NOWILDCARD);
17086810ad6fSSam Leffler }
1709f6c4bc3bSPawel Jakub Dawidek 
17106810ad6fSSam Leffler static int
17116810ad6fSSam Leffler swcr_attach(device_t dev)
17126810ad6fSSam Leffler {
17136810ad6fSSam Leffler 
17149ebbebe4SConrad Meyer 	swcr_id = crypto_get_driverid(dev, sizeof(struct swcr_session),
17156810ad6fSSam Leffler 			CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC);
17166810ad6fSSam Leffler 	if (swcr_id < 0) {
17176810ad6fSSam Leffler 		device_printf(dev, "cannot initialize!");
1718c0341432SJohn Baldwin 		return (ENXIO);
17196810ad6fSSam Leffler 	}
17206810ad6fSSam Leffler 
1721c0341432SJohn Baldwin 	return (0);
1722091d81d1SSam Leffler }
17234b465da2SPawel Jakub Dawidek 
17243f147ab2SWarner Losh static int
17256810ad6fSSam Leffler swcr_detach(device_t dev)
17264b465da2SPawel Jakub Dawidek {
17276810ad6fSSam Leffler 	crypto_unregister_all(swcr_id);
17283f147ab2SWarner Losh 	return 0;
17294b465da2SPawel Jakub Dawidek }
17306810ad6fSSam Leffler 
17316810ad6fSSam Leffler static device_method_t swcr_methods[] = {
17326810ad6fSSam Leffler 	DEVMETHOD(device_identify,	swcr_identify),
17336810ad6fSSam Leffler 	DEVMETHOD(device_probe,		swcr_probe),
17346810ad6fSSam Leffler 	DEVMETHOD(device_attach,	swcr_attach),
17356810ad6fSSam Leffler 	DEVMETHOD(device_detach,	swcr_detach),
17366810ad6fSSam Leffler 
1737c0341432SJohn Baldwin 	DEVMETHOD(cryptodev_probesession, swcr_probesession),
17386810ad6fSSam Leffler 	DEVMETHOD(cryptodev_newsession,	swcr_newsession),
17396810ad6fSSam Leffler 	DEVMETHOD(cryptodev_freesession,swcr_freesession),
17406810ad6fSSam Leffler 	DEVMETHOD(cryptodev_process,	swcr_process),
17416810ad6fSSam Leffler 
17426810ad6fSSam Leffler 	{0, 0},
17436810ad6fSSam Leffler };
17446810ad6fSSam Leffler 
17456810ad6fSSam Leffler static driver_t swcr_driver = {
17466810ad6fSSam Leffler 	"cryptosoft",
17476810ad6fSSam Leffler 	swcr_methods,
17486810ad6fSSam Leffler 	0,		/* NB: no softc */
17496810ad6fSSam Leffler };
17506810ad6fSSam Leffler static devclass_t swcr_devclass;
17516810ad6fSSam Leffler 
17526810ad6fSSam Leffler /*
17536810ad6fSSam Leffler  * NB: We explicitly reference the crypto module so we
17546810ad6fSSam Leffler  * get the necessary ordering when built as a loadable
17556810ad6fSSam Leffler  * module.  This is required because we bundle the crypto
17566810ad6fSSam Leffler  * module code together with the cryptosoft driver (otherwise
17576810ad6fSSam Leffler  * normal module dependencies would handle things).
17586810ad6fSSam Leffler  */
17596810ad6fSSam Leffler extern int crypto_modevent(struct module *, int, void *);
17606810ad6fSSam Leffler /* XXX where to attach */
17616810ad6fSSam Leffler DRIVER_MODULE(cryptosoft, nexus, swcr_driver, swcr_devclass, crypto_modevent,0);
17626810ad6fSSam Leffler MODULE_VERSION(cryptosoft, 1);
17636810ad6fSSam Leffler MODULE_DEPEND(cryptosoft, crypto, 1, 1, 1);
1764