xref: /f-stack/freebsd/opencrypto/cryptosoft.c (revision 22ce4aff)
1a9643ea8Slogwang /*	$OpenBSD: cryptosoft.c,v 1.35 2002/04/26 08:43:50 deraadt Exp $	*/
2a9643ea8Slogwang 
3a9643ea8Slogwang /*-
4a9643ea8Slogwang  * The author of this code is Angelos D. Keromytis ([email protected])
5a9643ea8Slogwang  * Copyright (c) 2002-2006 Sam Leffler, Errno Consulting
6a9643ea8Slogwang  *
7a9643ea8Slogwang  * This code was written by Angelos D. Keromytis in Athens, Greece, in
8a9643ea8Slogwang  * February 2000. Network Security Technologies Inc. (NSTI) kindly
9a9643ea8Slogwang  * supported the development of this code.
10a9643ea8Slogwang  *
11a9643ea8Slogwang  * Copyright (c) 2000, 2001 Angelos D. Keromytis
12a9643ea8Slogwang  * Copyright (c) 2014 The FreeBSD Foundation
13a9643ea8Slogwang  * All rights reserved.
14a9643ea8Slogwang  *
15a9643ea8Slogwang  * Portions of this software were developed by John-Mark Gurney
16a9643ea8Slogwang  * under sponsorship of the FreeBSD Foundation and
17a9643ea8Slogwang  * Rubicon Communications, LLC (Netgate).
18a9643ea8Slogwang  *
19a9643ea8Slogwang  * Permission to use, copy, and modify this software with or without fee
20a9643ea8Slogwang  * is hereby granted, provided that this entire notice is included in
21a9643ea8Slogwang  * all source code copies of any software which is or includes a copy or
22a9643ea8Slogwang  * modification of this software.
23a9643ea8Slogwang  *
24a9643ea8Slogwang  * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
25a9643ea8Slogwang  * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
26a9643ea8Slogwang  * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
27a9643ea8Slogwang  * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
28a9643ea8Slogwang  * PURPOSE.
29a9643ea8Slogwang  */
30a9643ea8Slogwang 
31a9643ea8Slogwang #include <sys/cdefs.h>
32a9643ea8Slogwang __FBSDID("$FreeBSD$");
33a9643ea8Slogwang 
34a9643ea8Slogwang #include <sys/param.h>
35a9643ea8Slogwang #include <sys/systm.h>
36a9643ea8Slogwang #include <sys/malloc.h>
37a9643ea8Slogwang #include <sys/mbuf.h>
38a9643ea8Slogwang #include <sys/module.h>
39a9643ea8Slogwang #include <sys/sysctl.h>
40a9643ea8Slogwang #include <sys/errno.h>
41a9643ea8Slogwang #include <sys/random.h>
42a9643ea8Slogwang #include <sys/kernel.h>
43a9643ea8Slogwang #include <sys/uio.h>
44a9643ea8Slogwang #include <sys/lock.h>
45a9643ea8Slogwang #include <sys/rwlock.h>
46a9643ea8Slogwang #include <sys/endian.h>
47a9643ea8Slogwang #include <sys/limits.h>
48*22ce4affSfengbojiang #include <sys/mutex.h>
49a9643ea8Slogwang 
50a9643ea8Slogwang #include <crypto/sha1.h>
51a9643ea8Slogwang #include <opencrypto/rmd160.h>
52a9643ea8Slogwang 
53a9643ea8Slogwang #include <opencrypto/cryptodev.h>
54a9643ea8Slogwang #include <opencrypto/xform.h>
55a9643ea8Slogwang 
56a9643ea8Slogwang #include <sys/kobj.h>
57a9643ea8Slogwang #include <sys/bus.h>
58a9643ea8Slogwang #include "cryptodev_if.h"
59a9643ea8Slogwang 
60*22ce4affSfengbojiang struct swcr_auth {
61*22ce4affSfengbojiang 	void		*sw_ictx;
62*22ce4affSfengbojiang 	void		*sw_octx;
63*22ce4affSfengbojiang 	struct auth_hash *sw_axf;
64*22ce4affSfengbojiang 	uint16_t	sw_mlen;
65*22ce4affSfengbojiang };
66*22ce4affSfengbojiang 
67*22ce4affSfengbojiang struct swcr_encdec {
68*22ce4affSfengbojiang 	void		*sw_kschedule;
69*22ce4affSfengbojiang 	struct enc_xform *sw_exf;
70*22ce4affSfengbojiang };
71*22ce4affSfengbojiang 
72*22ce4affSfengbojiang struct swcr_compdec {
73*22ce4affSfengbojiang 	struct comp_algo *sw_cxf;
74*22ce4affSfengbojiang };
75*22ce4affSfengbojiang 
76*22ce4affSfengbojiang struct swcr_session {
77*22ce4affSfengbojiang 	struct mtx	swcr_lock;
78*22ce4affSfengbojiang 	int	(*swcr_process)(struct swcr_session *, struct cryptop *);
79*22ce4affSfengbojiang 
80*22ce4affSfengbojiang 	struct swcr_auth swcr_auth;
81*22ce4affSfengbojiang 	struct swcr_encdec swcr_encdec;
82*22ce4affSfengbojiang 	struct swcr_compdec swcr_compdec;
83*22ce4affSfengbojiang };
84*22ce4affSfengbojiang 
85a9643ea8Slogwang static	int32_t swcr_id;
86a9643ea8Slogwang 
87*22ce4affSfengbojiang static	void swcr_freesession(device_t dev, crypto_session_t cses);
88a9643ea8Slogwang 
89*22ce4affSfengbojiang /* Used for CRYPTO_NULL_CBC. */
90*22ce4affSfengbojiang static int
swcr_null(struct swcr_session * ses,struct cryptop * crp)91*22ce4affSfengbojiang swcr_null(struct swcr_session *ses, struct cryptop *crp)
92*22ce4affSfengbojiang {
93*22ce4affSfengbojiang 
94*22ce4affSfengbojiang 	return (0);
95*22ce4affSfengbojiang }
96a9643ea8Slogwang 
97a9643ea8Slogwang /*
98a9643ea8Slogwang  * Apply a symmetric encryption/decryption algorithm.
99a9643ea8Slogwang  */
100a9643ea8Slogwang static int
swcr_encdec(struct swcr_session * ses,struct cryptop * crp)101*22ce4affSfengbojiang swcr_encdec(struct swcr_session *ses, struct cryptop *crp)
102a9643ea8Slogwang {
103*22ce4affSfengbojiang 	unsigned char iv[EALG_MAX_BLOCK_LEN], blk[EALG_MAX_BLOCK_LEN];
104a9643ea8Slogwang 	unsigned char *ivp, *nivp, iv2[EALG_MAX_BLOCK_LEN];
105*22ce4affSfengbojiang 	const struct crypto_session_params *csp;
106*22ce4affSfengbojiang 	struct swcr_encdec *sw;
107a9643ea8Slogwang 	struct enc_xform *exf;
108*22ce4affSfengbojiang 	int i, blks, inlen, ivlen, outlen, resid;
109*22ce4affSfengbojiang 	struct crypto_buffer_cursor cc_in, cc_out;
110*22ce4affSfengbojiang 	const unsigned char *inblk;
111*22ce4affSfengbojiang 	unsigned char *outblk;
112a9643ea8Slogwang 	int error;
113*22ce4affSfengbojiang 	bool encrypting;
114a9643ea8Slogwang 
115a9643ea8Slogwang 	error = 0;
116a9643ea8Slogwang 
117*22ce4affSfengbojiang 	sw = &ses->swcr_encdec;
118a9643ea8Slogwang 	exf = sw->sw_exf;
119a9643ea8Slogwang 	ivlen = exf->ivsize;
120a9643ea8Slogwang 
121*22ce4affSfengbojiang 	if (exf->native_blocksize == 0) {
122a9643ea8Slogwang 		/* Check for non-padded data */
123*22ce4affSfengbojiang 		if ((crp->crp_payload_length % exf->blocksize) != 0)
124a9643ea8Slogwang 			return (EINVAL);
125a9643ea8Slogwang 
126*22ce4affSfengbojiang 		blks = exf->blocksize;
127*22ce4affSfengbojiang 	} else
128*22ce4affSfengbojiang 		blks = exf->native_blocksize;
129a9643ea8Slogwang 
130*22ce4affSfengbojiang 	if (exf == &enc_xform_aes_icm &&
131*22ce4affSfengbojiang 	    (crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0)
132*22ce4affSfengbojiang 		return (EINVAL);
133a9643ea8Slogwang 
134*22ce4affSfengbojiang 	if (crp->crp_cipher_key != NULL) {
135*22ce4affSfengbojiang 		csp = crypto_get_params(crp->crp_session);
136*22ce4affSfengbojiang 		error = exf->setkey(sw->sw_kschedule,
137*22ce4affSfengbojiang 		    crp->crp_cipher_key, csp->csp_cipher_klen);
138a9643ea8Slogwang 		if (error)
139a9643ea8Slogwang 			return (error);
140a9643ea8Slogwang 	}
141a9643ea8Slogwang 
142*22ce4affSfengbojiang 	crypto_read_iv(crp, iv);
143a9643ea8Slogwang 
144a9643ea8Slogwang 	if (exf->reinit) {
145a9643ea8Slogwang 		/*
146a9643ea8Slogwang 		 * xforms that provide a reinit method perform all IV
147a9643ea8Slogwang 		 * handling themselves.
148a9643ea8Slogwang 		 */
149a9643ea8Slogwang 		exf->reinit(sw->sw_kschedule, iv);
150a9643ea8Slogwang 	}
151a9643ea8Slogwang 
152*22ce4affSfengbojiang 	ivp = iv;
153a9643ea8Slogwang 
154*22ce4affSfengbojiang 	crypto_cursor_init(&cc_in, &crp->crp_buf);
155*22ce4affSfengbojiang 	crypto_cursor_advance(&cc_in, crp->crp_payload_start);
156*22ce4affSfengbojiang 	inlen = crypto_cursor_seglen(&cc_in);
157*22ce4affSfengbojiang 	inblk = crypto_cursor_segbase(&cc_in);
158*22ce4affSfengbojiang 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
159*22ce4affSfengbojiang 		crypto_cursor_init(&cc_out, &crp->crp_obuf);
160*22ce4affSfengbojiang 		crypto_cursor_advance(&cc_out, crp->crp_payload_output_start);
161*22ce4affSfengbojiang 	} else
162*22ce4affSfengbojiang 		cc_out = cc_in;
163*22ce4affSfengbojiang 	outlen = crypto_cursor_seglen(&cc_out);
164*22ce4affSfengbojiang 	outblk = crypto_cursor_segbase(&cc_out);
165a9643ea8Slogwang 
166*22ce4affSfengbojiang 	resid = crp->crp_payload_length;
167*22ce4affSfengbojiang 	encrypting = CRYPTO_OP_IS_ENCRYPT(crp->crp_op);
168*22ce4affSfengbojiang 
169a9643ea8Slogwang 	/*
170*22ce4affSfengbojiang 	 * Loop through encrypting blocks.  'inlen' is the remaining
171*22ce4affSfengbojiang 	 * length of the current segment in the input buffer.
172*22ce4affSfengbojiang 	 * 'outlen' is the remaining length of current segment in the
173*22ce4affSfengbojiang 	 * output buffer.
174a9643ea8Slogwang 	 */
175*22ce4affSfengbojiang 	while (resid >= blks) {
176*22ce4affSfengbojiang 		/*
177*22ce4affSfengbojiang 		 * If the current block is not contained within the
178*22ce4affSfengbojiang 		 * current input/output segment, use 'blk' as a local
179*22ce4affSfengbojiang 		 * buffer.
180*22ce4affSfengbojiang 		 */
181*22ce4affSfengbojiang 		if (inlen < blks) {
182*22ce4affSfengbojiang 			crypto_cursor_copydata(&cc_in, blks, blk);
183*22ce4affSfengbojiang 			inblk = blk;
184a9643ea8Slogwang 		}
185*22ce4affSfengbojiang 		if (outlen < blks)
186*22ce4affSfengbojiang 			outblk = blk;
187a9643ea8Slogwang 
188*22ce4affSfengbojiang 		/*
189*22ce4affSfengbojiang 		 * Ciphers without a 'reinit' hook are assumed to be
190*22ce4affSfengbojiang 		 * used in CBC mode where the chaining is done here.
191*22ce4affSfengbojiang 		 */
192*22ce4affSfengbojiang 		if (exf->reinit != NULL) {
193*22ce4affSfengbojiang 			if (encrypting)
194*22ce4affSfengbojiang 				exf->encrypt(sw->sw_kschedule, inblk, outblk);
195*22ce4affSfengbojiang 			else
196*22ce4affSfengbojiang 				exf->decrypt(sw->sw_kschedule, inblk, outblk);
197*22ce4affSfengbojiang 		} else if (encrypting) {
198*22ce4affSfengbojiang 			/* XOR with previous block */
199*22ce4affSfengbojiang 			for (i = 0; i < blks; i++)
200*22ce4affSfengbojiang 				outblk[i] = inblk[i] ^ ivp[i];
201*22ce4affSfengbojiang 
202*22ce4affSfengbojiang 			exf->encrypt(sw->sw_kschedule, outblk, outblk);
203a9643ea8Slogwang 
204a9643ea8Slogwang 			/*
205a9643ea8Slogwang 			 * Keep encrypted block for XOR'ing
206a9643ea8Slogwang 			 * with next block
207a9643ea8Slogwang 			 */
208*22ce4affSfengbojiang 			memcpy(iv, outblk, blks);
209a9643ea8Slogwang 			ivp = iv;
210a9643ea8Slogwang 		} else {	/* decrypt */
211a9643ea8Slogwang 			/*
212a9643ea8Slogwang 			 * Keep encrypted block for XOR'ing
213a9643ea8Slogwang 			 * with next block
214a9643ea8Slogwang 			 */
215a9643ea8Slogwang 			nivp = (ivp == iv) ? iv2 : iv;
216*22ce4affSfengbojiang 			memcpy(nivp, inblk, blks);
217a9643ea8Slogwang 
218*22ce4affSfengbojiang 			exf->decrypt(sw->sw_kschedule, inblk, outblk);
219a9643ea8Slogwang 
220a9643ea8Slogwang 			/* XOR with previous block */
221*22ce4affSfengbojiang 			for (i = 0; i < blks; i++)
222*22ce4affSfengbojiang 				outblk[i] ^= ivp[i];
223a9643ea8Slogwang 
224a9643ea8Slogwang 			ivp = nivp;
225a9643ea8Slogwang 		}
226a9643ea8Slogwang 
227*22ce4affSfengbojiang 		if (inlen < blks) {
228*22ce4affSfengbojiang 			inlen = crypto_cursor_seglen(&cc_in);
229*22ce4affSfengbojiang 			inblk = crypto_cursor_segbase(&cc_in);
230a9643ea8Slogwang 		} else {
231*22ce4affSfengbojiang 			crypto_cursor_advance(&cc_in, blks);
232*22ce4affSfengbojiang 			inlen -= blks;
233*22ce4affSfengbojiang 			inblk += blks;
234a9643ea8Slogwang 		}
235a9643ea8Slogwang 
236*22ce4affSfengbojiang 		if (outlen < blks) {
237*22ce4affSfengbojiang 			crypto_cursor_copyback(&cc_out, blks, blk);
238*22ce4affSfengbojiang 			outlen = crypto_cursor_seglen(&cc_out);
239*22ce4affSfengbojiang 			outblk = crypto_cursor_segbase(&cc_out);
240*22ce4affSfengbojiang 		} else {
241*22ce4affSfengbojiang 			crypto_cursor_advance(&cc_out, blks);
242*22ce4affSfengbojiang 			outlen -= blks;
243*22ce4affSfengbojiang 			outblk += blks;
244a9643ea8Slogwang 		}
245a9643ea8Slogwang 
246*22ce4affSfengbojiang 		resid -= blks;
247a9643ea8Slogwang 	}
248a9643ea8Slogwang 
249*22ce4affSfengbojiang 	/* Handle trailing partial block for stream ciphers. */
250*22ce4affSfengbojiang 	if (resid > 0) {
251*22ce4affSfengbojiang 		KASSERT(exf->native_blocksize != 0,
252*22ce4affSfengbojiang 		    ("%s: partial block of %d bytes for cipher %s",
253*22ce4affSfengbojiang 		    __func__, i, exf->name));
254*22ce4affSfengbojiang 		KASSERT(exf->reinit != NULL,
255*22ce4affSfengbojiang 		    ("%s: partial block cipher %s without reinit hook",
256*22ce4affSfengbojiang 		    __func__, exf->name));
257*22ce4affSfengbojiang 		KASSERT(resid < blks, ("%s: partial block too big", __func__));
258a9643ea8Slogwang 
259*22ce4affSfengbojiang 		inlen = crypto_cursor_seglen(&cc_in);
260*22ce4affSfengbojiang 		outlen = crypto_cursor_seglen(&cc_out);
261*22ce4affSfengbojiang 		if (inlen < resid) {
262*22ce4affSfengbojiang 			crypto_cursor_copydata(&cc_in, resid, blk);
263*22ce4affSfengbojiang 			inblk = blk;
264*22ce4affSfengbojiang 		} else
265*22ce4affSfengbojiang 			inblk = crypto_cursor_segbase(&cc_in);
266*22ce4affSfengbojiang 		if (outlen < resid)
267*22ce4affSfengbojiang 			outblk = blk;
268*22ce4affSfengbojiang 		else
269*22ce4affSfengbojiang 			outblk = crypto_cursor_segbase(&cc_out);
270*22ce4affSfengbojiang 		if (encrypting)
271*22ce4affSfengbojiang 			exf->encrypt_last(sw->sw_kschedule, inblk, outblk,
272*22ce4affSfengbojiang 			    resid);
273*22ce4affSfengbojiang 		else
274*22ce4affSfengbojiang 			exf->decrypt_last(sw->sw_kschedule, inblk, outblk,
275*22ce4affSfengbojiang 			    resid);
276*22ce4affSfengbojiang 		if (outlen < resid)
277*22ce4affSfengbojiang 			crypto_cursor_copyback(&cc_out, resid, blk);
278*22ce4affSfengbojiang 	}
279*22ce4affSfengbojiang 
280*22ce4affSfengbojiang 	explicit_bzero(blk, sizeof(blk));
281*22ce4affSfengbojiang 	explicit_bzero(iv, sizeof(iv));
282*22ce4affSfengbojiang 	explicit_bzero(iv2, sizeof(iv2));
283*22ce4affSfengbojiang 	return (0);
284a9643ea8Slogwang }
285a9643ea8Slogwang 
286a9643ea8Slogwang static void
swcr_authprepare(struct auth_hash * axf,struct swcr_auth * sw,const uint8_t * key,int klen)287*22ce4affSfengbojiang swcr_authprepare(struct auth_hash *axf, struct swcr_auth *sw,
288*22ce4affSfengbojiang     const uint8_t *key, int klen)
289a9643ea8Slogwang {
290a9643ea8Slogwang 
291a9643ea8Slogwang 	switch (axf->type) {
292a9643ea8Slogwang 	case CRYPTO_SHA1_HMAC:
293*22ce4affSfengbojiang 	case CRYPTO_SHA2_224_HMAC:
294a9643ea8Slogwang 	case CRYPTO_SHA2_256_HMAC:
295a9643ea8Slogwang 	case CRYPTO_SHA2_384_HMAC:
296a9643ea8Slogwang 	case CRYPTO_SHA2_512_HMAC:
297a9643ea8Slogwang 	case CRYPTO_NULL_HMAC:
298a9643ea8Slogwang 	case CRYPTO_RIPEMD160_HMAC:
299*22ce4affSfengbojiang 		hmac_init_ipad(axf, key, klen, sw->sw_ictx);
300*22ce4affSfengbojiang 		hmac_init_opad(axf, key, klen, sw->sw_octx);
301a9643ea8Slogwang 		break;
302*22ce4affSfengbojiang 	case CRYPTO_POLY1305:
303*22ce4affSfengbojiang 	case CRYPTO_BLAKE2B:
304*22ce4affSfengbojiang 	case CRYPTO_BLAKE2S:
305*22ce4affSfengbojiang 		axf->Setkey(sw->sw_ictx, key, klen);
306a9643ea8Slogwang 		axf->Init(sw->sw_ictx);
307a9643ea8Slogwang 		break;
308a9643ea8Slogwang 	default:
309*22ce4affSfengbojiang 		panic("%s: algorithm %d doesn't use keys", __func__, axf->type);
310a9643ea8Slogwang 	}
311a9643ea8Slogwang }
312a9643ea8Slogwang 
313a9643ea8Slogwang /*
314*22ce4affSfengbojiang  * Compute or verify hash.
315a9643ea8Slogwang  */
316a9643ea8Slogwang static int
swcr_authcompute(struct swcr_session * ses,struct cryptop * crp)317*22ce4affSfengbojiang swcr_authcompute(struct swcr_session *ses, struct cryptop *crp)
318a9643ea8Slogwang {
319*22ce4affSfengbojiang 	u_char aalg[HASH_MAX_LEN];
320*22ce4affSfengbojiang 	const struct crypto_session_params *csp;
321*22ce4affSfengbojiang 	struct swcr_auth *sw;
322a9643ea8Slogwang 	struct auth_hash *axf;
323a9643ea8Slogwang 	union authctx ctx;
324a9643ea8Slogwang 	int err;
325a9643ea8Slogwang 
326*22ce4affSfengbojiang 	sw = &ses->swcr_auth;
327a9643ea8Slogwang 
328a9643ea8Slogwang 	axf = sw->sw_axf;
329a9643ea8Slogwang 
330*22ce4affSfengbojiang 	csp = crypto_get_params(crp->crp_session);
331*22ce4affSfengbojiang 	if (crp->crp_auth_key != NULL) {
332*22ce4affSfengbojiang 		swcr_authprepare(axf, sw, crp->crp_auth_key,
333*22ce4affSfengbojiang 		    csp->csp_auth_klen);
334*22ce4affSfengbojiang 	}
335a9643ea8Slogwang 
336a9643ea8Slogwang 	bcopy(sw->sw_ictx, &ctx, axf->ctxsize);
337a9643ea8Slogwang 
338*22ce4affSfengbojiang 	if (crp->crp_aad != NULL)
339*22ce4affSfengbojiang 		err = axf->Update(&ctx, crp->crp_aad, crp->crp_aad_length);
340*22ce4affSfengbojiang 	else
341*22ce4affSfengbojiang 		err = crypto_apply(crp, crp->crp_aad_start, crp->crp_aad_length,
342*22ce4affSfengbojiang 		    axf->Update, &ctx);
343a9643ea8Slogwang 	if (err)
344*22ce4affSfengbojiang 		goto out;
345a9643ea8Slogwang 
346*22ce4affSfengbojiang 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp) &&
347*22ce4affSfengbojiang 	    CRYPTO_OP_IS_ENCRYPT(crp->crp_op))
348*22ce4affSfengbojiang 		err = crypto_apply_buf(&crp->crp_obuf,
349*22ce4affSfengbojiang 		    crp->crp_payload_output_start, crp->crp_payload_length,
350*22ce4affSfengbojiang 		    axf->Update, &ctx);
351*22ce4affSfengbojiang 	else
352*22ce4affSfengbojiang 		err = crypto_apply(crp, crp->crp_payload_start,
353*22ce4affSfengbojiang 		    crp->crp_payload_length, axf->Update, &ctx);
354*22ce4affSfengbojiang 	if (err)
355*22ce4affSfengbojiang 		goto out;
356*22ce4affSfengbojiang 
357*22ce4affSfengbojiang 	if (csp->csp_flags & CSP_F_ESN)
358*22ce4affSfengbojiang 		axf->Update(&ctx, crp->crp_esn, 4);
359a9643ea8Slogwang 
360a9643ea8Slogwang 	axf->Final(aalg, &ctx);
361*22ce4affSfengbojiang 	if (sw->sw_octx != NULL) {
362a9643ea8Slogwang 		bcopy(sw->sw_octx, &ctx, axf->ctxsize);
363a9643ea8Slogwang 		axf->Update(&ctx, aalg, axf->hashsize);
364a9643ea8Slogwang 		axf->Final(aalg, &ctx);
365a9643ea8Slogwang 	}
366a9643ea8Slogwang 
367*22ce4affSfengbojiang 	if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
368*22ce4affSfengbojiang 		u_char uaalg[HASH_MAX_LEN];
369*22ce4affSfengbojiang 
370*22ce4affSfengbojiang 		crypto_copydata(crp, crp->crp_digest_start, sw->sw_mlen, uaalg);
371*22ce4affSfengbojiang 		if (timingsafe_bcmp(aalg, uaalg, sw->sw_mlen) != 0)
372*22ce4affSfengbojiang 			err = EBADMSG;
373*22ce4affSfengbojiang 		explicit_bzero(uaalg, sizeof(uaalg));
374*22ce4affSfengbojiang 	} else {
375a9643ea8Slogwang 		/* Inject the authentication data */
376*22ce4affSfengbojiang 		crypto_copyback(crp, crp->crp_digest_start, sw->sw_mlen, aalg);
377*22ce4affSfengbojiang 	}
378*22ce4affSfengbojiang 	explicit_bzero(aalg, sizeof(aalg));
379*22ce4affSfengbojiang out:
380*22ce4affSfengbojiang 	explicit_bzero(&ctx, sizeof(ctx));
381*22ce4affSfengbojiang 	return (err);
382a9643ea8Slogwang }
383a9643ea8Slogwang 
384a9643ea8Slogwang CTASSERT(INT_MAX <= (1ll<<39) - 256);	/* GCM: plain text < 2^39-256 */
385a9643ea8Slogwang CTASSERT(INT_MAX <= (uint64_t)-1);	/* GCM: associated data <= 2^64-1 */
386a9643ea8Slogwang 
387a9643ea8Slogwang static int
swcr_gmac(struct swcr_session * ses,struct cryptop * crp)388*22ce4affSfengbojiang swcr_gmac(struct swcr_session *ses, struct cryptop *crp)
389a9643ea8Slogwang {
390*22ce4affSfengbojiang 	uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))];
391a9643ea8Slogwang 	u_char *blk = (u_char *)blkbuf;
392*22ce4affSfengbojiang 	u_char tag[GMAC_DIGEST_LEN];
393*22ce4affSfengbojiang 	u_char iv[AES_BLOCK_LEN];
394*22ce4affSfengbojiang 	struct crypto_buffer_cursor cc;
395*22ce4affSfengbojiang 	const u_char *inblk;
396a9643ea8Slogwang 	union authctx ctx;
397*22ce4affSfengbojiang 	struct swcr_auth *swa;
398*22ce4affSfengbojiang 	struct auth_hash *axf;
399a9643ea8Slogwang 	uint32_t *blkp;
400*22ce4affSfengbojiang 	int blksz, error, ivlen, len, resid;
401a9643ea8Slogwang 
402*22ce4affSfengbojiang 	swa = &ses->swcr_auth;
403a9643ea8Slogwang 	axf = swa->sw_axf;
404*22ce4affSfengbojiang 
405a9643ea8Slogwang 	bcopy(swa->sw_ictx, &ctx, axf->ctxsize);
406*22ce4affSfengbojiang 	blksz = GMAC_BLOCK_LEN;
407*22ce4affSfengbojiang 	KASSERT(axf->blocksize == blksz, ("%s: axf block size mismatch",
408*22ce4affSfengbojiang 	    __func__));
409a9643ea8Slogwang 
410*22ce4affSfengbojiang 	/* Initialize the IV */
411*22ce4affSfengbojiang 	ivlen = AES_GCM_IV_LEN;
412*22ce4affSfengbojiang 	crypto_read_iv(crp, iv);
413a9643ea8Slogwang 
414*22ce4affSfengbojiang 	axf->Reinit(&ctx, iv, ivlen);
415*22ce4affSfengbojiang 	crypto_cursor_init(&cc, &crp->crp_buf);
416*22ce4affSfengbojiang 	crypto_cursor_advance(&cc, crp->crp_payload_start);
417*22ce4affSfengbojiang 	for (resid = crp->crp_payload_length; resid >= blksz; resid -= len) {
418*22ce4affSfengbojiang 		len = crypto_cursor_seglen(&cc);
419*22ce4affSfengbojiang 		if (len >= blksz) {
420*22ce4affSfengbojiang 			inblk = crypto_cursor_segbase(&cc);
421*22ce4affSfengbojiang 			len = rounddown(MIN(len, resid), blksz);
422*22ce4affSfengbojiang 			crypto_cursor_advance(&cc, len);
423*22ce4affSfengbojiang 		} else {
424*22ce4affSfengbojiang 			len = blksz;
425*22ce4affSfengbojiang 			crypto_cursor_copydata(&cc, len, blk);
426*22ce4affSfengbojiang 			inblk = blk;
427*22ce4affSfengbojiang 		}
428*22ce4affSfengbojiang 		axf->Update(&ctx, inblk, len);
429*22ce4affSfengbojiang 	}
430*22ce4affSfengbojiang 	if (resid > 0) {
431*22ce4affSfengbojiang 		memset(blk, 0, blksz);
432*22ce4affSfengbojiang 		crypto_cursor_copydata(&cc, resid, blk);
433*22ce4affSfengbojiang 		axf->Update(&ctx, blk, blksz);
434*22ce4affSfengbojiang 	}
435*22ce4affSfengbojiang 
436*22ce4affSfengbojiang 	/* length block */
437*22ce4affSfengbojiang 	memset(blk, 0, blksz);
438*22ce4affSfengbojiang 	blkp = (uint32_t *)blk + 1;
439*22ce4affSfengbojiang 	*blkp = htobe32(crp->crp_payload_length * 8);
440*22ce4affSfengbojiang 	axf->Update(&ctx, blk, blksz);
441*22ce4affSfengbojiang 
442*22ce4affSfengbojiang 	/* Finalize MAC */
443*22ce4affSfengbojiang 	axf->Final(tag, &ctx);
444*22ce4affSfengbojiang 
445*22ce4affSfengbojiang 	error = 0;
446*22ce4affSfengbojiang 	if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
447*22ce4affSfengbojiang 		u_char tag2[GMAC_DIGEST_LEN];
448*22ce4affSfengbojiang 
449*22ce4affSfengbojiang 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen,
450*22ce4affSfengbojiang 		    tag2);
451*22ce4affSfengbojiang 		if (timingsafe_bcmp(tag, tag2, swa->sw_mlen) != 0)
452*22ce4affSfengbojiang 			error = EBADMSG;
453*22ce4affSfengbojiang 		explicit_bzero(tag2, sizeof(tag2));
454*22ce4affSfengbojiang 	} else {
455*22ce4affSfengbojiang 		/* Inject the authentication data */
456*22ce4affSfengbojiang 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag);
457*22ce4affSfengbojiang 	}
458*22ce4affSfengbojiang 	explicit_bzero(blkbuf, sizeof(blkbuf));
459*22ce4affSfengbojiang 	explicit_bzero(tag, sizeof(tag));
460*22ce4affSfengbojiang 	explicit_bzero(iv, sizeof(iv));
461*22ce4affSfengbojiang 	return (error);
462*22ce4affSfengbojiang }
463*22ce4affSfengbojiang 
464*22ce4affSfengbojiang static int
swcr_gcm(struct swcr_session * ses,struct cryptop * crp)465*22ce4affSfengbojiang swcr_gcm(struct swcr_session *ses, struct cryptop *crp)
466*22ce4affSfengbojiang {
467*22ce4affSfengbojiang 	uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))];
468*22ce4affSfengbojiang 	u_char *blk = (u_char *)blkbuf;
469*22ce4affSfengbojiang 	u_char tag[GMAC_DIGEST_LEN];
470*22ce4affSfengbojiang 	u_char iv[AES_BLOCK_LEN];
471*22ce4affSfengbojiang 	struct crypto_buffer_cursor cc_in, cc_out;
472*22ce4affSfengbojiang 	const u_char *inblk;
473*22ce4affSfengbojiang 	u_char *outblk;
474*22ce4affSfengbojiang 	union authctx ctx;
475*22ce4affSfengbojiang 	struct swcr_auth *swa;
476*22ce4affSfengbojiang 	struct swcr_encdec *swe;
477*22ce4affSfengbojiang 	struct auth_hash *axf;
478*22ce4affSfengbojiang 	struct enc_xform *exf;
479*22ce4affSfengbojiang 	uint32_t *blkp;
480*22ce4affSfengbojiang 	int blksz, error, ivlen, len, r, resid;
481*22ce4affSfengbojiang 
482*22ce4affSfengbojiang 	swa = &ses->swcr_auth;
483*22ce4affSfengbojiang 	axf = swa->sw_axf;
484*22ce4affSfengbojiang 
485*22ce4affSfengbojiang 	bcopy(swa->sw_ictx, &ctx, axf->ctxsize);
486*22ce4affSfengbojiang 	blksz = GMAC_BLOCK_LEN;
487*22ce4affSfengbojiang 	KASSERT(axf->blocksize == blksz, ("%s: axf block size mismatch",
488*22ce4affSfengbojiang 	    __func__));
489*22ce4affSfengbojiang 
490*22ce4affSfengbojiang 	swe = &ses->swcr_encdec;
491*22ce4affSfengbojiang 	exf = swe->sw_exf;
492*22ce4affSfengbojiang 	KASSERT(axf->blocksize == exf->native_blocksize,
493*22ce4affSfengbojiang 	    ("%s: blocksize mismatch", __func__));
494*22ce4affSfengbojiang 
495*22ce4affSfengbojiang 	if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0)
496a9643ea8Slogwang 		return (EINVAL);
497a9643ea8Slogwang 
498a9643ea8Slogwang 	/* Initialize the IV */
499*22ce4affSfengbojiang 	ivlen = AES_GCM_IV_LEN;
500*22ce4affSfengbojiang 	bcopy(crp->crp_iv, iv, ivlen);
501a9643ea8Slogwang 
502a9643ea8Slogwang 	/* Supply MAC with IV */
503a9643ea8Slogwang 	axf->Reinit(&ctx, iv, ivlen);
504a9643ea8Slogwang 
505a9643ea8Slogwang 	/* Supply MAC with AAD */
506*22ce4affSfengbojiang 	if (crp->crp_aad != NULL) {
507*22ce4affSfengbojiang 		len = rounddown(crp->crp_aad_length, blksz);
508*22ce4affSfengbojiang 		if (len != 0)
509*22ce4affSfengbojiang 			axf->Update(&ctx, crp->crp_aad, len);
510*22ce4affSfengbojiang 		if (crp->crp_aad_length != len) {
511*22ce4affSfengbojiang 			memset(blk, 0, blksz);
512*22ce4affSfengbojiang 			memcpy(blk, (char *)crp->crp_aad + len,
513*22ce4affSfengbojiang 			    crp->crp_aad_length - len);
514a9643ea8Slogwang 			axf->Update(&ctx, blk, blksz);
515*22ce4affSfengbojiang 		}
516*22ce4affSfengbojiang 	} else {
517*22ce4affSfengbojiang 		crypto_cursor_init(&cc_in, &crp->crp_buf);
518*22ce4affSfengbojiang 		crypto_cursor_advance(&cc_in, crp->crp_aad_start);
519*22ce4affSfengbojiang 		for (resid = crp->crp_aad_length; resid >= blksz;
520*22ce4affSfengbojiang 		     resid -= len) {
521*22ce4affSfengbojiang 			len = crypto_cursor_seglen(&cc_in);
522*22ce4affSfengbojiang 			if (len >= blksz) {
523*22ce4affSfengbojiang 				inblk = crypto_cursor_segbase(&cc_in);
524*22ce4affSfengbojiang 				len = rounddown(MIN(len, resid), blksz);
525*22ce4affSfengbojiang 				crypto_cursor_advance(&cc_in, len);
526*22ce4affSfengbojiang 			} else {
527*22ce4affSfengbojiang 				len = blksz;
528*22ce4affSfengbojiang 				crypto_cursor_copydata(&cc_in, len, blk);
529*22ce4affSfengbojiang 				inblk = blk;
530*22ce4affSfengbojiang 			}
531*22ce4affSfengbojiang 			axf->Update(&ctx, inblk, len);
532*22ce4affSfengbojiang 		}
533*22ce4affSfengbojiang 		if (resid > 0) {
534*22ce4affSfengbojiang 			memset(blk, 0, blksz);
535*22ce4affSfengbojiang 			crypto_cursor_copydata(&cc_in, resid, blk);
536*22ce4affSfengbojiang 			axf->Update(&ctx, blk, blksz);
537*22ce4affSfengbojiang 		}
538a9643ea8Slogwang 	}
539a9643ea8Slogwang 
540*22ce4affSfengbojiang 	exf->reinit(swe->sw_kschedule, iv);
541*22ce4affSfengbojiang 
542*22ce4affSfengbojiang 	/* Do encryption with MAC */
543*22ce4affSfengbojiang 	crypto_cursor_init(&cc_in, &crp->crp_buf);
544*22ce4affSfengbojiang 	crypto_cursor_advance(&cc_in, crp->crp_payload_start);
545*22ce4affSfengbojiang 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
546*22ce4affSfengbojiang 		crypto_cursor_init(&cc_out, &crp->crp_obuf);
547*22ce4affSfengbojiang 		crypto_cursor_advance(&cc_out, crp->crp_payload_output_start);
548*22ce4affSfengbojiang 	} else
549*22ce4affSfengbojiang 		cc_out = cc_in;
550*22ce4affSfengbojiang 	for (resid = crp->crp_payload_length; resid >= blksz; resid -= blksz) {
551*22ce4affSfengbojiang 		if (crypto_cursor_seglen(&cc_in) < blksz) {
552*22ce4affSfengbojiang 			crypto_cursor_copydata(&cc_in, blksz, blk);
553*22ce4affSfengbojiang 			inblk = blk;
554*22ce4affSfengbojiang 		} else {
555*22ce4affSfengbojiang 			inblk = crypto_cursor_segbase(&cc_in);
556*22ce4affSfengbojiang 			crypto_cursor_advance(&cc_in, blksz);
557*22ce4affSfengbojiang 		}
558*22ce4affSfengbojiang 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
559*22ce4affSfengbojiang 			if (crypto_cursor_seglen(&cc_out) < blksz)
560*22ce4affSfengbojiang 				outblk = blk;
561*22ce4affSfengbojiang 			else
562*22ce4affSfengbojiang 				outblk = crypto_cursor_segbase(&cc_out);
563*22ce4affSfengbojiang 			exf->encrypt(swe->sw_kschedule, inblk, outblk);
564*22ce4affSfengbojiang 			axf->Update(&ctx, outblk, blksz);
565*22ce4affSfengbojiang 			if (outblk == blk)
566*22ce4affSfengbojiang 				crypto_cursor_copyback(&cc_out, blksz, blk);
567*22ce4affSfengbojiang 			else
568*22ce4affSfengbojiang 				crypto_cursor_advance(&cc_out, blksz);
569*22ce4affSfengbojiang 		} else {
570*22ce4affSfengbojiang 			axf->Update(&ctx, inblk, blksz);
571*22ce4affSfengbojiang 		}
572*22ce4affSfengbojiang 	}
573*22ce4affSfengbojiang 	if (resid > 0) {
574*22ce4affSfengbojiang 		crypto_cursor_copydata(&cc_in, resid, blk);
575*22ce4affSfengbojiang 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
576*22ce4affSfengbojiang 			exf->encrypt_last(swe->sw_kschedule, blk, blk, resid);
577*22ce4affSfengbojiang 			crypto_cursor_copyback(&cc_out, resid, blk);
578*22ce4affSfengbojiang 		}
579*22ce4affSfengbojiang 		axf->Update(&ctx, blk, resid);
580*22ce4affSfengbojiang 	}
581*22ce4affSfengbojiang 
582*22ce4affSfengbojiang 	/* length block */
583*22ce4affSfengbojiang 	memset(blk, 0, blksz);
584*22ce4affSfengbojiang 	blkp = (uint32_t *)blk + 1;
585*22ce4affSfengbojiang 	*blkp = htobe32(crp->crp_aad_length * 8);
586*22ce4affSfengbojiang 	blkp = (uint32_t *)blk + 3;
587*22ce4affSfengbojiang 	*blkp = htobe32(crp->crp_payload_length * 8);
588*22ce4affSfengbojiang 	axf->Update(&ctx, blk, blksz);
589*22ce4affSfengbojiang 
590*22ce4affSfengbojiang 	/* Finalize MAC */
591*22ce4affSfengbojiang 	axf->Final(tag, &ctx);
592*22ce4affSfengbojiang 
593*22ce4affSfengbojiang 	/* Validate tag */
594*22ce4affSfengbojiang 	error = 0;
595*22ce4affSfengbojiang 	if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
596*22ce4affSfengbojiang 		u_char tag2[GMAC_DIGEST_LEN];
597*22ce4affSfengbojiang 
598*22ce4affSfengbojiang 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, tag2);
599*22ce4affSfengbojiang 
600*22ce4affSfengbojiang 		r = timingsafe_bcmp(tag, tag2, swa->sw_mlen);
601*22ce4affSfengbojiang 		explicit_bzero(tag2, sizeof(tag2));
602*22ce4affSfengbojiang 		if (r != 0) {
603*22ce4affSfengbojiang 			error = EBADMSG;
604*22ce4affSfengbojiang 			goto out;
605*22ce4affSfengbojiang 		}
606*22ce4affSfengbojiang 
607*22ce4affSfengbojiang 		/* tag matches, decrypt data */
608*22ce4affSfengbojiang 		crypto_cursor_init(&cc_in, &crp->crp_buf);
609*22ce4affSfengbojiang 		crypto_cursor_advance(&cc_in, crp->crp_payload_start);
610*22ce4affSfengbojiang 		for (resid = crp->crp_payload_length; resid > blksz;
611*22ce4affSfengbojiang 		     resid -= blksz) {
612*22ce4affSfengbojiang 			if (crypto_cursor_seglen(&cc_in) < blksz) {
613*22ce4affSfengbojiang 				crypto_cursor_copydata(&cc_in, blksz, blk);
614*22ce4affSfengbojiang 				inblk = blk;
615*22ce4affSfengbojiang 			} else {
616*22ce4affSfengbojiang 				inblk = crypto_cursor_segbase(&cc_in);
617*22ce4affSfengbojiang 				crypto_cursor_advance(&cc_in, blksz);
618*22ce4affSfengbojiang 			}
619*22ce4affSfengbojiang 			if (crypto_cursor_seglen(&cc_out) < blksz)
620*22ce4affSfengbojiang 				outblk = blk;
621*22ce4affSfengbojiang 			else
622*22ce4affSfengbojiang 				outblk = crypto_cursor_segbase(&cc_out);
623*22ce4affSfengbojiang 			exf->decrypt(swe->sw_kschedule, inblk, outblk);
624*22ce4affSfengbojiang 			if (outblk == blk)
625*22ce4affSfengbojiang 				crypto_cursor_copyback(&cc_out, blksz, blk);
626*22ce4affSfengbojiang 			else
627*22ce4affSfengbojiang 				crypto_cursor_advance(&cc_out, blksz);
628*22ce4affSfengbojiang 		}
629*22ce4affSfengbojiang 		if (resid > 0) {
630*22ce4affSfengbojiang 			crypto_cursor_copydata(&cc_in, resid, blk);
631*22ce4affSfengbojiang 			exf->decrypt_last(swe->sw_kschedule, blk, blk, resid);
632*22ce4affSfengbojiang 			crypto_cursor_copyback(&cc_out, resid, blk);
633*22ce4affSfengbojiang 		}
634*22ce4affSfengbojiang 	} else {
635*22ce4affSfengbojiang 		/* Inject the authentication data */
636*22ce4affSfengbojiang 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag);
637*22ce4affSfengbojiang 	}
638*22ce4affSfengbojiang 
639*22ce4affSfengbojiang out:
640*22ce4affSfengbojiang 	explicit_bzero(blkbuf, sizeof(blkbuf));
641*22ce4affSfengbojiang 	explicit_bzero(tag, sizeof(tag));
642*22ce4affSfengbojiang 	explicit_bzero(iv, sizeof(iv));
643*22ce4affSfengbojiang 
644*22ce4affSfengbojiang 	return (error);
645*22ce4affSfengbojiang }
646*22ce4affSfengbojiang 
647*22ce4affSfengbojiang static int
swcr_ccm_cbc_mac(struct swcr_session * ses,struct cryptop * crp)648*22ce4affSfengbojiang swcr_ccm_cbc_mac(struct swcr_session *ses, struct cryptop *crp)
649*22ce4affSfengbojiang {
650*22ce4affSfengbojiang 	u_char tag[AES_CBC_MAC_HASH_LEN];
651*22ce4affSfengbojiang 	u_char iv[AES_BLOCK_LEN];
652*22ce4affSfengbojiang 	union authctx ctx;
653*22ce4affSfengbojiang 	struct swcr_auth *swa;
654*22ce4affSfengbojiang 	struct auth_hash *axf;
655*22ce4affSfengbojiang 	int error, ivlen;
656*22ce4affSfengbojiang 
657*22ce4affSfengbojiang 	swa = &ses->swcr_auth;
658*22ce4affSfengbojiang 	axf = swa->sw_axf;
659*22ce4affSfengbojiang 
660*22ce4affSfengbojiang 	bcopy(swa->sw_ictx, &ctx, axf->ctxsize);
661*22ce4affSfengbojiang 
662*22ce4affSfengbojiang 	/* Initialize the IV */
663*22ce4affSfengbojiang 	ivlen = AES_CCM_IV_LEN;
664*22ce4affSfengbojiang 	crypto_read_iv(crp, iv);
665*22ce4affSfengbojiang 
666*22ce4affSfengbojiang 	/*
667*22ce4affSfengbojiang 	 * AES CCM-CBC-MAC needs to know the length of both the auth
668*22ce4affSfengbojiang 	 * data and payload data before doing the auth computation.
669*22ce4affSfengbojiang 	 */
670*22ce4affSfengbojiang 	ctx.aes_cbc_mac_ctx.authDataLength = crp->crp_payload_length;
671*22ce4affSfengbojiang 	ctx.aes_cbc_mac_ctx.cryptDataLength = 0;
672*22ce4affSfengbojiang 
673*22ce4affSfengbojiang 	axf->Reinit(&ctx, iv, ivlen);
674*22ce4affSfengbojiang 	if (crp->crp_aad != NULL)
675*22ce4affSfengbojiang 		error = axf->Update(&ctx, crp->crp_aad, crp->crp_aad_length);
676*22ce4affSfengbojiang 	else
677*22ce4affSfengbojiang 		error = crypto_apply(crp, crp->crp_payload_start,
678*22ce4affSfengbojiang 		    crp->crp_payload_length, axf->Update, &ctx);
679*22ce4affSfengbojiang 	if (error)
680*22ce4affSfengbojiang 		return (error);
681*22ce4affSfengbojiang 
682*22ce4affSfengbojiang 	/* Finalize MAC */
683*22ce4affSfengbojiang 	axf->Final(tag, &ctx);
684*22ce4affSfengbojiang 
685*22ce4affSfengbojiang 	if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
686*22ce4affSfengbojiang 		u_char tag2[AES_CBC_MAC_HASH_LEN];
687*22ce4affSfengbojiang 
688*22ce4affSfengbojiang 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen,
689*22ce4affSfengbojiang 		    tag2);
690*22ce4affSfengbojiang 		if (timingsafe_bcmp(tag, tag2, swa->sw_mlen) != 0)
691*22ce4affSfengbojiang 			error = EBADMSG;
692*22ce4affSfengbojiang 		explicit_bzero(tag2, sizeof(tag));
693*22ce4affSfengbojiang 	} else {
694*22ce4affSfengbojiang 		/* Inject the authentication data */
695*22ce4affSfengbojiang 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag);
696*22ce4affSfengbojiang 	}
697*22ce4affSfengbojiang 	explicit_bzero(tag, sizeof(tag));
698*22ce4affSfengbojiang 	explicit_bzero(iv, sizeof(iv));
699*22ce4affSfengbojiang 	return (error);
700*22ce4affSfengbojiang }
701*22ce4affSfengbojiang 
702*22ce4affSfengbojiang static int
swcr_ccm(struct swcr_session * ses,struct cryptop * crp)703*22ce4affSfengbojiang swcr_ccm(struct swcr_session *ses, struct cryptop *crp)
704*22ce4affSfengbojiang {
705*22ce4affSfengbojiang 	uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))];
706*22ce4affSfengbojiang 	u_char *blk = (u_char *)blkbuf;
707*22ce4affSfengbojiang 	u_char tag[AES_CBC_MAC_HASH_LEN];
708*22ce4affSfengbojiang 	u_char iv[AES_BLOCK_LEN];
709*22ce4affSfengbojiang 	struct crypto_buffer_cursor cc_in, cc_out;
710*22ce4affSfengbojiang 	const u_char *inblk;
711*22ce4affSfengbojiang 	u_char *outblk;
712*22ce4affSfengbojiang 	union authctx ctx;
713*22ce4affSfengbojiang 	struct swcr_auth *swa;
714*22ce4affSfengbojiang 	struct swcr_encdec *swe;
715*22ce4affSfengbojiang 	struct auth_hash *axf;
716*22ce4affSfengbojiang 	struct enc_xform *exf;
717*22ce4affSfengbojiang 	int blksz, error, ivlen, r, resid;
718*22ce4affSfengbojiang 
719*22ce4affSfengbojiang 	swa = &ses->swcr_auth;
720*22ce4affSfengbojiang 	axf = swa->sw_axf;
721*22ce4affSfengbojiang 
722*22ce4affSfengbojiang 	bcopy(swa->sw_ictx, &ctx, axf->ctxsize);
723*22ce4affSfengbojiang 	blksz = AES_BLOCK_LEN;
724*22ce4affSfengbojiang 	KASSERT(axf->blocksize == blksz, ("%s: axf block size mismatch",
725*22ce4affSfengbojiang 	    __func__));
726*22ce4affSfengbojiang 
727*22ce4affSfengbojiang 	swe = &ses->swcr_encdec;
728*22ce4affSfengbojiang 	exf = swe->sw_exf;
729*22ce4affSfengbojiang 	KASSERT(axf->blocksize == exf->native_blocksize,
730*22ce4affSfengbojiang 	    ("%s: blocksize mismatch", __func__));
731*22ce4affSfengbojiang 
732*22ce4affSfengbojiang 	if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0)
733*22ce4affSfengbojiang 		return (EINVAL);
734*22ce4affSfengbojiang 
735*22ce4affSfengbojiang 	/* Initialize the IV */
736*22ce4affSfengbojiang 	ivlen = AES_CCM_IV_LEN;
737*22ce4affSfengbojiang 	bcopy(crp->crp_iv, iv, ivlen);
738*22ce4affSfengbojiang 
739*22ce4affSfengbojiang 	/*
740*22ce4affSfengbojiang 	 * AES CCM-CBC-MAC needs to know the length of both the auth
741*22ce4affSfengbojiang 	 * data and payload data before doing the auth computation.
742*22ce4affSfengbojiang 	 */
743*22ce4affSfengbojiang 	ctx.aes_cbc_mac_ctx.authDataLength = crp->crp_aad_length;
744*22ce4affSfengbojiang 	ctx.aes_cbc_mac_ctx.cryptDataLength = crp->crp_payload_length;
745*22ce4affSfengbojiang 
746*22ce4affSfengbojiang 	/* Supply MAC with IV */
747*22ce4affSfengbojiang 	axf->Reinit(&ctx, iv, ivlen);
748*22ce4affSfengbojiang 
749*22ce4affSfengbojiang 	/* Supply MAC with AAD */
750*22ce4affSfengbojiang 	if (crp->crp_aad != NULL)
751*22ce4affSfengbojiang 		error = axf->Update(&ctx, crp->crp_aad, crp->crp_aad_length);
752*22ce4affSfengbojiang 	else
753*22ce4affSfengbojiang 		error = crypto_apply(crp, crp->crp_aad_start,
754*22ce4affSfengbojiang 		    crp->crp_aad_length, axf->Update, &ctx);
755*22ce4affSfengbojiang 	if (error)
756*22ce4affSfengbojiang 		return (error);
757*22ce4affSfengbojiang 
758a9643ea8Slogwang 	exf->reinit(swe->sw_kschedule, iv);
759a9643ea8Slogwang 
760a9643ea8Slogwang 	/* Do encryption/decryption with MAC */
761*22ce4affSfengbojiang 	crypto_cursor_init(&cc_in, &crp->crp_buf);
762*22ce4affSfengbojiang 	crypto_cursor_advance(&cc_in, crp->crp_payload_start);
763*22ce4affSfengbojiang 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
764*22ce4affSfengbojiang 		crypto_cursor_init(&cc_out, &crp->crp_obuf);
765*22ce4affSfengbojiang 		crypto_cursor_advance(&cc_out, crp->crp_payload_output_start);
766*22ce4affSfengbojiang 	} else
767*22ce4affSfengbojiang 		cc_out = cc_in;
768*22ce4affSfengbojiang 	for (resid = crp->crp_payload_length; resid >= blksz; resid -= blksz) {
769*22ce4affSfengbojiang 		if (crypto_cursor_seglen(&cc_in) < blksz) {
770*22ce4affSfengbojiang 			crypto_cursor_copydata(&cc_in, blksz, blk);
771*22ce4affSfengbojiang 			inblk = blk;
772a9643ea8Slogwang 		} else {
773*22ce4affSfengbojiang 			inblk = crypto_cursor_segbase(&cc_in);
774*22ce4affSfengbojiang 			crypto_cursor_advance(&cc_in, blksz);
775a9643ea8Slogwang 		}
776*22ce4affSfengbojiang 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
777*22ce4affSfengbojiang 			if (crypto_cursor_seglen(&cc_out) < blksz)
778*22ce4affSfengbojiang 				outblk = blk;
779*22ce4affSfengbojiang 			else
780*22ce4affSfengbojiang 				outblk = crypto_cursor_segbase(&cc_out);
781*22ce4affSfengbojiang 			axf->Update(&ctx, inblk, blksz);
782*22ce4affSfengbojiang 			exf->encrypt(swe->sw_kschedule, inblk, outblk);
783*22ce4affSfengbojiang 			if (outblk == blk)
784*22ce4affSfengbojiang 				crypto_cursor_copyback(&cc_out, blksz, blk);
785*22ce4affSfengbojiang 			else
786*22ce4affSfengbojiang 				crypto_cursor_advance(&cc_out, blksz);
787*22ce4affSfengbojiang 		} else {
788*22ce4affSfengbojiang 			/*
789*22ce4affSfengbojiang 			 * One of the problems with CCM+CBC is that
790*22ce4affSfengbojiang 			 * the authentication is done on the
791*22ce4affSfengbojiang 			 * unencrypted data.  As a result, we have to
792*22ce4affSfengbojiang 			 * decrypt the data twice: once to generate
793*22ce4affSfengbojiang 			 * the tag and a second time after the tag is
794*22ce4affSfengbojiang 			 * verified.
795*22ce4affSfengbojiang 			 */
796*22ce4affSfengbojiang 			exf->decrypt(swe->sw_kschedule, inblk, blk);
797a9643ea8Slogwang 			axf->Update(&ctx, blk, blksz);
798*22ce4affSfengbojiang 		}
799*22ce4affSfengbojiang 	}
800*22ce4affSfengbojiang 	if (resid > 0) {
801*22ce4affSfengbojiang 		crypto_cursor_copydata(&cc_in, resid, blk);
802*22ce4affSfengbojiang 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
803*22ce4affSfengbojiang 			axf->Update(&ctx, blk, resid);
804*22ce4affSfengbojiang 			exf->encrypt_last(swe->sw_kschedule, blk, blk, resid);
805*22ce4affSfengbojiang 			crypto_cursor_copyback(&cc_out, resid, blk);
806*22ce4affSfengbojiang 		} else {
807*22ce4affSfengbojiang 			exf->decrypt_last(swe->sw_kschedule, blk, blk, resid);
808*22ce4affSfengbojiang 			axf->Update(&ctx, blk, resid);
809*22ce4affSfengbojiang 		}
810a9643ea8Slogwang 	}
811a9643ea8Slogwang 
812a9643ea8Slogwang 	/* Finalize MAC */
813*22ce4affSfengbojiang 	axf->Final(tag, &ctx);
814a9643ea8Slogwang 
815a9643ea8Slogwang 	/* Validate tag */
816*22ce4affSfengbojiang 	error = 0;
817*22ce4affSfengbojiang 	if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
818*22ce4affSfengbojiang 		u_char tag2[AES_CBC_MAC_HASH_LEN];
819a9643ea8Slogwang 
820*22ce4affSfengbojiang 		crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen,
821*22ce4affSfengbojiang 		    tag2);
822*22ce4affSfengbojiang 
823*22ce4affSfengbojiang 		r = timingsafe_bcmp(tag, tag2, swa->sw_mlen);
824*22ce4affSfengbojiang 		explicit_bzero(tag2, sizeof(tag2));
825*22ce4affSfengbojiang 		if (r != 0) {
826*22ce4affSfengbojiang 			error = EBADMSG;
827*22ce4affSfengbojiang 			goto out;
828*22ce4affSfengbojiang 		}
829*22ce4affSfengbojiang 
830a9643ea8Slogwang 		/* tag matches, decrypt data */
831*22ce4affSfengbojiang 		exf->reinit(swe->sw_kschedule, iv);
832*22ce4affSfengbojiang 		crypto_cursor_init(&cc_in, &crp->crp_buf);
833*22ce4affSfengbojiang 		crypto_cursor_advance(&cc_in, crp->crp_payload_start);
834*22ce4affSfengbojiang 		for (resid = crp->crp_payload_length; resid > blksz;
835*22ce4affSfengbojiang 		     resid -= blksz) {
836*22ce4affSfengbojiang 			if (crypto_cursor_seglen(&cc_in) < blksz) {
837*22ce4affSfengbojiang 				crypto_cursor_copydata(&cc_in, blksz, blk);
838*22ce4affSfengbojiang 				inblk = blk;
839*22ce4affSfengbojiang 			} else {
840*22ce4affSfengbojiang 				inblk = crypto_cursor_segbase(&cc_in);
841*22ce4affSfengbojiang 				crypto_cursor_advance(&cc_in, blksz);
842a9643ea8Slogwang 			}
843*22ce4affSfengbojiang 			if (crypto_cursor_seglen(&cc_out) < blksz)
844*22ce4affSfengbojiang 				outblk = blk;
845*22ce4affSfengbojiang 			else
846*22ce4affSfengbojiang 				outblk = crypto_cursor_segbase(&cc_out);
847*22ce4affSfengbojiang 			exf->decrypt(swe->sw_kschedule, inblk, outblk);
848*22ce4affSfengbojiang 			if (outblk == blk)
849*22ce4affSfengbojiang 				crypto_cursor_copyback(&cc_out, blksz, blk);
850*22ce4affSfengbojiang 			else
851*22ce4affSfengbojiang 				crypto_cursor_advance(&cc_out, blksz);
852a9643ea8Slogwang 		}
853*22ce4affSfengbojiang 		if (resid > 0) {
854*22ce4affSfengbojiang 			crypto_cursor_copydata(&cc_in, resid, blk);
855*22ce4affSfengbojiang 			exf->decrypt_last(swe->sw_kschedule, blk, blk, resid);
856*22ce4affSfengbojiang 			crypto_cursor_copyback(&cc_out, resid, blk);
857*22ce4affSfengbojiang 		}
858a9643ea8Slogwang 	} else {
859a9643ea8Slogwang 		/* Inject the authentication data */
860*22ce4affSfengbojiang 		crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag);
861a9643ea8Slogwang 	}
862a9643ea8Slogwang 
863*22ce4affSfengbojiang out:
864*22ce4affSfengbojiang 	explicit_bzero(blkbuf, sizeof(blkbuf));
865*22ce4affSfengbojiang 	explicit_bzero(tag, sizeof(tag));
866*22ce4affSfengbojiang 	explicit_bzero(iv, sizeof(iv));
867*22ce4affSfengbojiang 	return (error);
868*22ce4affSfengbojiang }
869*22ce4affSfengbojiang 
870*22ce4affSfengbojiang /*
871*22ce4affSfengbojiang  * Apply a cipher and a digest to perform EtA.
872*22ce4affSfengbojiang  */
873*22ce4affSfengbojiang static int
swcr_eta(struct swcr_session * ses,struct cryptop * crp)874*22ce4affSfengbojiang swcr_eta(struct swcr_session *ses, struct cryptop *crp)
875*22ce4affSfengbojiang {
876*22ce4affSfengbojiang 	int error;
877*22ce4affSfengbojiang 
878*22ce4affSfengbojiang 	if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
879*22ce4affSfengbojiang 		error = swcr_encdec(ses, crp);
880*22ce4affSfengbojiang 		if (error == 0)
881*22ce4affSfengbojiang 			error = swcr_authcompute(ses, crp);
882*22ce4affSfengbojiang 	} else {
883*22ce4affSfengbojiang 		error = swcr_authcompute(ses, crp);
884*22ce4affSfengbojiang 		if (error == 0)
885*22ce4affSfengbojiang 			error = swcr_encdec(ses, crp);
886*22ce4affSfengbojiang 	}
887*22ce4affSfengbojiang 	return (error);
888a9643ea8Slogwang }
889a9643ea8Slogwang 
890a9643ea8Slogwang /*
891a9643ea8Slogwang  * Apply a compression/decompression algorithm
892a9643ea8Slogwang  */
893a9643ea8Slogwang static int
swcr_compdec(struct swcr_session * ses,struct cryptop * crp)894*22ce4affSfengbojiang swcr_compdec(struct swcr_session *ses, struct cryptop *crp)
895a9643ea8Slogwang {
896*22ce4affSfengbojiang 	uint8_t *data, *out;
897a9643ea8Slogwang 	struct comp_algo *cxf;
898a9643ea8Slogwang 	int adj;
899*22ce4affSfengbojiang 	uint32_t result;
900a9643ea8Slogwang 
901*22ce4affSfengbojiang 	cxf = ses->swcr_compdec.sw_cxf;
902a9643ea8Slogwang 
903a9643ea8Slogwang 	/* We must handle the whole buffer of data in one time
904a9643ea8Slogwang 	 * then if there is not all the data in the mbuf, we must
905a9643ea8Slogwang 	 * copy in a buffer.
906a9643ea8Slogwang 	 */
907a9643ea8Slogwang 
908*22ce4affSfengbojiang 	data = malloc(crp->crp_payload_length, M_CRYPTO_DATA,  M_NOWAIT);
909a9643ea8Slogwang 	if (data == NULL)
910a9643ea8Slogwang 		return (EINVAL);
911*22ce4affSfengbojiang 	crypto_copydata(crp, crp->crp_payload_start, crp->crp_payload_length,
912*22ce4affSfengbojiang 	    data);
913a9643ea8Slogwang 
914*22ce4affSfengbojiang 	if (CRYPTO_OP_IS_COMPRESS(crp->crp_op))
915*22ce4affSfengbojiang 		result = cxf->compress(data, crp->crp_payload_length, &out);
916a9643ea8Slogwang 	else
917*22ce4affSfengbojiang 		result = cxf->decompress(data, crp->crp_payload_length, &out);
918a9643ea8Slogwang 
919a9643ea8Slogwang 	free(data, M_CRYPTO_DATA);
920a9643ea8Slogwang 	if (result == 0)
921*22ce4affSfengbojiang 		return (EINVAL);
922*22ce4affSfengbojiang 	crp->crp_olen = result;
923*22ce4affSfengbojiang 
924*22ce4affSfengbojiang 	/* Check the compressed size when doing compression */
925*22ce4affSfengbojiang 	if (CRYPTO_OP_IS_COMPRESS(crp->crp_op)) {
926*22ce4affSfengbojiang 		if (result >= crp->crp_payload_length) {
927*22ce4affSfengbojiang 			/* Compression was useless, we lost time */
928*22ce4affSfengbojiang 			free(out, M_CRYPTO_DATA);
929*22ce4affSfengbojiang 			return (0);
930*22ce4affSfengbojiang 		}
931*22ce4affSfengbojiang 	}
932a9643ea8Slogwang 
933a9643ea8Slogwang 	/* Copy back the (de)compressed data. m_copyback is
934a9643ea8Slogwang 	 * extending the mbuf as necessary.
935a9643ea8Slogwang 	 */
936*22ce4affSfengbojiang 	crypto_copyback(crp, crp->crp_payload_start, result, out);
937*22ce4affSfengbojiang 	if (result < crp->crp_payload_length) {
938*22ce4affSfengbojiang 		switch (crp->crp_buf.cb_type) {
939*22ce4affSfengbojiang 		case CRYPTO_BUF_MBUF:
940*22ce4affSfengbojiang 			adj = result - crp->crp_payload_length;
941*22ce4affSfengbojiang 			m_adj(crp->crp_buf.cb_mbuf, adj);
942*22ce4affSfengbojiang 			break;
943*22ce4affSfengbojiang 		case CRYPTO_BUF_UIO: {
944*22ce4affSfengbojiang 			struct uio *uio = crp->crp_buf.cb_uio;
945a9643ea8Slogwang 			int ind;
946a9643ea8Slogwang 
947*22ce4affSfengbojiang 			adj = crp->crp_payload_length - result;
948a9643ea8Slogwang 			ind = uio->uio_iovcnt - 1;
949a9643ea8Slogwang 
950a9643ea8Slogwang 			while (adj > 0 && ind >= 0) {
951a9643ea8Slogwang 				if (adj < uio->uio_iov[ind].iov_len) {
952a9643ea8Slogwang 					uio->uio_iov[ind].iov_len -= adj;
953a9643ea8Slogwang 					break;
954a9643ea8Slogwang 				}
955a9643ea8Slogwang 
956a9643ea8Slogwang 				adj -= uio->uio_iov[ind].iov_len;
957a9643ea8Slogwang 				uio->uio_iov[ind].iov_len = 0;
958a9643ea8Slogwang 				ind--;
959a9643ea8Slogwang 				uio->uio_iovcnt--;
960a9643ea8Slogwang 			}
961a9643ea8Slogwang 			}
962*22ce4affSfengbojiang 			break;
963*22ce4affSfengbojiang 		case CRYPTO_BUF_VMPAGE:
964*22ce4affSfengbojiang 			adj = crp->crp_payload_length - result;
965*22ce4affSfengbojiang 			crp->crp_buf.cb_vm_page_len -= adj;
966*22ce4affSfengbojiang 			break;
967*22ce4affSfengbojiang 		default:
968*22ce4affSfengbojiang 			break;
969*22ce4affSfengbojiang 		}
970a9643ea8Slogwang 	}
971a9643ea8Slogwang 	free(out, M_CRYPTO_DATA);
972a9643ea8Slogwang 	return 0;
973a9643ea8Slogwang }
974a9643ea8Slogwang 
975*22ce4affSfengbojiang static int
swcr_setup_cipher(struct swcr_session * ses,const struct crypto_session_params * csp)976*22ce4affSfengbojiang swcr_setup_cipher(struct swcr_session *ses,
977*22ce4affSfengbojiang     const struct crypto_session_params *csp)
978*22ce4affSfengbojiang {
979*22ce4affSfengbojiang 	struct swcr_encdec *swe;
980*22ce4affSfengbojiang 	struct enc_xform *txf;
981*22ce4affSfengbojiang 	int error;
982*22ce4affSfengbojiang 
983*22ce4affSfengbojiang 	swe = &ses->swcr_encdec;
984*22ce4affSfengbojiang 	txf = crypto_cipher(csp);
985*22ce4affSfengbojiang 	MPASS(txf->ivsize == csp->csp_ivlen);
986*22ce4affSfengbojiang 	if (txf->ctxsize != 0) {
987*22ce4affSfengbojiang 		swe->sw_kschedule = malloc(txf->ctxsize, M_CRYPTO_DATA,
988*22ce4affSfengbojiang 		    M_NOWAIT);
989*22ce4affSfengbojiang 		if (swe->sw_kschedule == NULL)
990*22ce4affSfengbojiang 			return (ENOMEM);
991*22ce4affSfengbojiang 	}
992*22ce4affSfengbojiang 	if (csp->csp_cipher_key != NULL) {
993*22ce4affSfengbojiang 		error = txf->setkey(swe->sw_kschedule,
994*22ce4affSfengbojiang 		    csp->csp_cipher_key, csp->csp_cipher_klen);
995*22ce4affSfengbojiang 		if (error)
996*22ce4affSfengbojiang 			return (error);
997*22ce4affSfengbojiang 	}
998*22ce4affSfengbojiang 	swe->sw_exf = txf;
999*22ce4affSfengbojiang 	return (0);
1000*22ce4affSfengbojiang }
1001*22ce4affSfengbojiang 
1002*22ce4affSfengbojiang static int
swcr_setup_auth(struct swcr_session * ses,const struct crypto_session_params * csp)1003*22ce4affSfengbojiang swcr_setup_auth(struct swcr_session *ses,
1004*22ce4affSfengbojiang     const struct crypto_session_params *csp)
1005*22ce4affSfengbojiang {
1006*22ce4affSfengbojiang 	struct swcr_auth *swa;
1007*22ce4affSfengbojiang 	struct auth_hash *axf;
1008*22ce4affSfengbojiang 
1009*22ce4affSfengbojiang 	swa = &ses->swcr_auth;
1010*22ce4affSfengbojiang 
1011*22ce4affSfengbojiang 	axf = crypto_auth_hash(csp);
1012*22ce4affSfengbojiang 	swa->sw_axf = axf;
1013*22ce4affSfengbojiang 	if (csp->csp_auth_mlen < 0 || csp->csp_auth_mlen > axf->hashsize)
1014*22ce4affSfengbojiang 		return (EINVAL);
1015*22ce4affSfengbojiang 	if (csp->csp_auth_mlen == 0)
1016*22ce4affSfengbojiang 		swa->sw_mlen = axf->hashsize;
1017*22ce4affSfengbojiang 	else
1018*22ce4affSfengbojiang 		swa->sw_mlen = csp->csp_auth_mlen;
1019*22ce4affSfengbojiang 	swa->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, M_NOWAIT);
1020*22ce4affSfengbojiang 	if (swa->sw_ictx == NULL)
1021*22ce4affSfengbojiang 		return (ENOBUFS);
1022*22ce4affSfengbojiang 
1023*22ce4affSfengbojiang 	switch (csp->csp_auth_alg) {
1024*22ce4affSfengbojiang 	case CRYPTO_SHA1_HMAC:
1025*22ce4affSfengbojiang 	case CRYPTO_SHA2_224_HMAC:
1026*22ce4affSfengbojiang 	case CRYPTO_SHA2_256_HMAC:
1027*22ce4affSfengbojiang 	case CRYPTO_SHA2_384_HMAC:
1028*22ce4affSfengbojiang 	case CRYPTO_SHA2_512_HMAC:
1029*22ce4affSfengbojiang 	case CRYPTO_NULL_HMAC:
1030*22ce4affSfengbojiang 	case CRYPTO_RIPEMD160_HMAC:
1031*22ce4affSfengbojiang 		swa->sw_octx = malloc(axf->ctxsize, M_CRYPTO_DATA,
1032*22ce4affSfengbojiang 		    M_NOWAIT);
1033*22ce4affSfengbojiang 		if (swa->sw_octx == NULL)
1034*22ce4affSfengbojiang 			return (ENOBUFS);
1035*22ce4affSfengbojiang 
1036*22ce4affSfengbojiang 		if (csp->csp_auth_key != NULL) {
1037*22ce4affSfengbojiang 			swcr_authprepare(axf, swa, csp->csp_auth_key,
1038*22ce4affSfengbojiang 			    csp->csp_auth_klen);
1039*22ce4affSfengbojiang 		}
1040*22ce4affSfengbojiang 
1041*22ce4affSfengbojiang 		if (csp->csp_mode == CSP_MODE_DIGEST)
1042*22ce4affSfengbojiang 			ses->swcr_process = swcr_authcompute;
1043*22ce4affSfengbojiang 		break;
1044*22ce4affSfengbojiang 	case CRYPTO_SHA1:
1045*22ce4affSfengbojiang 	case CRYPTO_SHA2_224:
1046*22ce4affSfengbojiang 	case CRYPTO_SHA2_256:
1047*22ce4affSfengbojiang 	case CRYPTO_SHA2_384:
1048*22ce4affSfengbojiang 	case CRYPTO_SHA2_512:
1049*22ce4affSfengbojiang 		axf->Init(swa->sw_ictx);
1050*22ce4affSfengbojiang 		if (csp->csp_mode == CSP_MODE_DIGEST)
1051*22ce4affSfengbojiang 			ses->swcr_process = swcr_authcompute;
1052*22ce4affSfengbojiang 		break;
1053*22ce4affSfengbojiang 	case CRYPTO_AES_NIST_GMAC:
1054*22ce4affSfengbojiang 		axf->Init(swa->sw_ictx);
1055*22ce4affSfengbojiang 		axf->Setkey(swa->sw_ictx, csp->csp_auth_key,
1056*22ce4affSfengbojiang 		    csp->csp_auth_klen);
1057*22ce4affSfengbojiang 		if (csp->csp_mode == CSP_MODE_DIGEST)
1058*22ce4affSfengbojiang 			ses->swcr_process = swcr_gmac;
1059*22ce4affSfengbojiang 		break;
1060*22ce4affSfengbojiang 	case CRYPTO_POLY1305:
1061*22ce4affSfengbojiang 	case CRYPTO_BLAKE2B:
1062*22ce4affSfengbojiang 	case CRYPTO_BLAKE2S:
1063*22ce4affSfengbojiang 		/*
1064*22ce4affSfengbojiang 		 * Blake2b and Blake2s support an optional key but do
1065*22ce4affSfengbojiang 		 * not require one.
1066*22ce4affSfengbojiang 		 */
1067*22ce4affSfengbojiang 		if (csp->csp_auth_klen == 0 || csp->csp_auth_key != NULL)
1068*22ce4affSfengbojiang 			axf->Setkey(swa->sw_ictx, csp->csp_auth_key,
1069*22ce4affSfengbojiang 			    csp->csp_auth_klen);
1070*22ce4affSfengbojiang 		axf->Init(swa->sw_ictx);
1071*22ce4affSfengbojiang 		if (csp->csp_mode == CSP_MODE_DIGEST)
1072*22ce4affSfengbojiang 			ses->swcr_process = swcr_authcompute;
1073*22ce4affSfengbojiang 		break;
1074*22ce4affSfengbojiang 	case CRYPTO_AES_CCM_CBC_MAC:
1075*22ce4affSfengbojiang 		axf->Init(swa->sw_ictx);
1076*22ce4affSfengbojiang 		axf->Setkey(swa->sw_ictx, csp->csp_auth_key,
1077*22ce4affSfengbojiang 		    csp->csp_auth_klen);
1078*22ce4affSfengbojiang 		if (csp->csp_mode == CSP_MODE_DIGEST)
1079*22ce4affSfengbojiang 			ses->swcr_process = swcr_ccm_cbc_mac;
1080*22ce4affSfengbojiang 		break;
1081*22ce4affSfengbojiang 	}
1082*22ce4affSfengbojiang 
1083*22ce4affSfengbojiang 	return (0);
1084*22ce4affSfengbojiang }
1085*22ce4affSfengbojiang 
1086*22ce4affSfengbojiang static int
swcr_setup_gcm(struct swcr_session * ses,const struct crypto_session_params * csp)1087*22ce4affSfengbojiang swcr_setup_gcm(struct swcr_session *ses,
1088*22ce4affSfengbojiang     const struct crypto_session_params *csp)
1089*22ce4affSfengbojiang {
1090*22ce4affSfengbojiang 	struct swcr_auth *swa;
1091*22ce4affSfengbojiang 	struct auth_hash *axf;
1092*22ce4affSfengbojiang 
1093*22ce4affSfengbojiang 	if (csp->csp_ivlen != AES_GCM_IV_LEN)
1094*22ce4affSfengbojiang 		return (EINVAL);
1095*22ce4affSfengbojiang 
1096*22ce4affSfengbojiang 	/* First, setup the auth side. */
1097*22ce4affSfengbojiang 	swa = &ses->swcr_auth;
1098*22ce4affSfengbojiang 	switch (csp->csp_cipher_klen * 8) {
1099*22ce4affSfengbojiang 	case 128:
1100*22ce4affSfengbojiang 		axf = &auth_hash_nist_gmac_aes_128;
1101*22ce4affSfengbojiang 		break;
1102*22ce4affSfengbojiang 	case 192:
1103*22ce4affSfengbojiang 		axf = &auth_hash_nist_gmac_aes_192;
1104*22ce4affSfengbojiang 		break;
1105*22ce4affSfengbojiang 	case 256:
1106*22ce4affSfengbojiang 		axf = &auth_hash_nist_gmac_aes_256;
1107*22ce4affSfengbojiang 		break;
1108*22ce4affSfengbojiang 	default:
1109*22ce4affSfengbojiang 		return (EINVAL);
1110*22ce4affSfengbojiang 	}
1111*22ce4affSfengbojiang 	swa->sw_axf = axf;
1112*22ce4affSfengbojiang 	if (csp->csp_auth_mlen < 0 || csp->csp_auth_mlen > axf->hashsize)
1113*22ce4affSfengbojiang 		return (EINVAL);
1114*22ce4affSfengbojiang 	if (csp->csp_auth_mlen == 0)
1115*22ce4affSfengbojiang 		swa->sw_mlen = axf->hashsize;
1116*22ce4affSfengbojiang 	else
1117*22ce4affSfengbojiang 		swa->sw_mlen = csp->csp_auth_mlen;
1118*22ce4affSfengbojiang 	swa->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, M_NOWAIT);
1119*22ce4affSfengbojiang 	if (swa->sw_ictx == NULL)
1120*22ce4affSfengbojiang 		return (ENOBUFS);
1121*22ce4affSfengbojiang 	axf->Init(swa->sw_ictx);
1122*22ce4affSfengbojiang 	if (csp->csp_cipher_key != NULL)
1123*22ce4affSfengbojiang 		axf->Setkey(swa->sw_ictx, csp->csp_cipher_key,
1124*22ce4affSfengbojiang 		    csp->csp_cipher_klen);
1125*22ce4affSfengbojiang 
1126*22ce4affSfengbojiang 	/* Second, setup the cipher side. */
1127*22ce4affSfengbojiang 	return (swcr_setup_cipher(ses, csp));
1128*22ce4affSfengbojiang }
1129*22ce4affSfengbojiang 
1130*22ce4affSfengbojiang static int
swcr_setup_ccm(struct swcr_session * ses,const struct crypto_session_params * csp)1131*22ce4affSfengbojiang swcr_setup_ccm(struct swcr_session *ses,
1132*22ce4affSfengbojiang     const struct crypto_session_params *csp)
1133*22ce4affSfengbojiang {
1134*22ce4affSfengbojiang 	struct swcr_auth *swa;
1135*22ce4affSfengbojiang 	struct auth_hash *axf;
1136*22ce4affSfengbojiang 
1137*22ce4affSfengbojiang 	if (csp->csp_ivlen != AES_CCM_IV_LEN)
1138*22ce4affSfengbojiang 		return (EINVAL);
1139*22ce4affSfengbojiang 
1140*22ce4affSfengbojiang 	/* First, setup the auth side. */
1141*22ce4affSfengbojiang 	swa = &ses->swcr_auth;
1142*22ce4affSfengbojiang 	switch (csp->csp_cipher_klen * 8) {
1143*22ce4affSfengbojiang 	case 128:
1144*22ce4affSfengbojiang 		axf = &auth_hash_ccm_cbc_mac_128;
1145*22ce4affSfengbojiang 		break;
1146*22ce4affSfengbojiang 	case 192:
1147*22ce4affSfengbojiang 		axf = &auth_hash_ccm_cbc_mac_192;
1148*22ce4affSfengbojiang 		break;
1149*22ce4affSfengbojiang 	case 256:
1150*22ce4affSfengbojiang 		axf = &auth_hash_ccm_cbc_mac_256;
1151*22ce4affSfengbojiang 		break;
1152*22ce4affSfengbojiang 	default:
1153*22ce4affSfengbojiang 		return (EINVAL);
1154*22ce4affSfengbojiang 	}
1155*22ce4affSfengbojiang 	swa->sw_axf = axf;
1156*22ce4affSfengbojiang 	if (csp->csp_auth_mlen < 0 || csp->csp_auth_mlen > axf->hashsize)
1157*22ce4affSfengbojiang 		return (EINVAL);
1158*22ce4affSfengbojiang 	if (csp->csp_auth_mlen == 0)
1159*22ce4affSfengbojiang 		swa->sw_mlen = axf->hashsize;
1160*22ce4affSfengbojiang 	else
1161*22ce4affSfengbojiang 		swa->sw_mlen = csp->csp_auth_mlen;
1162*22ce4affSfengbojiang 	swa->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, M_NOWAIT);
1163*22ce4affSfengbojiang 	if (swa->sw_ictx == NULL)
1164*22ce4affSfengbojiang 		return (ENOBUFS);
1165*22ce4affSfengbojiang 	axf->Init(swa->sw_ictx);
1166*22ce4affSfengbojiang 	if (csp->csp_cipher_key != NULL)
1167*22ce4affSfengbojiang 		axf->Setkey(swa->sw_ictx, csp->csp_cipher_key,
1168*22ce4affSfengbojiang 		    csp->csp_cipher_klen);
1169*22ce4affSfengbojiang 
1170*22ce4affSfengbojiang 	/* Second, setup the cipher side. */
1171*22ce4affSfengbojiang 	return (swcr_setup_cipher(ses, csp));
1172*22ce4affSfengbojiang }
1173*22ce4affSfengbojiang 
1174*22ce4affSfengbojiang static bool
swcr_auth_supported(const struct crypto_session_params * csp)1175*22ce4affSfengbojiang swcr_auth_supported(const struct crypto_session_params *csp)
1176*22ce4affSfengbojiang {
1177*22ce4affSfengbojiang 	struct auth_hash *axf;
1178*22ce4affSfengbojiang 
1179*22ce4affSfengbojiang 	axf = crypto_auth_hash(csp);
1180*22ce4affSfengbojiang 	if (axf == NULL)
1181*22ce4affSfengbojiang 		return (false);
1182*22ce4affSfengbojiang 	switch (csp->csp_auth_alg) {
1183*22ce4affSfengbojiang 	case CRYPTO_SHA1_HMAC:
1184*22ce4affSfengbojiang 	case CRYPTO_SHA2_224_HMAC:
1185*22ce4affSfengbojiang 	case CRYPTO_SHA2_256_HMAC:
1186*22ce4affSfengbojiang 	case CRYPTO_SHA2_384_HMAC:
1187*22ce4affSfengbojiang 	case CRYPTO_SHA2_512_HMAC:
1188*22ce4affSfengbojiang 	case CRYPTO_NULL_HMAC:
1189*22ce4affSfengbojiang 	case CRYPTO_RIPEMD160_HMAC:
1190*22ce4affSfengbojiang 		break;
1191*22ce4affSfengbojiang 	case CRYPTO_AES_NIST_GMAC:
1192*22ce4affSfengbojiang 		switch (csp->csp_auth_klen * 8) {
1193*22ce4affSfengbojiang 		case 128:
1194*22ce4affSfengbojiang 		case 192:
1195*22ce4affSfengbojiang 		case 256:
1196*22ce4affSfengbojiang 			break;
1197*22ce4affSfengbojiang 		default:
1198*22ce4affSfengbojiang 			return (false);
1199*22ce4affSfengbojiang 		}
1200*22ce4affSfengbojiang 		if (csp->csp_auth_key == NULL)
1201*22ce4affSfengbojiang 			return (false);
1202*22ce4affSfengbojiang 		if (csp->csp_ivlen != AES_GCM_IV_LEN)
1203*22ce4affSfengbojiang 			return (false);
1204*22ce4affSfengbojiang 		break;
1205*22ce4affSfengbojiang 	case CRYPTO_POLY1305:
1206*22ce4affSfengbojiang 		if (csp->csp_auth_klen != POLY1305_KEY_LEN)
1207*22ce4affSfengbojiang 			return (false);
1208*22ce4affSfengbojiang 		break;
1209*22ce4affSfengbojiang 	case CRYPTO_AES_CCM_CBC_MAC:
1210*22ce4affSfengbojiang 		switch (csp->csp_auth_klen * 8) {
1211*22ce4affSfengbojiang 		case 128:
1212*22ce4affSfengbojiang 		case 192:
1213*22ce4affSfengbojiang 		case 256:
1214*22ce4affSfengbojiang 			break;
1215*22ce4affSfengbojiang 		default:
1216*22ce4affSfengbojiang 			return (false);
1217*22ce4affSfengbojiang 		}
1218*22ce4affSfengbojiang 		if (csp->csp_auth_key == NULL)
1219*22ce4affSfengbojiang 			return (false);
1220*22ce4affSfengbojiang 		if (csp->csp_ivlen != AES_CCM_IV_LEN)
1221*22ce4affSfengbojiang 			return (false);
1222*22ce4affSfengbojiang 		break;
1223*22ce4affSfengbojiang 	}
1224*22ce4affSfengbojiang 	return (true);
1225*22ce4affSfengbojiang }
1226*22ce4affSfengbojiang 
1227*22ce4affSfengbojiang static bool
swcr_cipher_supported(const struct crypto_session_params * csp)1228*22ce4affSfengbojiang swcr_cipher_supported(const struct crypto_session_params *csp)
1229*22ce4affSfengbojiang {
1230*22ce4affSfengbojiang 	struct enc_xform *txf;
1231*22ce4affSfengbojiang 
1232*22ce4affSfengbojiang 	txf = crypto_cipher(csp);
1233*22ce4affSfengbojiang 	if (txf == NULL)
1234*22ce4affSfengbojiang 		return (false);
1235*22ce4affSfengbojiang 	if (csp->csp_cipher_alg != CRYPTO_NULL_CBC &&
1236*22ce4affSfengbojiang 	    txf->ivsize != csp->csp_ivlen)
1237*22ce4affSfengbojiang 		return (false);
1238*22ce4affSfengbojiang 	return (true);
1239*22ce4affSfengbojiang }
1240*22ce4affSfengbojiang 
1241*22ce4affSfengbojiang #define SUPPORTED_SES (CSP_F_SEPARATE_OUTPUT | CSP_F_SEPARATE_AAD | CSP_F_ESN)
1242*22ce4affSfengbojiang 
1243*22ce4affSfengbojiang static int
swcr_probesession(device_t dev,const struct crypto_session_params * csp)1244*22ce4affSfengbojiang swcr_probesession(device_t dev, const struct crypto_session_params *csp)
1245*22ce4affSfengbojiang {
1246*22ce4affSfengbojiang 	if ((csp->csp_flags & ~(SUPPORTED_SES)) != 0)
1247*22ce4affSfengbojiang 		return (EINVAL);
1248*22ce4affSfengbojiang 	switch (csp->csp_mode) {
1249*22ce4affSfengbojiang 	case CSP_MODE_COMPRESS:
1250*22ce4affSfengbojiang 		switch (csp->csp_cipher_alg) {
1251*22ce4affSfengbojiang 		case CRYPTO_DEFLATE_COMP:
1252*22ce4affSfengbojiang 			break;
1253*22ce4affSfengbojiang 		default:
1254*22ce4affSfengbojiang 			return (EINVAL);
1255*22ce4affSfengbojiang 		}
1256*22ce4affSfengbojiang 		break;
1257*22ce4affSfengbojiang 	case CSP_MODE_CIPHER:
1258*22ce4affSfengbojiang 		switch (csp->csp_cipher_alg) {
1259*22ce4affSfengbojiang 		case CRYPTO_AES_NIST_GCM_16:
1260*22ce4affSfengbojiang 		case CRYPTO_AES_CCM_16:
1261*22ce4affSfengbojiang 			return (EINVAL);
1262*22ce4affSfengbojiang 		default:
1263*22ce4affSfengbojiang 			if (!swcr_cipher_supported(csp))
1264*22ce4affSfengbojiang 				return (EINVAL);
1265*22ce4affSfengbojiang 			break;
1266*22ce4affSfengbojiang 		}
1267*22ce4affSfengbojiang 		break;
1268*22ce4affSfengbojiang 	case CSP_MODE_DIGEST:
1269*22ce4affSfengbojiang 		if (!swcr_auth_supported(csp))
1270*22ce4affSfengbojiang 			return (EINVAL);
1271*22ce4affSfengbojiang 		break;
1272*22ce4affSfengbojiang 	case CSP_MODE_AEAD:
1273*22ce4affSfengbojiang 		switch (csp->csp_cipher_alg) {
1274*22ce4affSfengbojiang 		case CRYPTO_AES_NIST_GCM_16:
1275*22ce4affSfengbojiang 		case CRYPTO_AES_CCM_16:
1276*22ce4affSfengbojiang 			break;
1277*22ce4affSfengbojiang 		default:
1278*22ce4affSfengbojiang 			return (EINVAL);
1279*22ce4affSfengbojiang 		}
1280*22ce4affSfengbojiang 		break;
1281*22ce4affSfengbojiang 	case CSP_MODE_ETA:
1282*22ce4affSfengbojiang 		/* AEAD algorithms cannot be used for EtA. */
1283*22ce4affSfengbojiang 		switch (csp->csp_cipher_alg) {
1284*22ce4affSfengbojiang 		case CRYPTO_AES_NIST_GCM_16:
1285*22ce4affSfengbojiang 		case CRYPTO_AES_CCM_16:
1286*22ce4affSfengbojiang 			return (EINVAL);
1287*22ce4affSfengbojiang 		}
1288*22ce4affSfengbojiang 		switch (csp->csp_auth_alg) {
1289*22ce4affSfengbojiang 		case CRYPTO_AES_NIST_GMAC:
1290*22ce4affSfengbojiang 		case CRYPTO_AES_CCM_CBC_MAC:
1291*22ce4affSfengbojiang 			return (EINVAL);
1292*22ce4affSfengbojiang 		}
1293*22ce4affSfengbojiang 
1294*22ce4affSfengbojiang 		if (!swcr_cipher_supported(csp) ||
1295*22ce4affSfengbojiang 		    !swcr_auth_supported(csp))
1296*22ce4affSfengbojiang 			return (EINVAL);
1297*22ce4affSfengbojiang 		break;
1298*22ce4affSfengbojiang 	default:
1299*22ce4affSfengbojiang 		return (EINVAL);
1300*22ce4affSfengbojiang 	}
1301*22ce4affSfengbojiang 
1302*22ce4affSfengbojiang 	return (CRYPTODEV_PROBE_SOFTWARE);
1303*22ce4affSfengbojiang }
1304*22ce4affSfengbojiang 
1305a9643ea8Slogwang /*
1306a9643ea8Slogwang  * Generate a new software session.
1307a9643ea8Slogwang  */
1308a9643ea8Slogwang static int
swcr_newsession(device_t dev,crypto_session_t cses,const struct crypto_session_params * csp)1309*22ce4affSfengbojiang swcr_newsession(device_t dev, crypto_session_t cses,
1310*22ce4affSfengbojiang     const struct crypto_session_params *csp)
1311a9643ea8Slogwang {
1312*22ce4affSfengbojiang 	struct swcr_session *ses;
1313*22ce4affSfengbojiang 	struct swcr_encdec *swe;
1314*22ce4affSfengbojiang 	struct swcr_auth *swa;
1315a9643ea8Slogwang 	struct comp_algo *cxf;
1316a9643ea8Slogwang 	int error;
1317a9643ea8Slogwang 
1318*22ce4affSfengbojiang 	ses = crypto_get_driver_session(cses);
1319*22ce4affSfengbojiang 	mtx_init(&ses->swcr_lock, "swcr session lock", NULL, MTX_DEF);
1320a9643ea8Slogwang 
1321*22ce4affSfengbojiang 	error = 0;
1322*22ce4affSfengbojiang 	swe = &ses->swcr_encdec;
1323*22ce4affSfengbojiang 	swa = &ses->swcr_auth;
1324*22ce4affSfengbojiang 	switch (csp->csp_mode) {
1325*22ce4affSfengbojiang 	case CSP_MODE_COMPRESS:
1326*22ce4affSfengbojiang 		switch (csp->csp_cipher_alg) {
1327a9643ea8Slogwang 		case CRYPTO_DEFLATE_COMP:
1328a9643ea8Slogwang 			cxf = &comp_algo_deflate;
1329*22ce4affSfengbojiang 			break;
1330*22ce4affSfengbojiang #ifdef INVARIANTS
1331*22ce4affSfengbojiang 		default:
1332*22ce4affSfengbojiang 			panic("bad compression algo");
1333*22ce4affSfengbojiang #endif
1334*22ce4affSfengbojiang 		}
1335*22ce4affSfengbojiang 		ses->swcr_compdec.sw_cxf = cxf;
1336*22ce4affSfengbojiang 		ses->swcr_process = swcr_compdec;
1337*22ce4affSfengbojiang 		break;
1338*22ce4affSfengbojiang 	case CSP_MODE_CIPHER:
1339*22ce4affSfengbojiang 		switch (csp->csp_cipher_alg) {
1340*22ce4affSfengbojiang 		case CRYPTO_NULL_CBC:
1341*22ce4affSfengbojiang 			ses->swcr_process = swcr_null;
1342*22ce4affSfengbojiang 			break;
1343*22ce4affSfengbojiang #ifdef INVARIANTS
1344*22ce4affSfengbojiang 		case CRYPTO_AES_NIST_GCM_16:
1345*22ce4affSfengbojiang 		case CRYPTO_AES_CCM_16:
1346*22ce4affSfengbojiang 			panic("bad cipher algo");
1347*22ce4affSfengbojiang #endif
1348*22ce4affSfengbojiang 		default:
1349*22ce4affSfengbojiang 			error = swcr_setup_cipher(ses, csp);
1350*22ce4affSfengbojiang 			if (error == 0)
1351*22ce4affSfengbojiang 				ses->swcr_process = swcr_encdec;
1352*22ce4affSfengbojiang 		}
1353*22ce4affSfengbojiang 		break;
1354*22ce4affSfengbojiang 	case CSP_MODE_DIGEST:
1355*22ce4affSfengbojiang 		error = swcr_setup_auth(ses, csp);
1356*22ce4affSfengbojiang 		break;
1357*22ce4affSfengbojiang 	case CSP_MODE_AEAD:
1358*22ce4affSfengbojiang 		switch (csp->csp_cipher_alg) {
1359*22ce4affSfengbojiang 		case CRYPTO_AES_NIST_GCM_16:
1360*22ce4affSfengbojiang 			error = swcr_setup_gcm(ses, csp);
1361*22ce4affSfengbojiang 			if (error == 0)
1362*22ce4affSfengbojiang 				ses->swcr_process = swcr_gcm;
1363*22ce4affSfengbojiang 			break;
1364*22ce4affSfengbojiang 		case CRYPTO_AES_CCM_16:
1365*22ce4affSfengbojiang 			error = swcr_setup_ccm(ses, csp);
1366*22ce4affSfengbojiang 			if (error == 0)
1367*22ce4affSfengbojiang 				ses->swcr_process = swcr_ccm;
1368*22ce4affSfengbojiang 			break;
1369*22ce4affSfengbojiang #ifdef INVARIANTS
1370*22ce4affSfengbojiang 		default:
1371*22ce4affSfengbojiang 			panic("bad aead algo");
1372*22ce4affSfengbojiang #endif
1373*22ce4affSfengbojiang 		}
1374*22ce4affSfengbojiang 		break;
1375*22ce4affSfengbojiang 	case CSP_MODE_ETA:
1376*22ce4affSfengbojiang #ifdef INVARIANTS
1377*22ce4affSfengbojiang 		switch (csp->csp_cipher_alg) {
1378*22ce4affSfengbojiang 		case CRYPTO_AES_NIST_GCM_16:
1379*22ce4affSfengbojiang 		case CRYPTO_AES_CCM_16:
1380*22ce4affSfengbojiang 			panic("bad eta cipher algo");
1381*22ce4affSfengbojiang 		}
1382*22ce4affSfengbojiang 		switch (csp->csp_auth_alg) {
1383*22ce4affSfengbojiang 		case CRYPTO_AES_NIST_GMAC:
1384*22ce4affSfengbojiang 		case CRYPTO_AES_CCM_CBC_MAC:
1385*22ce4affSfengbojiang 			panic("bad eta auth algo");
1386*22ce4affSfengbojiang 		}
1387*22ce4affSfengbojiang #endif
1388*22ce4affSfengbojiang 
1389*22ce4affSfengbojiang 		error = swcr_setup_auth(ses, csp);
1390*22ce4affSfengbojiang 		if (error)
1391*22ce4affSfengbojiang 			break;
1392*22ce4affSfengbojiang 		if (csp->csp_cipher_alg == CRYPTO_NULL_CBC) {
1393*22ce4affSfengbojiang 			/* Effectively degrade to digest mode. */
1394*22ce4affSfengbojiang 			ses->swcr_process = swcr_authcompute;
1395*22ce4affSfengbojiang 			break;
1396*22ce4affSfengbojiang 		}
1397*22ce4affSfengbojiang 
1398*22ce4affSfengbojiang 		error = swcr_setup_cipher(ses, csp);
1399*22ce4affSfengbojiang 		if (error == 0)
1400*22ce4affSfengbojiang 			ses->swcr_process = swcr_eta;
1401a9643ea8Slogwang 		break;
1402a9643ea8Slogwang 	default:
1403*22ce4affSfengbojiang 		error = EINVAL;
1404a9643ea8Slogwang 	}
1405a9643ea8Slogwang 
1406*22ce4affSfengbojiang 	if (error)
1407*22ce4affSfengbojiang 		swcr_freesession(dev, cses);
1408*22ce4affSfengbojiang 	return (error);
1409a9643ea8Slogwang }
1410a9643ea8Slogwang 
1411*22ce4affSfengbojiang static void
swcr_freesession(device_t dev,crypto_session_t cses)1412*22ce4affSfengbojiang swcr_freesession(device_t dev, crypto_session_t cses)
1413a9643ea8Slogwang {
1414*22ce4affSfengbojiang 	struct swcr_session *ses;
1415a9643ea8Slogwang 
1416*22ce4affSfengbojiang 	ses = crypto_get_driver_session(cses);
1417a9643ea8Slogwang 
1418*22ce4affSfengbojiang 	mtx_destroy(&ses->swcr_lock);
1419a9643ea8Slogwang 
1420*22ce4affSfengbojiang 	zfree(ses->swcr_encdec.sw_kschedule, M_CRYPTO_DATA);
1421*22ce4affSfengbojiang 	zfree(ses->swcr_auth.sw_ictx, M_CRYPTO_DATA);
1422*22ce4affSfengbojiang 	zfree(ses->swcr_auth.sw_octx, M_CRYPTO_DATA);
1423a9643ea8Slogwang }
1424a9643ea8Slogwang 
1425a9643ea8Slogwang /*
1426a9643ea8Slogwang  * Process a software request.
1427a9643ea8Slogwang  */
1428a9643ea8Slogwang static int
swcr_process(device_t dev,struct cryptop * crp,int hint)1429a9643ea8Slogwang swcr_process(device_t dev, struct cryptop *crp, int hint)
1430a9643ea8Slogwang {
1431*22ce4affSfengbojiang 	struct swcr_session *ses;
1432a9643ea8Slogwang 
1433*22ce4affSfengbojiang 	ses = crypto_get_driver_session(crp->crp_session);
1434*22ce4affSfengbojiang 	mtx_lock(&ses->swcr_lock);
1435a9643ea8Slogwang 
1436*22ce4affSfengbojiang 	crp->crp_etype = ses->swcr_process(ses, crp);
1437a9643ea8Slogwang 
1438*22ce4affSfengbojiang 	mtx_unlock(&ses->swcr_lock);
1439a9643ea8Slogwang 	crypto_done(crp);
1440*22ce4affSfengbojiang 	return (0);
1441a9643ea8Slogwang }
1442a9643ea8Slogwang 
1443a9643ea8Slogwang static void
swcr_identify(driver_t * drv,device_t parent)1444a9643ea8Slogwang swcr_identify(driver_t *drv, device_t parent)
1445a9643ea8Slogwang {
1446a9643ea8Slogwang 	/* NB: order 10 is so we get attached after h/w devices */
1447a9643ea8Slogwang 	if (device_find_child(parent, "cryptosoft", -1) == NULL &&
1448a9643ea8Slogwang 	    BUS_ADD_CHILD(parent, 10, "cryptosoft", 0) == 0)
1449a9643ea8Slogwang 		panic("cryptosoft: could not attach");
1450a9643ea8Slogwang }
1451a9643ea8Slogwang 
1452a9643ea8Slogwang static int
swcr_probe(device_t dev)1453a9643ea8Slogwang swcr_probe(device_t dev)
1454a9643ea8Slogwang {
1455a9643ea8Slogwang 	device_set_desc(dev, "software crypto");
1456a9643ea8Slogwang 	return (BUS_PROBE_NOWILDCARD);
1457a9643ea8Slogwang }
1458a9643ea8Slogwang 
1459a9643ea8Slogwang static int
swcr_attach(device_t dev)1460a9643ea8Slogwang swcr_attach(device_t dev)
1461a9643ea8Slogwang {
1462a9643ea8Slogwang 
1463*22ce4affSfengbojiang 	swcr_id = crypto_get_driverid(dev, sizeof(struct swcr_session),
1464a9643ea8Slogwang 			CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC);
1465a9643ea8Slogwang 	if (swcr_id < 0) {
1466a9643ea8Slogwang 		device_printf(dev, "cannot initialize!");
1467*22ce4affSfengbojiang 		return (ENXIO);
1468a9643ea8Slogwang 	}
1469a9643ea8Slogwang 
1470*22ce4affSfengbojiang 	return (0);
1471a9643ea8Slogwang }
1472a9643ea8Slogwang 
1473a9643ea8Slogwang static int
swcr_detach(device_t dev)1474a9643ea8Slogwang swcr_detach(device_t dev)
1475a9643ea8Slogwang {
1476a9643ea8Slogwang 	crypto_unregister_all(swcr_id);
1477a9643ea8Slogwang 	return 0;
1478a9643ea8Slogwang }
1479a9643ea8Slogwang 
1480a9643ea8Slogwang static device_method_t swcr_methods[] = {
1481a9643ea8Slogwang 	DEVMETHOD(device_identify,	swcr_identify),
1482a9643ea8Slogwang 	DEVMETHOD(device_probe,		swcr_probe),
1483a9643ea8Slogwang 	DEVMETHOD(device_attach,	swcr_attach),
1484a9643ea8Slogwang 	DEVMETHOD(device_detach,	swcr_detach),
1485a9643ea8Slogwang 
1486*22ce4affSfengbojiang 	DEVMETHOD(cryptodev_probesession, swcr_probesession),
1487a9643ea8Slogwang 	DEVMETHOD(cryptodev_newsession,	swcr_newsession),
1488a9643ea8Slogwang 	DEVMETHOD(cryptodev_freesession,swcr_freesession),
1489a9643ea8Slogwang 	DEVMETHOD(cryptodev_process,	swcr_process),
1490a9643ea8Slogwang 
1491a9643ea8Slogwang 	{0, 0},
1492a9643ea8Slogwang };
1493a9643ea8Slogwang 
1494a9643ea8Slogwang static driver_t swcr_driver = {
1495a9643ea8Slogwang 	"cryptosoft",
1496a9643ea8Slogwang 	swcr_methods,
1497a9643ea8Slogwang 	0,		/* NB: no softc */
1498a9643ea8Slogwang };
1499a9643ea8Slogwang static devclass_t swcr_devclass;
1500a9643ea8Slogwang 
1501a9643ea8Slogwang /*
1502a9643ea8Slogwang  * NB: We explicitly reference the crypto module so we
1503a9643ea8Slogwang  * get the necessary ordering when built as a loadable
1504a9643ea8Slogwang  * module.  This is required because we bundle the crypto
1505a9643ea8Slogwang  * module code together with the cryptosoft driver (otherwise
1506a9643ea8Slogwang  * normal module dependencies would handle things).
1507a9643ea8Slogwang  */
1508a9643ea8Slogwang extern int crypto_modevent(struct module *, int, void *);
1509a9643ea8Slogwang /* XXX where to attach */
1510a9643ea8Slogwang DRIVER_MODULE(cryptosoft, nexus, swcr_driver, swcr_devclass, crypto_modevent,0);
1511a9643ea8Slogwang MODULE_VERSION(cryptosoft, 1);
1512a9643ea8Slogwang MODULE_DEPEND(cryptosoft, crypto, 1, 1, 1);
1513