xref: /dflybsd-src/sys/dev/disk/dm/crypt/dm_target_crypt.c (revision f603807b2c8b9b8ca8a7a99e36eeb70cd39b460d)
1*f603807bSTomohiro Kusumi /*
2*f603807bSTomohiro Kusumi  * Copyright (c) 2010 The DragonFly Project.  All rights reserved.
3*f603807bSTomohiro Kusumi  *
4*f603807bSTomohiro Kusumi  * This code is derived from software contributed to The DragonFly Project
5*f603807bSTomohiro Kusumi  * by Alex Hornung <ahornung@gmail.com>
6*f603807bSTomohiro Kusumi  *
7*f603807bSTomohiro Kusumi  * Redistribution and use in source and binary forms, with or without
8*f603807bSTomohiro Kusumi  * modification, are permitted provided that the following conditions
9*f603807bSTomohiro Kusumi  * are met:
10*f603807bSTomohiro Kusumi  *
11*f603807bSTomohiro Kusumi  * 1. Redistributions of source code must retain the above copyright
12*f603807bSTomohiro Kusumi  *    notice, this list of conditions and the following disclaimer.
13*f603807bSTomohiro Kusumi  * 2. Redistributions in binary form must reproduce the above copyright
14*f603807bSTomohiro Kusumi  *    notice, this list of conditions and the following disclaimer in
15*f603807bSTomohiro Kusumi  *    the documentation and/or other materials provided with the
16*f603807bSTomohiro Kusumi  *    distribution.
17*f603807bSTomohiro Kusumi  * 3. Neither the name of The DragonFly Project nor the names of its
18*f603807bSTomohiro Kusumi  *    contributors may be used to endorse or promote products derived
19*f603807bSTomohiro Kusumi  *    from this software without specific, prior written permission.
20*f603807bSTomohiro Kusumi  *
21*f603807bSTomohiro Kusumi  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22*f603807bSTomohiro Kusumi  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23*f603807bSTomohiro Kusumi  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24*f603807bSTomohiro Kusumi  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25*f603807bSTomohiro Kusumi  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26*f603807bSTomohiro Kusumi  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27*f603807bSTomohiro Kusumi  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28*f603807bSTomohiro Kusumi  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29*f603807bSTomohiro Kusumi  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30*f603807bSTomohiro Kusumi  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31*f603807bSTomohiro Kusumi  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32*f603807bSTomohiro Kusumi  * SUCH DAMAGE.
33*f603807bSTomohiro Kusumi  */
34*f603807bSTomohiro Kusumi 
35*f603807bSTomohiro Kusumi /*
36*f603807bSTomohiro Kusumi  * This file implements initial version of device-mapper crypt target.
37*f603807bSTomohiro Kusumi  */
38*f603807bSTomohiro Kusumi #include <sys/endian.h>
39*f603807bSTomohiro Kusumi 
40*f603807bSTomohiro Kusumi #include <sys/bio.h>
41*f603807bSTomohiro Kusumi #include <sys/globaldata.h>
42*f603807bSTomohiro Kusumi #include <sys/kerneldump.h>
43*f603807bSTomohiro Kusumi #include <sys/malloc.h>
44*f603807bSTomohiro Kusumi #include <sys/mpipe.h>
45*f603807bSTomohiro Kusumi #include <sys/md5.h>
46*f603807bSTomohiro Kusumi #include <sys/mutex2.h>
47*f603807bSTomohiro Kusumi #include <crypto/sha1.h>
48*f603807bSTomohiro Kusumi #include <crypto/sha2/sha2.h>
49*f603807bSTomohiro Kusumi #include <opencrypto/cryptodev.h>
50*f603807bSTomohiro Kusumi #include <opencrypto/rmd160.h>
51*f603807bSTomohiro Kusumi #include <machine/cpufunc.h>
52*f603807bSTomohiro Kusumi #include <cpu/atomic.h>
53*f603807bSTomohiro Kusumi 
54*f603807bSTomohiro Kusumi #include <sys/ktr.h>
55*f603807bSTomohiro Kusumi 
56*f603807bSTomohiro Kusumi #include <dev/disk/dm/dm.h>
57*f603807bSTomohiro Kusumi MALLOC_DEFINE(M_DMCRYPT, "dm_crypt", "Device Mapper Target Crypt");
58*f603807bSTomohiro Kusumi 
59*f603807bSTomohiro Kusumi KTR_INFO_MASTER(dmcrypt);
60*f603807bSTomohiro Kusumi 
61*f603807bSTomohiro Kusumi #if !defined(KTR_DMCRYPT)
62*f603807bSTomohiro Kusumi #define KTR_DMCRYPT	KTR_ALL
63*f603807bSTomohiro Kusumi #endif
64*f603807bSTomohiro Kusumi 
65*f603807bSTomohiro Kusumi KTR_INFO(KTR_DMCRYPT, dmcrypt, crypto_dispatch, 0,
66*f603807bSTomohiro Kusumi     "crypto_dispatch(%p)", struct cryptop *crp);
67*f603807bSTomohiro Kusumi KTR_INFO(KTR_DMCRYPT, dmcrypt, crypt_strategy, 0,
68*f603807bSTomohiro Kusumi     "crypt_strategy(b_cmd = %d, bp = %p)", int cmd, struct buf *bp);
69*f603807bSTomohiro Kusumi KTR_INFO(KTR_DMCRYPT, dmcrypt, crypto_write_start, 1,
70*f603807bSTomohiro Kusumi     "crypto_write_start(crp = %p, bp = %p, sector = %d/%d)",
71*f603807bSTomohiro Kusumi     struct cryptop *crp, struct buf *bp, int i, int sectors);
72*f603807bSTomohiro Kusumi KTR_INFO(KTR_DMCRYPT, dmcrypt, crypto_cb_write_done, 1,
73*f603807bSTomohiro Kusumi     "crypto_cb_write_done(crp = %p, bp = %p, n = %d)",
74*f603807bSTomohiro Kusumi     struct cryptop *crp, struct buf *bp, int n);
75*f603807bSTomohiro Kusumi KTR_INFO(KTR_DMCRYPT, dmcrypt, bio_write_done, 1,
76*f603807bSTomohiro Kusumi     "bio_write_done(bp = %p)", struct buf *bp);
77*f603807bSTomohiro Kusumi KTR_INFO(KTR_DMCRYPT, dmcrypt, crypto_write_retry, 1,
78*f603807bSTomohiro Kusumi     "crypto_write_retry(crp = %p)", struct buf *bp);
79*f603807bSTomohiro Kusumi KTR_INFO(KTR_DMCRYPT, dmcrypt, bio_read_done, 2,
80*f603807bSTomohiro Kusumi     "bio_read_done(bp = %p)", struct buf *bp);
81*f603807bSTomohiro Kusumi KTR_INFO(KTR_DMCRYPT, dmcrypt, crypto_read_start, 2,
82*f603807bSTomohiro Kusumi     "crypto_read_start(crp = %p, bp = %p, sector = %d/%d)",
83*f603807bSTomohiro Kusumi     struct cryptop *crp, struct buf *bp, int i, int sectors);
84*f603807bSTomohiro Kusumi KTR_INFO(KTR_DMCRYPT, dmcrypt, crypto_cb_read_done, 2,
85*f603807bSTomohiro Kusumi     "crypto_cb_read_done(crp = %p, bp = %p, n = %d)",
86*f603807bSTomohiro Kusumi     struct cryptop *crp, struct buf *bp, int n);
87*f603807bSTomohiro Kusumi 
88*f603807bSTomohiro Kusumi struct target_crypt_config;
89*f603807bSTomohiro Kusumi 
90*f603807bSTomohiro Kusumi typedef void dispatch_t(void *);
91*f603807bSTomohiro Kusumi typedef void ivgen_t(struct target_crypt_config *, u_int8_t *, size_t, off_t,
92*f603807bSTomohiro Kusumi     void *);
93*f603807bSTomohiro Kusumi 
94*f603807bSTomohiro Kusumi typedef int ivgen_ctor_t(struct target_crypt_config *, char *, void **);
95*f603807bSTomohiro Kusumi typedef int ivgen_dtor_t(struct target_crypt_config *, void *);
96*f603807bSTomohiro Kusumi 
97*f603807bSTomohiro Kusumi struct iv_generator {
98*f603807bSTomohiro Kusumi 	const char	*name;
99*f603807bSTomohiro Kusumi 	ivgen_ctor_t	*ctor;
100*f603807bSTomohiro Kusumi 	ivgen_dtor_t	*dtor;
101*f603807bSTomohiro Kusumi 	ivgen_t		*gen_iv;
102*f603807bSTomohiro Kusumi };
103*f603807bSTomohiro Kusumi 
104*f603807bSTomohiro Kusumi struct essiv_ivgen_priv {
105*f603807bSTomohiro Kusumi 	struct cryptoini	crypto_session;
106*f603807bSTomohiro Kusumi 	struct objcache	*crp_crd_cache;
107*f603807bSTomohiro Kusumi 	u_int64_t	crypto_sid;
108*f603807bSTomohiro Kusumi 	size_t		keyhash_len;
109*f603807bSTomohiro Kusumi 	u_int8_t	crypto_keyhash[SHA512_DIGEST_LENGTH];
110*f603807bSTomohiro Kusumi };
111*f603807bSTomohiro Kusumi 
112*f603807bSTomohiro Kusumi typedef struct target_crypt_config {
113*f603807bSTomohiro Kusumi 	size_t	params_len;
114*f603807bSTomohiro Kusumi 	dm_pdev_t *pdev;
115*f603807bSTomohiro Kusumi 	char	*status_str;
116*f603807bSTomohiro Kusumi 	int	crypto_alg;
117*f603807bSTomohiro Kusumi 	int	crypto_klen;
118*f603807bSTomohiro Kusumi 	u_int8_t	crypto_key[512>>3];
119*f603807bSTomohiro Kusumi 
120*f603807bSTomohiro Kusumi 	u_int64_t	crypto_sid;
121*f603807bSTomohiro Kusumi 	u_int64_t	block_offset;
122*f603807bSTomohiro Kusumi 	int64_t		iv_offset;
123*f603807bSTomohiro Kusumi 	SHA512_CTX	essivsha512_ctx;
124*f603807bSTomohiro Kusumi 
125*f603807bSTomohiro Kusumi 	struct cryptoini	crypto_session;
126*f603807bSTomohiro Kusumi 
127*f603807bSTomohiro Kusumi 	struct iv_generator	*ivgen;
128*f603807bSTomohiro Kusumi 	void	*ivgen_priv;
129*f603807bSTomohiro Kusumi 
130*f603807bSTomohiro Kusumi 	struct malloc_pipe	read_mpipe;
131*f603807bSTomohiro Kusumi 	struct malloc_pipe	write_mpipe;
132*f603807bSTomohiro Kusumi } dm_target_crypt_config_t;
133*f603807bSTomohiro Kusumi 
134*f603807bSTomohiro Kusumi struct dmtc_helper {
135*f603807bSTomohiro Kusumi 	dm_target_crypt_config_t *priv;
136*f603807bSTomohiro Kusumi 	caddr_t	free_addr;
137*f603807bSTomohiro Kusumi 	caddr_t	orig_buf;
138*f603807bSTomohiro Kusumi 	caddr_t data_buf;
139*f603807bSTomohiro Kusumi };
140*f603807bSTomohiro Kusumi 
141*f603807bSTomohiro Kusumi struct dmtc_dump_helper {
142*f603807bSTomohiro Kusumi 	dm_target_crypt_config_t *priv;
143*f603807bSTomohiro Kusumi 	void *data;
144*f603807bSTomohiro Kusumi 	size_t length;
145*f603807bSTomohiro Kusumi 	off_t offset;
146*f603807bSTomohiro Kusumi 
147*f603807bSTomohiro Kusumi 	int sectors;
148*f603807bSTomohiro Kusumi 	int *ident;
149*f603807bSTomohiro Kusumi 
150*f603807bSTomohiro Kusumi 	struct cryptodesc crd[128];
151*f603807bSTomohiro Kusumi 	struct cryptop crp[128];
152*f603807bSTomohiro Kusumi 	u_char space[65536];
153*f603807bSTomohiro Kusumi };
154*f603807bSTomohiro Kusumi 
155*f603807bSTomohiro Kusumi #define DMTC_BUF_SIZE_WRITE \
156*f603807bSTomohiro Kusumi     MAXPHYS + sizeof(struct dmtc_helper) + \
157*f603807bSTomohiro Kusumi     MAXPHYS/DEV_BSIZE*(sizeof(struct cryptop) + sizeof(struct cryptodesc))
158*f603807bSTomohiro Kusumi #define DMTC_BUF_SIZE_READ \
159*f603807bSTomohiro Kusumi     sizeof(struct dmtc_helper) + \
160*f603807bSTomohiro Kusumi     MAXPHYS/DEV_BSIZE*(sizeof(struct cryptop) + sizeof(struct cryptodesc))
161*f603807bSTomohiro Kusumi 
162*f603807bSTomohiro Kusumi static void dmtc_crypto_dispatch(void *arg);
163*f603807bSTomohiro Kusumi static void dmtc_crypto_dump_start(dm_target_crypt_config_t *priv,
164*f603807bSTomohiro Kusumi 				struct dmtc_dump_helper *dump_helper);
165*f603807bSTomohiro Kusumi static void dmtc_crypto_read_start(dm_target_crypt_config_t *priv,
166*f603807bSTomohiro Kusumi 				struct bio *bio);
167*f603807bSTomohiro Kusumi static void dmtc_crypto_write_start(dm_target_crypt_config_t *priv,
168*f603807bSTomohiro Kusumi 				struct bio *bio);
169*f603807bSTomohiro Kusumi static void dmtc_bio_read_done(struct bio *bio);
170*f603807bSTomohiro Kusumi static void dmtc_bio_write_done(struct bio *bio);
171*f603807bSTomohiro Kusumi static int dmtc_crypto_cb_dump_done(struct cryptop *crp);
172*f603807bSTomohiro Kusumi static int dmtc_crypto_cb_read_done(struct cryptop *crp);
173*f603807bSTomohiro Kusumi static int dmtc_crypto_cb_write_done(struct cryptop *crp);
174*f603807bSTomohiro Kusumi 
175*f603807bSTomohiro Kusumi static ivgen_ctor_t	essiv_ivgen_ctor;
176*f603807bSTomohiro Kusumi static ivgen_dtor_t	essiv_ivgen_dtor;
177*f603807bSTomohiro Kusumi static ivgen_t		essiv_ivgen;
178*f603807bSTomohiro Kusumi static ivgen_t		plain_ivgen;
179*f603807bSTomohiro Kusumi static ivgen_t		plain64_ivgen;
180*f603807bSTomohiro Kusumi 
181*f603807bSTomohiro Kusumi static struct iv_generator ivgens[] = {
182*f603807bSTomohiro Kusumi 	{ .name = "essiv", .ctor = essiv_ivgen_ctor, .dtor = essiv_ivgen_dtor,
183*f603807bSTomohiro Kusumi 	    .gen_iv = essiv_ivgen },
184*f603807bSTomohiro Kusumi 	{ .name = "plain", .ctor = NULL, .dtor = NULL, .gen_iv = plain_ivgen },
185*f603807bSTomohiro Kusumi 	{ .name = "plain64", .ctor = NULL, .dtor = NULL, .gen_iv = plain64_ivgen },
186*f603807bSTomohiro Kusumi 	{ NULL, NULL, NULL, NULL }
187*f603807bSTomohiro Kusumi };
188*f603807bSTomohiro Kusumi 
189*f603807bSTomohiro Kusumi struct objcache_malloc_args essiv_ivgen_malloc_args = {
190*f603807bSTomohiro Kusumi 		2*sizeof(void *) + (sizeof(struct cryptodesc) +
191*f603807bSTomohiro Kusumi 		sizeof(struct cryptop)), M_DMCRYPT };
192*f603807bSTomohiro Kusumi 
193*f603807bSTomohiro Kusumi static void
194*f603807bSTomohiro Kusumi dmtc_init_mpipe(struct target_crypt_config *priv)
195*f603807bSTomohiro Kusumi {
196*f603807bSTomohiro Kusumi 	int nmax;
197*f603807bSTomohiro Kusumi 
198*f603807bSTomohiro Kusumi 	nmax = (physmem*2/1000*PAGE_SIZE)/(DMTC_BUF_SIZE_WRITE + DMTC_BUF_SIZE_READ) + 1;
199*f603807bSTomohiro Kusumi 
200*f603807bSTomohiro Kusumi 	if (nmax < 2)
201*f603807bSTomohiro Kusumi 		nmax = 2;
202*f603807bSTomohiro Kusumi 
203*f603807bSTomohiro Kusumi 	kprintf("dm_target_crypt: Setting min/max mpipe buffers: %d/%d\n", 2, nmax);
204*f603807bSTomohiro Kusumi 
205*f603807bSTomohiro Kusumi 	mpipe_init(&priv->write_mpipe, M_DMCRYPT, DMTC_BUF_SIZE_WRITE,
206*f603807bSTomohiro Kusumi 		   2, nmax, MPF_NOZERO | MPF_CALLBACK, NULL, NULL, NULL);
207*f603807bSTomohiro Kusumi 	mpipe_init(&priv->read_mpipe, M_DMCRYPT, DMTC_BUF_SIZE_READ,
208*f603807bSTomohiro Kusumi 		   2, nmax, MPF_NOZERO | MPF_CALLBACK, NULL, NULL, NULL);
209*f603807bSTomohiro Kusumi }
210*f603807bSTomohiro Kusumi 
211*f603807bSTomohiro Kusumi static void
212*f603807bSTomohiro Kusumi dmtc_destroy_mpipe(struct target_crypt_config *priv)
213*f603807bSTomohiro Kusumi {
214*f603807bSTomohiro Kusumi 	mpipe_done(&priv->write_mpipe);
215*f603807bSTomohiro Kusumi 	mpipe_done(&priv->read_mpipe);
216*f603807bSTomohiro Kusumi }
217*f603807bSTomohiro Kusumi 
218*f603807bSTomohiro Kusumi /*
219*f603807bSTomohiro Kusumi  * Overwrite private information (in buf) to avoid leaking it
220*f603807bSTomohiro Kusumi  */
221*f603807bSTomohiro Kusumi static void
222*f603807bSTomohiro Kusumi dmtc_crypto_clear(void *buf, size_t len)
223*f603807bSTomohiro Kusumi {
224*f603807bSTomohiro Kusumi 	memset(buf, 0xFF, len);
225*f603807bSTomohiro Kusumi 	bzero(buf, len);
226*f603807bSTomohiro Kusumi }
227*f603807bSTomohiro Kusumi 
228*f603807bSTomohiro Kusumi /*
229*f603807bSTomohiro Kusumi  * ESSIV IV Generator Routines
230*f603807bSTomohiro Kusumi  */
231*f603807bSTomohiro Kusumi static int
232*f603807bSTomohiro Kusumi essiv_ivgen_ctor(struct target_crypt_config *priv, char *iv_hash, void **p_ivpriv)
233*f603807bSTomohiro Kusumi {
234*f603807bSTomohiro Kusumi 	struct essiv_ivgen_priv *ivpriv;
235*f603807bSTomohiro Kusumi 	u_int8_t crypto_keyhash[SHA512_DIGEST_LENGTH];
236*f603807bSTomohiro Kusumi 	unsigned int klen, hashlen;
237*f603807bSTomohiro Kusumi 	int error;
238*f603807bSTomohiro Kusumi 
239*f603807bSTomohiro Kusumi 	klen = (priv->crypto_klen >> 3);
240*f603807bSTomohiro Kusumi 
241*f603807bSTomohiro Kusumi 	if (iv_hash == NULL)
242*f603807bSTomohiro Kusumi 		return EINVAL;
243*f603807bSTomohiro Kusumi 
244*f603807bSTomohiro Kusumi 	if (!strcmp(iv_hash, "sha1")) {
245*f603807bSTomohiro Kusumi 		SHA1_CTX ctx;
246*f603807bSTomohiro Kusumi 
247*f603807bSTomohiro Kusumi 		hashlen = SHA1_RESULTLEN;
248*f603807bSTomohiro Kusumi 		SHA1Init(&ctx);
249*f603807bSTomohiro Kusumi 		SHA1Update(&ctx, priv->crypto_key, klen);
250*f603807bSTomohiro Kusumi 		SHA1Final(crypto_keyhash, &ctx);
251*f603807bSTomohiro Kusumi 	} else if (!strcmp(iv_hash, "sha256")) {
252*f603807bSTomohiro Kusumi 		SHA256_CTX ctx;
253*f603807bSTomohiro Kusumi 
254*f603807bSTomohiro Kusumi 		hashlen = SHA256_DIGEST_LENGTH;
255*f603807bSTomohiro Kusumi 		SHA256_Init(&ctx);
256*f603807bSTomohiro Kusumi 		SHA256_Update(&ctx, priv->crypto_key, klen);
257*f603807bSTomohiro Kusumi 		SHA256_Final(crypto_keyhash, &ctx);
258*f603807bSTomohiro Kusumi 	} else if (!strcmp(iv_hash, "sha384")) {
259*f603807bSTomohiro Kusumi 		SHA384_CTX ctx;
260*f603807bSTomohiro Kusumi 
261*f603807bSTomohiro Kusumi 		hashlen = SHA384_DIGEST_LENGTH;
262*f603807bSTomohiro Kusumi 		SHA384_Init(&ctx);
263*f603807bSTomohiro Kusumi 		SHA384_Update(&ctx, priv->crypto_key, klen);
264*f603807bSTomohiro Kusumi 		SHA384_Final(crypto_keyhash, &ctx);
265*f603807bSTomohiro Kusumi 	} else if (!strcmp(iv_hash, "sha512")) {
266*f603807bSTomohiro Kusumi 		SHA512_CTX ctx;
267*f603807bSTomohiro Kusumi 
268*f603807bSTomohiro Kusumi 		hashlen = SHA512_DIGEST_LENGTH;
269*f603807bSTomohiro Kusumi 		SHA512_Init(&ctx);
270*f603807bSTomohiro Kusumi 		SHA512_Update(&ctx, priv->crypto_key, klen);
271*f603807bSTomohiro Kusumi 		SHA512_Final(crypto_keyhash, &ctx);
272*f603807bSTomohiro Kusumi 	} else if (!strcmp(iv_hash, "md5")) {
273*f603807bSTomohiro Kusumi 		MD5_CTX ctx;
274*f603807bSTomohiro Kusumi 
275*f603807bSTomohiro Kusumi 		hashlen = MD5_DIGEST_LENGTH;
276*f603807bSTomohiro Kusumi 		MD5Init(&ctx);
277*f603807bSTomohiro Kusumi 		MD5Update(&ctx, priv->crypto_key, klen);
278*f603807bSTomohiro Kusumi 		MD5Final(crypto_keyhash, &ctx);
279*f603807bSTomohiro Kusumi 	} else if (!strcmp(iv_hash, "rmd160") ||
280*f603807bSTomohiro Kusumi 		   !strcmp(iv_hash, "ripemd160")) {
281*f603807bSTomohiro Kusumi 		RMD160_CTX ctx;
282*f603807bSTomohiro Kusumi 
283*f603807bSTomohiro Kusumi 		hashlen = 160/8;
284*f603807bSTomohiro Kusumi 		RMD160Init(&ctx);
285*f603807bSTomohiro Kusumi 		RMD160Update(&ctx, priv->crypto_key, klen);
286*f603807bSTomohiro Kusumi 		RMD160Final(crypto_keyhash, &ctx);
287*f603807bSTomohiro Kusumi 	} else {
288*f603807bSTomohiro Kusumi 		return EINVAL;
289*f603807bSTomohiro Kusumi 	}
290*f603807bSTomohiro Kusumi 
291*f603807bSTomohiro Kusumi 	/* Convert hashlen to bits */
292*f603807bSTomohiro Kusumi 	hashlen <<= 3;
293*f603807bSTomohiro Kusumi 
294*f603807bSTomohiro Kusumi 	ivpriv = kmalloc(sizeof(struct essiv_ivgen_priv), M_DMCRYPT,
295*f603807bSTomohiro Kusumi 	    M_WAITOK | M_ZERO);
296*f603807bSTomohiro Kusumi 	memcpy(ivpriv->crypto_keyhash, crypto_keyhash, sizeof(crypto_keyhash));
297*f603807bSTomohiro Kusumi 	ivpriv->keyhash_len = sizeof(crypto_keyhash);
298*f603807bSTomohiro Kusumi 	dmtc_crypto_clear(crypto_keyhash, sizeof(crypto_keyhash));
299*f603807bSTomohiro Kusumi 
300*f603807bSTomohiro Kusumi 	ivpriv->crypto_session.cri_alg = priv->crypto_alg;
301*f603807bSTomohiro Kusumi 	ivpriv->crypto_session.cri_key = (u_int8_t *)ivpriv->crypto_keyhash;
302*f603807bSTomohiro Kusumi 	ivpriv->crypto_session.cri_klen = hashlen;
303*f603807bSTomohiro Kusumi 	ivpriv->crypto_session.cri_mlen = 0;
304*f603807bSTomohiro Kusumi 	ivpriv->crypto_session.cri_next = NULL;
305*f603807bSTomohiro Kusumi 
306*f603807bSTomohiro Kusumi 	/*
307*f603807bSTomohiro Kusumi 	 * XXX: in principle we also need to check if the block size of the
308*f603807bSTomohiro Kusumi 	 *	cipher is a valid iv size for the block cipher.
309*f603807bSTomohiro Kusumi 	 */
310*f603807bSTomohiro Kusumi 
311*f603807bSTomohiro Kusumi 	error = crypto_newsession(&ivpriv->crypto_sid,
312*f603807bSTomohiro Kusumi 				  &ivpriv->crypto_session,
313*f603807bSTomohiro Kusumi 				  CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_HARDWARE);
314*f603807bSTomohiro Kusumi 	if (error) {
315*f603807bSTomohiro Kusumi 		kprintf("dm_target_crypt: Error during crypto_newsession "
316*f603807bSTomohiro Kusumi 			"for essiv_ivgen, error = %d\n",
317*f603807bSTomohiro Kusumi 			error);
318*f603807bSTomohiro Kusumi 		dmtc_crypto_clear(ivpriv->crypto_keyhash, ivpriv->keyhash_len);
319*f603807bSTomohiro Kusumi 		kfree(ivpriv, M_DMCRYPT);
320*f603807bSTomohiro Kusumi 		return ENOTSUP;
321*f603807bSTomohiro Kusumi 	}
322*f603807bSTomohiro Kusumi 
323*f603807bSTomohiro Kusumi 	ivpriv->crp_crd_cache = objcache_create(
324*f603807bSTomohiro Kusumi 	    "dmcrypt-essiv-cache", 0, 0,
325*f603807bSTomohiro Kusumi 	    NULL, NULL, NULL,
326*f603807bSTomohiro Kusumi 	    objcache_malloc_alloc,
327*f603807bSTomohiro Kusumi 	    objcache_malloc_free,
328*f603807bSTomohiro Kusumi 	    &essiv_ivgen_malloc_args );
329*f603807bSTomohiro Kusumi 
330*f603807bSTomohiro Kusumi 	*p_ivpriv = ivpriv;
331*f603807bSTomohiro Kusumi 	return 0;
332*f603807bSTomohiro Kusumi }
333*f603807bSTomohiro Kusumi 
334*f603807bSTomohiro Kusumi static int
335*f603807bSTomohiro Kusumi essiv_ivgen_dtor(struct target_crypt_config *priv, void *arg)
336*f603807bSTomohiro Kusumi {
337*f603807bSTomohiro Kusumi 	struct essiv_ivgen_priv *ivpriv;
338*f603807bSTomohiro Kusumi 
339*f603807bSTomohiro Kusumi 	ivpriv = (struct essiv_ivgen_priv *)arg;
340*f603807bSTomohiro Kusumi 	KKASSERT(ivpriv != NULL);
341*f603807bSTomohiro Kusumi 
342*f603807bSTomohiro Kusumi 	crypto_freesession(ivpriv->crypto_sid);
343*f603807bSTomohiro Kusumi 
344*f603807bSTomohiro Kusumi 	objcache_destroy(ivpriv->crp_crd_cache);
345*f603807bSTomohiro Kusumi 
346*f603807bSTomohiro Kusumi 	dmtc_crypto_clear(ivpriv->crypto_keyhash, ivpriv->keyhash_len);
347*f603807bSTomohiro Kusumi 	kfree(ivpriv, M_DMCRYPT);
348*f603807bSTomohiro Kusumi 
349*f603807bSTomohiro Kusumi 	return 0;
350*f603807bSTomohiro Kusumi }
351*f603807bSTomohiro Kusumi 
352*f603807bSTomohiro Kusumi static int
353*f603807bSTomohiro Kusumi essiv_ivgen_done(struct cryptop *crp)
354*f603807bSTomohiro Kusumi {
355*f603807bSTomohiro Kusumi 	struct essiv_ivgen_priv *ivpriv;
356*f603807bSTomohiro Kusumi 	void *free_addr;
357*f603807bSTomohiro Kusumi 	void *opaque;
358*f603807bSTomohiro Kusumi 
359*f603807bSTomohiro Kusumi 
360*f603807bSTomohiro Kusumi 	if (crp->crp_etype == EAGAIN)
361*f603807bSTomohiro Kusumi 		return crypto_dispatch(crp);
362*f603807bSTomohiro Kusumi 
363*f603807bSTomohiro Kusumi 	if (crp->crp_etype != 0) {
364*f603807bSTomohiro Kusumi 		kprintf("dm_target_crypt: essiv_ivgen_done, "
365*f603807bSTomohiro Kusumi 			"crp->crp_etype = %d\n", crp->crp_etype);
366*f603807bSTomohiro Kusumi 	}
367*f603807bSTomohiro Kusumi 
368*f603807bSTomohiro Kusumi 	free_addr = crp->crp_opaque;
369*f603807bSTomohiro Kusumi 	/*
370*f603807bSTomohiro Kusumi 	 * In-memory structure is:
371*f603807bSTomohiro Kusumi 	 * |  ivpriv  |  opaque  |     crp     |      crd      |
372*f603807bSTomohiro Kusumi 	 * | (void *) | (void *) |   (cryptop) |  (cryptodesc) |
373*f603807bSTomohiro Kusumi 	 */
374*f603807bSTomohiro Kusumi 	ivpriv = *((struct essiv_ivgen_priv **)crp->crp_opaque);
375*f603807bSTomohiro Kusumi 	crp->crp_opaque += sizeof(void *);
376*f603807bSTomohiro Kusumi 	opaque = *((void **)crp->crp_opaque);
377*f603807bSTomohiro Kusumi 
378*f603807bSTomohiro Kusumi 	objcache_put(ivpriv->crp_crd_cache, free_addr);
379*f603807bSTomohiro Kusumi 	dmtc_crypto_dispatch(opaque);
380*f603807bSTomohiro Kusumi 	return 0;
381*f603807bSTomohiro Kusumi }
382*f603807bSTomohiro Kusumi 
383*f603807bSTomohiro Kusumi static void
384*f603807bSTomohiro Kusumi essiv_ivgen(dm_target_crypt_config_t *priv, u_int8_t *iv,
385*f603807bSTomohiro Kusumi 	    size_t iv_len, off_t sector, void *opaque)
386*f603807bSTomohiro Kusumi {
387*f603807bSTomohiro Kusumi 	struct essiv_ivgen_priv *ivpriv;
388*f603807bSTomohiro Kusumi 	struct cryptodesc *crd;
389*f603807bSTomohiro Kusumi 	struct cryptop *crp;
390*f603807bSTomohiro Kusumi 	caddr_t space, alloc_addr;
391*f603807bSTomohiro Kusumi 	int error;
392*f603807bSTomohiro Kusumi 
393*f603807bSTomohiro Kusumi 	ivpriv = priv->ivgen_priv;
394*f603807bSTomohiro Kusumi 	KKASSERT(ivpriv != NULL);
395*f603807bSTomohiro Kusumi 
396*f603807bSTomohiro Kusumi 	/*
397*f603807bSTomohiro Kusumi 	 * In-memory structure is:
398*f603807bSTomohiro Kusumi 	 * |  ivpriv  |  opaque  |     crp     |      crd      |
399*f603807bSTomohiro Kusumi 	 * | (void *) | (void *) |   (cryptop) |  (cryptodesc) |
400*f603807bSTomohiro Kusumi 	 */
401*f603807bSTomohiro Kusumi 	alloc_addr = space = objcache_get(ivpriv->crp_crd_cache, M_WAITOK);
402*f603807bSTomohiro Kusumi 	*((struct essiv_ivgen_priv **)space) = ivpriv;
403*f603807bSTomohiro Kusumi 	space += sizeof(void *);
404*f603807bSTomohiro Kusumi 	*((void **)space) = opaque;
405*f603807bSTomohiro Kusumi 	space += sizeof(void *);
406*f603807bSTomohiro Kusumi 	crp = (struct cryptop *)space;
407*f603807bSTomohiro Kusumi 	space += sizeof(struct cryptop);
408*f603807bSTomohiro Kusumi 	crd = (struct cryptodesc *)space;
409*f603807bSTomohiro Kusumi 
410*f603807bSTomohiro Kusumi 	bzero(iv, iv_len);
411*f603807bSTomohiro Kusumi 	bzero(crd, sizeof(struct cryptodesc));
412*f603807bSTomohiro Kusumi 	bzero(crp, sizeof(struct cryptop));
413*f603807bSTomohiro Kusumi 	*((off_t *)iv) = htole64(sector + priv->iv_offset);
414*f603807bSTomohiro Kusumi 	crp->crp_buf = (caddr_t)iv;
415*f603807bSTomohiro Kusumi 
416*f603807bSTomohiro Kusumi 	crp->crp_sid = ivpriv->crypto_sid;
417*f603807bSTomohiro Kusumi 	crp->crp_ilen = crp->crp_olen = iv_len;
418*f603807bSTomohiro Kusumi 
419*f603807bSTomohiro Kusumi 	crp->crp_opaque = alloc_addr;
420*f603807bSTomohiro Kusumi 
421*f603807bSTomohiro Kusumi 	crp->crp_callback = essiv_ivgen_done;
422*f603807bSTomohiro Kusumi 
423*f603807bSTomohiro Kusumi 	crp->crp_desc = crd;
424*f603807bSTomohiro Kusumi 	crp->crp_etype = 0;
425*f603807bSTomohiro Kusumi 	crp->crp_flags = CRYPTO_F_CBIFSYNC | CRYPTO_F_REL | CRYPTO_F_BATCH;
426*f603807bSTomohiro Kusumi 
427*f603807bSTomohiro Kusumi 	crd->crd_alg = priv->crypto_alg;
428*f603807bSTomohiro Kusumi #if 0
429*f603807bSTomohiro Kusumi 	crd->crd_key = (caddr_t)priv->crypto_keyhash;
430*f603807bSTomohiro Kusumi 	crd->crd_klen = priv->crypto_klen;
431*f603807bSTomohiro Kusumi #endif
432*f603807bSTomohiro Kusumi 
433*f603807bSTomohiro Kusumi 	bzero(crd->crd_iv, sizeof(crd->crd_iv));
434*f603807bSTomohiro Kusumi 
435*f603807bSTomohiro Kusumi 	crd->crd_skip = 0;
436*f603807bSTomohiro Kusumi 	crd->crd_len = iv_len;
437*f603807bSTomohiro Kusumi 	crd->crd_flags = CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
438*f603807bSTomohiro Kusumi 	crd->crd_flags |= CRD_F_ENCRYPT;
439*f603807bSTomohiro Kusumi 	crd->crd_next = NULL;
440*f603807bSTomohiro Kusumi 
441*f603807bSTomohiro Kusumi 	error = crypto_dispatch(crp);
442*f603807bSTomohiro Kusumi 	if (error)
443*f603807bSTomohiro Kusumi 		kprintf("dm_target_crypt: essiv_ivgen, error = %d\n", error);
444*f603807bSTomohiro Kusumi }
445*f603807bSTomohiro Kusumi 
446*f603807bSTomohiro Kusumi 
447*f603807bSTomohiro Kusumi static void
448*f603807bSTomohiro Kusumi plain_ivgen(dm_target_crypt_config_t *priv, u_int8_t *iv,
449*f603807bSTomohiro Kusumi 	    size_t iv_len, off_t sector, void *opaque)
450*f603807bSTomohiro Kusumi {
451*f603807bSTomohiro Kusumi 	bzero(iv, iv_len);
452*f603807bSTomohiro Kusumi 	*((uint32_t *)iv) = htole32((uint32_t)(sector + priv->iv_offset));
453*f603807bSTomohiro Kusumi 	dmtc_crypto_dispatch(opaque);
454*f603807bSTomohiro Kusumi }
455*f603807bSTomohiro Kusumi 
456*f603807bSTomohiro Kusumi static void
457*f603807bSTomohiro Kusumi plain64_ivgen(dm_target_crypt_config_t *priv, u_int8_t *iv,
458*f603807bSTomohiro Kusumi     size_t iv_len, off_t sector, void *opaque)
459*f603807bSTomohiro Kusumi {
460*f603807bSTomohiro Kusumi 	bzero(iv, iv_len);
461*f603807bSTomohiro Kusumi 	*((uint64_t *)iv) = htole64((uint64_t)(sector + priv->iv_offset));
462*f603807bSTomohiro Kusumi 	dmtc_crypto_dispatch(opaque);
463*f603807bSTomohiro Kusumi }
464*f603807bSTomohiro Kusumi 
465*f603807bSTomohiro Kusumi #if 0
466*f603807bSTomohiro Kusumi static void
467*f603807bSTomohiro Kusumi geli_ivgen(dm_target_crypt_config_t *priv, u_int8_t *iv,
468*f603807bSTomohiro Kusumi 	   size_t iv_len, off_t sector, void *opaque)
469*f603807bSTomohiro Kusumi {
470*f603807bSTomohiro Kusumi 
471*f603807bSTomohiro Kusumi 	SHA512_CTX	ctx512;
472*f603807bSTomohiro Kusumi 	u_int8_t	md[SHA512_DIGEST_LENGTH]; /* Max. Digest Size */
473*f603807bSTomohiro Kusumi 
474*f603807bSTomohiro Kusumi 	memcpy(&ctx512, &priv->essivsha512_ctx, sizeof(SHA512_CTX));
475*f603807bSTomohiro Kusumi 	SHA512_Update(&ctx512, (u_int8_t*)&sector, sizeof(off_t));
476*f603807bSTomohiro Kusumi 	SHA512_Final(md, &ctx512);
477*f603807bSTomohiro Kusumi 
478*f603807bSTomohiro Kusumi 	memcpy(iv, md, iv_len);
479*f603807bSTomohiro Kusumi 	dmtc_crypto_dispatch(opaque);
480*f603807bSTomohiro Kusumi }
481*f603807bSTomohiro Kusumi #endif
482*f603807bSTomohiro Kusumi 
483*f603807bSTomohiro Kusumi /*
484*f603807bSTomohiro Kusumi  * Init function called from dm_table_load_ioctl.
485*f603807bSTomohiro Kusumi  * cryptsetup actually passes us this:
486*f603807bSTomohiro Kusumi  * aes-cbc-essiv:sha256 7997f8af... 0 /dev/ad0s0a 8
487*f603807bSTomohiro Kusumi  */
488*f603807bSTomohiro Kusumi static int
489*f603807bSTomohiro Kusumi hex2key(char *hex, size_t key_len, u_int8_t *key)
490*f603807bSTomohiro Kusumi {
491*f603807bSTomohiro Kusumi 	char hex_buf[3];
492*f603807bSTomohiro Kusumi 	size_t key_idx;
493*f603807bSTomohiro Kusumi 
494*f603807bSTomohiro Kusumi 	hex_buf[2] = 0;
495*f603807bSTomohiro Kusumi 	for (key_idx = 0; key_idx < key_len; ++key_idx) {
496*f603807bSTomohiro Kusumi 		hex_buf[0] = *hex++;
497*f603807bSTomohiro Kusumi 		hex_buf[1] = *hex++;
498*f603807bSTomohiro Kusumi 		key[key_idx] = (u_int8_t)strtoul(hex_buf, NULL, 16);
499*f603807bSTomohiro Kusumi 	}
500*f603807bSTomohiro Kusumi 	hex_buf[0] = 0;
501*f603807bSTomohiro Kusumi 	hex_buf[1] = 0;
502*f603807bSTomohiro Kusumi 
503*f603807bSTomohiro Kusumi 	return 0;
504*f603807bSTomohiro Kusumi }
505*f603807bSTomohiro Kusumi 
506*f603807bSTomohiro Kusumi static int
507*f603807bSTomohiro Kusumi dm_target_crypt_init(dm_table_entry_t *table_en, int argc, char **argv)
508*f603807bSTomohiro Kusumi {
509*f603807bSTomohiro Kusumi 	dm_target_crypt_config_t *priv;
510*f603807bSTomohiro Kusumi 	size_t len;
511*f603807bSTomohiro Kusumi 	char *crypto_alg, *crypto_mode, *iv_mode, *iv_opt, *key, *dev;
512*f603807bSTomohiro Kusumi 	char *status_str;
513*f603807bSTomohiro Kusumi 	int i, klen, error;
514*f603807bSTomohiro Kusumi 	uint64_t iv_offset, block_offset;
515*f603807bSTomohiro Kusumi 
516*f603807bSTomohiro Kusumi 	if (argc != 5) {
517*f603807bSTomohiro Kusumi 		kprintf("dm_target_crypt: not enough arguments, "
518*f603807bSTomohiro Kusumi 			"need exactly 5\n");
519*f603807bSTomohiro Kusumi 		return EINVAL;
520*f603807bSTomohiro Kusumi 	}
521*f603807bSTomohiro Kusumi 
522*f603807bSTomohiro Kusumi 	len = 0;
523*f603807bSTomohiro Kusumi 	for (i = 0; i < argc; i++) {
524*f603807bSTomohiro Kusumi 		len += strlen(argv[i]);
525*f603807bSTomohiro Kusumi 		len++;
526*f603807bSTomohiro Kusumi 	}
527*f603807bSTomohiro Kusumi 	/* len is strlen() of input string +1 */
528*f603807bSTomohiro Kusumi 	status_str = kmalloc(len, M_DMCRYPT, M_WAITOK);
529*f603807bSTomohiro Kusumi 
530*f603807bSTomohiro Kusumi 	crypto_alg = strsep(&argv[0], "-");
531*f603807bSTomohiro Kusumi 	crypto_mode = strsep(&argv[0], "-");
532*f603807bSTomohiro Kusumi 	iv_opt = strsep(&argv[0], "-");
533*f603807bSTomohiro Kusumi 	iv_mode = strsep(&iv_opt, ":");
534*f603807bSTomohiro Kusumi 	key = argv[1];
535*f603807bSTomohiro Kusumi 	iv_offset = strtouq(argv[2], NULL, 0);
536*f603807bSTomohiro Kusumi 	dev = argv[3];
537*f603807bSTomohiro Kusumi 	block_offset = strtouq(argv[4], NULL, 0);
538*f603807bSTomohiro Kusumi 	/* bits / 8 = bytes, 1 byte = 2 hexa chars, so << 2 */
539*f603807bSTomohiro Kusumi 	klen = strlen(key) << 2;
540*f603807bSTomohiro Kusumi 
541*f603807bSTomohiro Kusumi #if 0
542*f603807bSTomohiro Kusumi 	kprintf("dm_target_crypt - new: dev=%s, crypto_alg=%s, crypto_mode=%s, "
543*f603807bSTomohiro Kusumi 		"iv_mode=%s, iv_opt=%s, key=%s, iv_offset=%ju, "
544*f603807bSTomohiro Kusumi 		"block_offset=%ju\n",
545*f603807bSTomohiro Kusumi 		dev, crypto_alg, crypto_mode, iv_mode, iv_opt, key, iv_offset,
546*f603807bSTomohiro Kusumi 		block_offset);
547*f603807bSTomohiro Kusumi #endif
548*f603807bSTomohiro Kusumi 
549*f603807bSTomohiro Kusumi 	priv = kmalloc(sizeof(dm_target_crypt_config_t), M_DMCRYPT, M_WAITOK);
550*f603807bSTomohiro Kusumi 
551*f603807bSTomohiro Kusumi 	/* Insert dmp to global pdev list */
552*f603807bSTomohiro Kusumi 	if ((priv->pdev = dm_pdev_insert(dev)) == NULL) {
553*f603807bSTomohiro Kusumi 		kprintf("dm_target_crypt: dm_pdev_insert failed\n");
554*f603807bSTomohiro Kusumi 		kfree(status_str, M_DMCRYPT);
555*f603807bSTomohiro Kusumi 		return ENOENT;
556*f603807bSTomohiro Kusumi 	}
557*f603807bSTomohiro Kusumi 
558*f603807bSTomohiro Kusumi 	/*
559*f603807bSTomohiro Kusumi 	 * This code checks for valid combinations of algorithm and mode.
560*f603807bSTomohiro Kusumi 	 * Currently supported options are:
561*f603807bSTomohiro Kusumi 	 *
562*f603807bSTomohiro Kusumi 	 * *-cbc
563*f603807bSTomohiro Kusumi 	 * aes-xts
564*f603807bSTomohiro Kusumi 	 * twofish-xts
565*f603807bSTomohiro Kusumi 	 * serpent-xts
566*f603807bSTomohiro Kusumi 	 */
567*f603807bSTomohiro Kusumi 	if ((strcmp(crypto_mode, "cbc") != 0) &&
568*f603807bSTomohiro Kusumi 	    !((strcmp(crypto_mode, "xts") == 0) &&
569*f603807bSTomohiro Kusumi 	    ((strcmp(crypto_alg, "aes") == 0) ||
570*f603807bSTomohiro Kusumi 	    (strcmp(crypto_alg, "twofish") == 0) ||
571*f603807bSTomohiro Kusumi 	    (strcmp(crypto_alg, "serpent") == 0))))
572*f603807bSTomohiro Kusumi 	{
573*f603807bSTomohiro Kusumi 		kprintf("dm_target_crypt: only support 'cbc' chaining mode,"
574*f603807bSTomohiro Kusumi 		    " aes-xts, twofish-xts and serpent-xts, "
575*f603807bSTomohiro Kusumi 		    "invalid mode '%s-%s'\n",
576*f603807bSTomohiro Kusumi 		    crypto_alg, crypto_mode);
577*f603807bSTomohiro Kusumi 		goto notsup;
578*f603807bSTomohiro Kusumi 	}
579*f603807bSTomohiro Kusumi 
580*f603807bSTomohiro Kusumi 	if (!strcmp(crypto_alg, "aes")) {
581*f603807bSTomohiro Kusumi 		if (!strcmp(crypto_mode, "xts")) {
582*f603807bSTomohiro Kusumi 			priv->crypto_alg = CRYPTO_AES_XTS;
583*f603807bSTomohiro Kusumi 			if (klen != 256 && klen != 512)
584*f603807bSTomohiro Kusumi 				goto notsup;
585*f603807bSTomohiro Kusumi 		} else if (!strcmp(crypto_mode, "cbc")) {
586*f603807bSTomohiro Kusumi 			priv->crypto_alg = CRYPTO_AES_CBC;
587*f603807bSTomohiro Kusumi 			if (klen != 128 && klen != 192 && klen != 256)
588*f603807bSTomohiro Kusumi 				goto notsup;
589*f603807bSTomohiro Kusumi 		} else {
590*f603807bSTomohiro Kusumi 			goto notsup;
591*f603807bSTomohiro Kusumi 		}
592*f603807bSTomohiro Kusumi 		priv->crypto_klen = klen;
593*f603807bSTomohiro Kusumi 	} else if (!strcmp(crypto_alg, "twofish")) {
594*f603807bSTomohiro Kusumi 		if (!strcmp(crypto_mode, "xts")) {
595*f603807bSTomohiro Kusumi 			priv->crypto_alg = CRYPTO_TWOFISH_XTS;
596*f603807bSTomohiro Kusumi 			if (klen != 256 && klen != 512)
597*f603807bSTomohiro Kusumi 				goto notsup;
598*f603807bSTomohiro Kusumi 		} else if (!strcmp(crypto_mode, "cbc")) {
599*f603807bSTomohiro Kusumi 			priv->crypto_alg = CRYPTO_TWOFISH_CBC;
600*f603807bSTomohiro Kusumi 			if (klen != 128 && klen != 192 && klen != 256)
601*f603807bSTomohiro Kusumi 				goto notsup;
602*f603807bSTomohiro Kusumi 		} else {
603*f603807bSTomohiro Kusumi 			goto notsup;
604*f603807bSTomohiro Kusumi 		}
605*f603807bSTomohiro Kusumi 		priv->crypto_klen = klen;
606*f603807bSTomohiro Kusumi 	} else if (!strcmp(crypto_alg, "serpent")) {
607*f603807bSTomohiro Kusumi 		if (!strcmp(crypto_mode, "xts")) {
608*f603807bSTomohiro Kusumi 			priv->crypto_alg = CRYPTO_SERPENT_XTS;
609*f603807bSTomohiro Kusumi 			if (klen != 256 && klen != 512)
610*f603807bSTomohiro Kusumi 				goto notsup;
611*f603807bSTomohiro Kusumi 		} else if (!strcmp(crypto_mode, "cbc")) {
612*f603807bSTomohiro Kusumi 			priv->crypto_alg = CRYPTO_SERPENT_CBC;
613*f603807bSTomohiro Kusumi 			if (klen != 128 && klen != 192 && klen != 256)
614*f603807bSTomohiro Kusumi 				goto notsup;
615*f603807bSTomohiro Kusumi 		} else {
616*f603807bSTomohiro Kusumi 			goto notsup;
617*f603807bSTomohiro Kusumi 		}
618*f603807bSTomohiro Kusumi 		priv->crypto_klen = klen;
619*f603807bSTomohiro Kusumi 	} else if (!strcmp(crypto_alg, "blowfish")) {
620*f603807bSTomohiro Kusumi 		priv->crypto_alg = CRYPTO_BLF_CBC;
621*f603807bSTomohiro Kusumi 		if (klen < 128 || klen > 448 || (klen % 8) != 0)
622*f603807bSTomohiro Kusumi 			goto notsup;
623*f603807bSTomohiro Kusumi 		priv->crypto_klen = klen;
624*f603807bSTomohiro Kusumi 	} else if (!strcmp(crypto_alg, "3des") ||
625*f603807bSTomohiro Kusumi 		   !strncmp(crypto_alg, "des3", 4)) {
626*f603807bSTomohiro Kusumi 		priv->crypto_alg = CRYPTO_3DES_CBC;
627*f603807bSTomohiro Kusumi 		if (klen != 168)
628*f603807bSTomohiro Kusumi 			goto notsup;
629*f603807bSTomohiro Kusumi 		priv->crypto_klen = 168;
630*f603807bSTomohiro Kusumi 	} else if (!strcmp(crypto_alg, "camellia")) {
631*f603807bSTomohiro Kusumi 		priv->crypto_alg = CRYPTO_CAMELLIA_CBC;
632*f603807bSTomohiro Kusumi 		if (klen != 128 && klen != 192 && klen != 256)
633*f603807bSTomohiro Kusumi 			goto notsup;
634*f603807bSTomohiro Kusumi 		priv->crypto_klen = klen;
635*f603807bSTomohiro Kusumi 	} else if (!strcmp(crypto_alg, "skipjack")) {
636*f603807bSTomohiro Kusumi 		priv->crypto_alg = CRYPTO_SKIPJACK_CBC;
637*f603807bSTomohiro Kusumi 		if (klen != 80)
638*f603807bSTomohiro Kusumi 			goto notsup;
639*f603807bSTomohiro Kusumi 		priv->crypto_klen = 80;
640*f603807bSTomohiro Kusumi 	} else if (!strcmp(crypto_alg, "cast5")) {
641*f603807bSTomohiro Kusumi 		priv->crypto_alg = CRYPTO_CAST_CBC;
642*f603807bSTomohiro Kusumi 		if (klen != 128)
643*f603807bSTomohiro Kusumi 			goto notsup;
644*f603807bSTomohiro Kusumi 		priv->crypto_klen = 128;
645*f603807bSTomohiro Kusumi 	} else if (!strcmp(crypto_alg, "null")) {
646*f603807bSTomohiro Kusumi 		priv->crypto_alg = CRYPTO_NULL_CBC;
647*f603807bSTomohiro Kusumi 		if (klen != 128)
648*f603807bSTomohiro Kusumi 			goto notsup;
649*f603807bSTomohiro Kusumi 		priv->crypto_klen = 128;
650*f603807bSTomohiro Kusumi 	} else {
651*f603807bSTomohiro Kusumi 		kprintf("dm_target_crypt: Unsupported crypto algorithm: %s\n",
652*f603807bSTomohiro Kusumi 			crypto_alg);
653*f603807bSTomohiro Kusumi 		goto notsup;
654*f603807bSTomohiro Kusumi 	}
655*f603807bSTomohiro Kusumi 
656*f603807bSTomohiro Kusumi 	/* Save length of param string */
657*f603807bSTomohiro Kusumi 	priv->params_len = len;
658*f603807bSTomohiro Kusumi 	priv->block_offset = block_offset;
659*f603807bSTomohiro Kusumi 	priv->iv_offset = iv_offset - block_offset;
660*f603807bSTomohiro Kusumi 
661*f603807bSTomohiro Kusumi 	dm_table_add_deps(table_en, priv->pdev);
662*f603807bSTomohiro Kusumi 
663*f603807bSTomohiro Kusumi 	dm_table_init_target(table_en, DM_CRYPTO_DEV, priv);
664*f603807bSTomohiro Kusumi 
665*f603807bSTomohiro Kusumi 	error = hex2key(key, priv->crypto_klen >> 3,
666*f603807bSTomohiro Kusumi 			(u_int8_t *)priv->crypto_key);
667*f603807bSTomohiro Kusumi 
668*f603807bSTomohiro Kusumi 	if (error) {
669*f603807bSTomohiro Kusumi 		kprintf("dm_target_crypt: hex2key failed, "
670*f603807bSTomohiro Kusumi 			"invalid key format\n");
671*f603807bSTomohiro Kusumi 		goto notsup;
672*f603807bSTomohiro Kusumi 	}
673*f603807bSTomohiro Kusumi 
674*f603807bSTomohiro Kusumi 	/* Handle cmd */
675*f603807bSTomohiro Kusumi 	for(i = 0; ivgens[i].name != NULL; i++) {
676*f603807bSTomohiro Kusumi 		if (!strcmp(iv_mode, ivgens[i].name))
677*f603807bSTomohiro Kusumi 			break;
678*f603807bSTomohiro Kusumi 	}
679*f603807bSTomohiro Kusumi 
680*f603807bSTomohiro Kusumi 	if (ivgens[i].name == NULL) {
681*f603807bSTomohiro Kusumi 		kprintf("dm_target_crypt: iv_mode='%s' unsupported\n",
682*f603807bSTomohiro Kusumi 			iv_mode);
683*f603807bSTomohiro Kusumi 		goto notsup;
684*f603807bSTomohiro Kusumi 	}
685*f603807bSTomohiro Kusumi 
686*f603807bSTomohiro Kusumi 	/* Call our ivgen constructor */
687*f603807bSTomohiro Kusumi 	if (ivgens[i].ctor != NULL) {
688*f603807bSTomohiro Kusumi 		error = ivgens[i].ctor(priv, iv_opt,
689*f603807bSTomohiro Kusumi 		    &priv->ivgen_priv);
690*f603807bSTomohiro Kusumi 		if (error) {
691*f603807bSTomohiro Kusumi 			kprintf("dm_target_crypt: ctor for '%s' failed\n",
692*f603807bSTomohiro Kusumi 			    ivgens[i].name);
693*f603807bSTomohiro Kusumi 			goto notsup;
694*f603807bSTomohiro Kusumi 		}
695*f603807bSTomohiro Kusumi 	}
696*f603807bSTomohiro Kusumi 
697*f603807bSTomohiro Kusumi 	priv->ivgen = &ivgens[i];
698*f603807bSTomohiro Kusumi 
699*f603807bSTomohiro Kusumi 	priv->crypto_session.cri_alg = priv->crypto_alg;
700*f603807bSTomohiro Kusumi 	priv->crypto_session.cri_key = (u_int8_t *)priv->crypto_key;
701*f603807bSTomohiro Kusumi 	priv->crypto_session.cri_klen = priv->crypto_klen;
702*f603807bSTomohiro Kusumi 	priv->crypto_session.cri_mlen = 0;
703*f603807bSTomohiro Kusumi 	priv->crypto_session.cri_next = NULL;
704*f603807bSTomohiro Kusumi 
705*f603807bSTomohiro Kusumi 	error = crypto_newsession(&priv->crypto_sid,
706*f603807bSTomohiro Kusumi 				  &priv->crypto_session,
707*f603807bSTomohiro Kusumi 				  CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_HARDWARE);
708*f603807bSTomohiro Kusumi 	if (error) {
709*f603807bSTomohiro Kusumi 		kprintf("dm_target_crypt: Error during crypto_newsession, "
710*f603807bSTomohiro Kusumi 			"error = %d\n",
711*f603807bSTomohiro Kusumi 			error);
712*f603807bSTomohiro Kusumi 		goto notsup;
713*f603807bSTomohiro Kusumi 	}
714*f603807bSTomohiro Kusumi 
715*f603807bSTomohiro Kusumi 	memset(key, '0', strlen(key));
716*f603807bSTomohiro Kusumi 	if (iv_opt) {
717*f603807bSTomohiro Kusumi 		ksprintf(status_str, "%s-%s-%s:%s %s %ju %s %ju",
718*f603807bSTomohiro Kusumi 		    crypto_alg, crypto_mode, iv_mode, iv_opt,
719*f603807bSTomohiro Kusumi 		    key, iv_offset, dev, block_offset);
720*f603807bSTomohiro Kusumi 	} else {
721*f603807bSTomohiro Kusumi 		ksprintf(status_str, "%s-%s-%s %s %ju %s %ju",
722*f603807bSTomohiro Kusumi 		    crypto_alg, crypto_mode, iv_mode,
723*f603807bSTomohiro Kusumi 		    key, iv_offset, dev, block_offset);
724*f603807bSTomohiro Kusumi 	}
725*f603807bSTomohiro Kusumi 	priv->status_str = status_str;
726*f603807bSTomohiro Kusumi 
727*f603807bSTomohiro Kusumi 	/* Initialize mpipes */
728*f603807bSTomohiro Kusumi 	dmtc_init_mpipe(priv);
729*f603807bSTomohiro Kusumi 
730*f603807bSTomohiro Kusumi 	return 0;
731*f603807bSTomohiro Kusumi 
732*f603807bSTomohiro Kusumi notsup:
733*f603807bSTomohiro Kusumi 	kprintf("dm_target_crypt: ENOTSUP\n");
734*f603807bSTomohiro Kusumi 	kfree(status_str, M_DMCRYPT);
735*f603807bSTomohiro Kusumi 	return ENOTSUP;
736*f603807bSTomohiro Kusumi }
737*f603807bSTomohiro Kusumi 
738*f603807bSTomohiro Kusumi /* Table routine called to get params string. */
739*f603807bSTomohiro Kusumi static char *
740*f603807bSTomohiro Kusumi dm_target_crypt_table(void *target_config)
741*f603807bSTomohiro Kusumi {
742*f603807bSTomohiro Kusumi 	dm_target_crypt_config_t *priv;
743*f603807bSTomohiro Kusumi 	char *params;
744*f603807bSTomohiro Kusumi 
745*f603807bSTomohiro Kusumi 	priv = target_config;
746*f603807bSTomohiro Kusumi 
747*f603807bSTomohiro Kusumi 	params = dm_alloc_string(DM_MAX_PARAMS_SIZE);
748*f603807bSTomohiro Kusumi 
749*f603807bSTomohiro Kusumi 	ksnprintf(params, DM_MAX_PARAMS_SIZE, "%s",
750*f603807bSTomohiro Kusumi 	    priv->status_str);
751*f603807bSTomohiro Kusumi 
752*f603807bSTomohiro Kusumi 	return params;
753*f603807bSTomohiro Kusumi }
754*f603807bSTomohiro Kusumi 
755*f603807bSTomohiro Kusumi static int
756*f603807bSTomohiro Kusumi dm_target_crypt_destroy(dm_table_entry_t *table_en)
757*f603807bSTomohiro Kusumi {
758*f603807bSTomohiro Kusumi 	dm_target_crypt_config_t *priv;
759*f603807bSTomohiro Kusumi 
760*f603807bSTomohiro Kusumi 	/*
761*f603807bSTomohiro Kusumi 	 * Disconnect the crypt config before unbusying the target.
762*f603807bSTomohiro Kusumi 	 */
763*f603807bSTomohiro Kusumi 	priv = table_en->target_config;
764*f603807bSTomohiro Kusumi 	if (priv == NULL)
765*f603807bSTomohiro Kusumi 		return 0;
766*f603807bSTomohiro Kusumi 	dm_pdev_decr(priv->pdev);
767*f603807bSTomohiro Kusumi 
768*f603807bSTomohiro Kusumi 	/*
769*f603807bSTomohiro Kusumi 	 * Clean up the crypt config
770*f603807bSTomohiro Kusumi 	 *
771*f603807bSTomohiro Kusumi 	 * Overwrite the private information before freeing memory to
772*f603807bSTomohiro Kusumi 	 * avoid leaking it.
773*f603807bSTomohiro Kusumi 	 */
774*f603807bSTomohiro Kusumi 	if (priv->status_str) {
775*f603807bSTomohiro Kusumi 		dmtc_crypto_clear(priv->status_str, strlen(priv->status_str));
776*f603807bSTomohiro Kusumi 		kfree(priv->status_str, M_DMCRYPT);
777*f603807bSTomohiro Kusumi 		crypto_freesession(priv->crypto_sid);
778*f603807bSTomohiro Kusumi 	}
779*f603807bSTomohiro Kusumi 
780*f603807bSTomohiro Kusumi 	if ((priv->ivgen) && (priv->ivgen->dtor != NULL)) {
781*f603807bSTomohiro Kusumi 		priv->ivgen->dtor(priv, priv->ivgen_priv);
782*f603807bSTomohiro Kusumi 	}
783*f603807bSTomohiro Kusumi 
784*f603807bSTomohiro Kusumi 	/* Destroy mpipes */
785*f603807bSTomohiro Kusumi 	dmtc_destroy_mpipe(priv);
786*f603807bSTomohiro Kusumi 
787*f603807bSTomohiro Kusumi 	dmtc_crypto_clear(priv, sizeof(dm_target_crypt_config_t));
788*f603807bSTomohiro Kusumi 	kfree(priv, M_DMCRYPT);
789*f603807bSTomohiro Kusumi 
790*f603807bSTomohiro Kusumi 	return 0;
791*f603807bSTomohiro Kusumi }
792*f603807bSTomohiro Kusumi 
793*f603807bSTomohiro Kusumi /************************************************************************
794*f603807bSTomohiro Kusumi  *			STRATEGY SUPPORT FUNCTIONS			*
795*f603807bSTomohiro Kusumi  ************************************************************************
796*f603807bSTomohiro Kusumi  *
797*f603807bSTomohiro Kusumi  * READ PATH:	doio -> bio_read_done -> crypto_work -> crypto_cb_read_done
798*f603807bSTomohiro Kusumi  * WRITE PATH:	crypto_work -> crypto_cb_write_done -> doio -> bio_write_done
799*f603807bSTomohiro Kusumi  */
800*f603807bSTomohiro Kusumi 
801*f603807bSTomohiro Kusumi /*
802*f603807bSTomohiro Kusumi  * Wrapper around crypto_dispatch() to match dispatch_t type
803*f603807bSTomohiro Kusumi  */
804*f603807bSTomohiro Kusumi static void
805*f603807bSTomohiro Kusumi dmtc_crypto_dispatch(void *arg)
806*f603807bSTomohiro Kusumi {
807*f603807bSTomohiro Kusumi 	struct cryptop *crp;
808*f603807bSTomohiro Kusumi 
809*f603807bSTomohiro Kusumi 	crp = (struct cryptop *)arg;
810*f603807bSTomohiro Kusumi 	KKASSERT(crp != NULL);
811*f603807bSTomohiro Kusumi 	KTR_LOG(dmcrypt_crypto_dispatch, crp);
812*f603807bSTomohiro Kusumi 	crypto_dispatch(crp);
813*f603807bSTomohiro Kusumi }
814*f603807bSTomohiro Kusumi 
815*f603807bSTomohiro Kusumi /*
816*f603807bSTomohiro Kusumi  * Start IO operation, called from dmstrategy routine.
817*f603807bSTomohiro Kusumi  */
818*f603807bSTomohiro Kusumi static int
819*f603807bSTomohiro Kusumi dm_target_crypt_strategy(dm_table_entry_t *table_en, struct buf *bp)
820*f603807bSTomohiro Kusumi {
821*f603807bSTomohiro Kusumi 	struct bio *bio;
822*f603807bSTomohiro Kusumi 
823*f603807bSTomohiro Kusumi 	dm_target_crypt_config_t *priv;
824*f603807bSTomohiro Kusumi 	priv = table_en->target_config;
825*f603807bSTomohiro Kusumi 
826*f603807bSTomohiro Kusumi 	/* Get rid of stuff we can't really handle */
827*f603807bSTomohiro Kusumi 	if ((bp->b_cmd == BUF_CMD_READ) || (bp->b_cmd == BUF_CMD_WRITE)) {
828*f603807bSTomohiro Kusumi 		if (((bp->b_bcount % DEV_BSIZE) != 0) || (bp->b_bcount == 0)) {
829*f603807bSTomohiro Kusumi 			kprintf("dm_target_crypt_strategy: can't really "
830*f603807bSTomohiro Kusumi 				"handle bp->b_bcount = %d\n",
831*f603807bSTomohiro Kusumi 				bp->b_bcount);
832*f603807bSTomohiro Kusumi 			bp->b_error = EINVAL;
833*f603807bSTomohiro Kusumi 			bp->b_flags |= B_ERROR | B_INVAL;
834*f603807bSTomohiro Kusumi 			biodone(&bp->b_bio1);
835*f603807bSTomohiro Kusumi 			return 0;
836*f603807bSTomohiro Kusumi 		}
837*f603807bSTomohiro Kusumi 	}
838*f603807bSTomohiro Kusumi 
839*f603807bSTomohiro Kusumi 	KTR_LOG(dmcrypt_crypt_strategy, bp->b_cmd, bp);
840*f603807bSTomohiro Kusumi 
841*f603807bSTomohiro Kusumi 	switch (bp->b_cmd) {
842*f603807bSTomohiro Kusumi 	case BUF_CMD_READ:
843*f603807bSTomohiro Kusumi 		bio = push_bio(&bp->b_bio1);
844*f603807bSTomohiro Kusumi 		bio->bio_offset = bp->b_bio1.bio_offset +
845*f603807bSTomohiro Kusumi 				  priv->block_offset * DEV_BSIZE;
846*f603807bSTomohiro Kusumi 		bio->bio_caller_info1.ptr = priv;
847*f603807bSTomohiro Kusumi 		bio->bio_done = dmtc_bio_read_done;
848*f603807bSTomohiro Kusumi 		vn_strategy(priv->pdev->pdev_vnode, bio);
849*f603807bSTomohiro Kusumi 		break;
850*f603807bSTomohiro Kusumi 	case BUF_CMD_WRITE:
851*f603807bSTomohiro Kusumi 		bio = push_bio(&bp->b_bio1);
852*f603807bSTomohiro Kusumi 		bio->bio_offset = bp->b_bio1.bio_offset +
853*f603807bSTomohiro Kusumi 				  priv->block_offset * DEV_BSIZE;
854*f603807bSTomohiro Kusumi 		bio->bio_caller_info1.ptr = priv;
855*f603807bSTomohiro Kusumi 		dmtc_crypto_write_start(priv, bio);
856*f603807bSTomohiro Kusumi 		break;
857*f603807bSTomohiro Kusumi 	default:
858*f603807bSTomohiro Kusumi 		vn_strategy(priv->pdev->pdev_vnode, &bp->b_bio1);
859*f603807bSTomohiro Kusumi 		break;
860*f603807bSTomohiro Kusumi 	}
861*f603807bSTomohiro Kusumi 	return 0;
862*f603807bSTomohiro Kusumi }
863*f603807bSTomohiro Kusumi 
864*f603807bSTomohiro Kusumi /*
865*f603807bSTomohiro Kusumi  * STRATEGY READ PATH PART 1/3 (after read BIO completes)
866*f603807bSTomohiro Kusumi  */
867*f603807bSTomohiro Kusumi static void
868*f603807bSTomohiro Kusumi dmtc_bio_read_done(struct bio *bio)
869*f603807bSTomohiro Kusumi {
870*f603807bSTomohiro Kusumi 	struct bio *obio;
871*f603807bSTomohiro Kusumi 
872*f603807bSTomohiro Kusumi 	dm_target_crypt_config_t *priv;
873*f603807bSTomohiro Kusumi 
874*f603807bSTomohiro Kusumi 	KTR_LOG(dmcrypt_bio_read_done, bio->bio_buf);
875*f603807bSTomohiro Kusumi 
876*f603807bSTomohiro Kusumi 	/*
877*f603807bSTomohiro Kusumi 	 * If a read error occurs we shortcut the operation, otherwise
878*f603807bSTomohiro Kusumi 	 * go on to stage 2.
879*f603807bSTomohiro Kusumi 	 */
880*f603807bSTomohiro Kusumi 	if (bio->bio_buf->b_flags & B_ERROR) {
881*f603807bSTomohiro Kusumi 		obio = pop_bio(bio);
882*f603807bSTomohiro Kusumi 		biodone(obio);
883*f603807bSTomohiro Kusumi 	} else {
884*f603807bSTomohiro Kusumi 		priv = bio->bio_caller_info1.ptr;
885*f603807bSTomohiro Kusumi 		dmtc_crypto_read_start(priv, bio);
886*f603807bSTomohiro Kusumi 	}
887*f603807bSTomohiro Kusumi }
888*f603807bSTomohiro Kusumi 
889*f603807bSTomohiro Kusumi /*
890*f603807bSTomohiro Kusumi  * STRATEGY READ PATH PART 2/3
891*f603807bSTomohiro Kusumi  */
892*f603807bSTomohiro Kusumi static void
893*f603807bSTomohiro Kusumi dmtc_crypto_read_retry(void *arg1, void *arg2)
894*f603807bSTomohiro Kusumi {
895*f603807bSTomohiro Kusumi 	dm_target_crypt_config_t *priv = arg1;
896*f603807bSTomohiro Kusumi 	struct bio *bio = arg2;
897*f603807bSTomohiro Kusumi 
898*f603807bSTomohiro Kusumi 	dmtc_crypto_read_start(priv, bio);
899*f603807bSTomohiro Kusumi }
900*f603807bSTomohiro Kusumi 
901*f603807bSTomohiro Kusumi static void
902*f603807bSTomohiro Kusumi dmtc_crypto_read_start(dm_target_crypt_config_t *priv, struct bio *bio)
903*f603807bSTomohiro Kusumi {
904*f603807bSTomohiro Kusumi 	struct dmtc_helper *dmtc;
905*f603807bSTomohiro Kusumi 	struct cryptodesc *crd;
906*f603807bSTomohiro Kusumi 	struct cryptop *crp;
907*f603807bSTomohiro Kusumi 	int i, bytes, sectors, sz;
908*f603807bSTomohiro Kusumi 	off_t isector;
909*f603807bSTomohiro Kusumi 	u_char *ptr, *space;
910*f603807bSTomohiro Kusumi 
911*f603807bSTomohiro Kusumi 	/*
912*f603807bSTomohiro Kusumi 	 * Note: b_resid no good after read I/O, it will be 0, use
913*f603807bSTomohiro Kusumi 	 *	 b_bcount.
914*f603807bSTomohiro Kusumi 	 */
915*f603807bSTomohiro Kusumi 	bytes = bio->bio_buf->b_bcount;
916*f603807bSTomohiro Kusumi 	isector = bio->bio_offset / DEV_BSIZE;	/* ivgen salt base? */
917*f603807bSTomohiro Kusumi 	sectors = bytes / DEV_BSIZE;		/* Number of sectors */
918*f603807bSTomohiro Kusumi 	sz = sectors * (sizeof(*crp) + sizeof(*crd));
919*f603807bSTomohiro Kusumi 
920*f603807bSTomohiro Kusumi 	/*
921*f603807bSTomohiro Kusumi 	 * For reads with bogus page we can't decrypt in place as stuff
922*f603807bSTomohiro Kusumi 	 * can get ripped out from under us.
923*f603807bSTomohiro Kusumi 	 *
924*f603807bSTomohiro Kusumi 	 * XXX actually it looks like we can, and in any case the initial
925*f603807bSTomohiro Kusumi 	 * read already completed and threw crypted data into the buffer
926*f603807bSTomohiro Kusumi 	 * cache buffer.  Disable for now.
927*f603807bSTomohiro Kusumi 	 */
928*f603807bSTomohiro Kusumi 	space = mpipe_alloc_callback(&priv->read_mpipe,
929*f603807bSTomohiro Kusumi 				     dmtc_crypto_read_retry, priv, bio);
930*f603807bSTomohiro Kusumi 	if (space == NULL)
931*f603807bSTomohiro Kusumi 		return;
932*f603807bSTomohiro Kusumi 
933*f603807bSTomohiro Kusumi 	dmtc = (struct dmtc_helper *)space;
934*f603807bSTomohiro Kusumi 	dmtc->free_addr = space;
935*f603807bSTomohiro Kusumi 	space += sizeof(struct dmtc_helper);
936*f603807bSTomohiro Kusumi 	dmtc->orig_buf = NULL;
937*f603807bSTomohiro Kusumi 	dmtc->data_buf = bio->bio_buf->b_data;
938*f603807bSTomohiro Kusumi 	dmtc->priv = priv;
939*f603807bSTomohiro Kusumi 	bio->bio_caller_info2.ptr = dmtc;
940*f603807bSTomohiro Kusumi 	bio->bio_buf->b_error = 0;
941*f603807bSTomohiro Kusumi 
942*f603807bSTomohiro Kusumi 	/*
943*f603807bSTomohiro Kusumi 	 * Load crypto descriptors (crp/crd loop)
944*f603807bSTomohiro Kusumi 	 */
945*f603807bSTomohiro Kusumi 	bzero(space, sz);
946*f603807bSTomohiro Kusumi 	ptr = space;
947*f603807bSTomohiro Kusumi 	bio->bio_caller_info3.value = sectors;
948*f603807bSTomohiro Kusumi 	cpu_sfence();
949*f603807bSTomohiro Kusumi #if 0
950*f603807bSTomohiro Kusumi 	kprintf("Read, bytes = %d (b_bcount), "
951*f603807bSTomohiro Kusumi 		"sectors = %d (bio = %p, b_cmd = %d)\n",
952*f603807bSTomohiro Kusumi 		bytes, sectors, bio, bio->bio_buf->b_cmd);
953*f603807bSTomohiro Kusumi #endif
954*f603807bSTomohiro Kusumi 	for (i = 0; i < sectors; i++) {
955*f603807bSTomohiro Kusumi 		crp = (struct cryptop *)ptr;
956*f603807bSTomohiro Kusumi 		ptr += sizeof(*crp);
957*f603807bSTomohiro Kusumi 		crd = (struct cryptodesc *)ptr;
958*f603807bSTomohiro Kusumi 		ptr += sizeof (*crd);
959*f603807bSTomohiro Kusumi 
960*f603807bSTomohiro Kusumi 		crp->crp_buf = dmtc->data_buf + i * DEV_BSIZE;
961*f603807bSTomohiro Kusumi 
962*f603807bSTomohiro Kusumi 		crp->crp_sid = priv->crypto_sid;
963*f603807bSTomohiro Kusumi 		crp->crp_ilen = crp->crp_olen = DEV_BSIZE;
964*f603807bSTomohiro Kusumi 
965*f603807bSTomohiro Kusumi 		crp->crp_opaque = (void *)bio;
966*f603807bSTomohiro Kusumi 
967*f603807bSTomohiro Kusumi 		crp->crp_callback = dmtc_crypto_cb_read_done;
968*f603807bSTomohiro Kusumi 		crp->crp_desc = crd;
969*f603807bSTomohiro Kusumi 		crp->crp_etype = 0;
970*f603807bSTomohiro Kusumi 		crp->crp_flags = CRYPTO_F_CBIFSYNC | CRYPTO_F_REL |
971*f603807bSTomohiro Kusumi 				 CRYPTO_F_BATCH;
972*f603807bSTomohiro Kusumi 
973*f603807bSTomohiro Kusumi 		crd->crd_alg = priv->crypto_alg;
974*f603807bSTomohiro Kusumi #if 0
975*f603807bSTomohiro Kusumi 		crd->crd_key = (caddr_t)priv->crypto_key;
976*f603807bSTomohiro Kusumi 		crd->crd_klen = priv->crypto_klen;
977*f603807bSTomohiro Kusumi #endif
978*f603807bSTomohiro Kusumi 
979*f603807bSTomohiro Kusumi 		crd->crd_skip = 0;
980*f603807bSTomohiro Kusumi 		crd->crd_len = DEV_BSIZE /* XXX */;
981*f603807bSTomohiro Kusumi 		crd->crd_flags = CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
982*f603807bSTomohiro Kusumi 		crd->crd_next = NULL;
983*f603807bSTomohiro Kusumi 
984*f603807bSTomohiro Kusumi 		crd->crd_flags &= ~CRD_F_ENCRYPT;
985*f603807bSTomohiro Kusumi 
986*f603807bSTomohiro Kusumi 		KTR_LOG(dmcrypt_crypto_read_start, crp, bio->bio_buf, i,
987*f603807bSTomohiro Kusumi 		    sectors);
988*f603807bSTomohiro Kusumi 
989*f603807bSTomohiro Kusumi 		/*
990*f603807bSTomohiro Kusumi 		 * Note: last argument is used to generate salt(?) and is
991*f603807bSTomohiro Kusumi 		 *	 a 64 bit value, but the original code passed an
992*f603807bSTomohiro Kusumi 		 *	 int.  Changing it now will break pre-existing
993*f603807bSTomohiro Kusumi 		 *	 crypt volumes.
994*f603807bSTomohiro Kusumi 		 */
995*f603807bSTomohiro Kusumi 		priv->ivgen->gen_iv(priv, crd->crd_iv, sizeof(crd->crd_iv),
996*f603807bSTomohiro Kusumi 				    isector + i, crp);
997*f603807bSTomohiro Kusumi 	}
998*f603807bSTomohiro Kusumi }
999*f603807bSTomohiro Kusumi 
1000*f603807bSTomohiro Kusumi /*
1001*f603807bSTomohiro Kusumi  * STRATEGY READ PATH PART 3/3
1002*f603807bSTomohiro Kusumi  */
1003*f603807bSTomohiro Kusumi static int
1004*f603807bSTomohiro Kusumi dmtc_crypto_cb_read_done(struct cryptop *crp)
1005*f603807bSTomohiro Kusumi {
1006*f603807bSTomohiro Kusumi 	struct dmtc_helper *dmtc;
1007*f603807bSTomohiro Kusumi 	struct bio *bio, *obio;
1008*f603807bSTomohiro Kusumi 	int n;
1009*f603807bSTomohiro Kusumi 
1010*f603807bSTomohiro Kusumi 	if (crp->crp_etype == EAGAIN)
1011*f603807bSTomohiro Kusumi 		return crypto_dispatch(crp);
1012*f603807bSTomohiro Kusumi 
1013*f603807bSTomohiro Kusumi 	bio = (struct bio *)crp->crp_opaque;
1014*f603807bSTomohiro Kusumi 	KKASSERT(bio != NULL);
1015*f603807bSTomohiro Kusumi 
1016*f603807bSTomohiro Kusumi 	/*
1017*f603807bSTomohiro Kusumi 	 * Cumulative error
1018*f603807bSTomohiro Kusumi 	 */
1019*f603807bSTomohiro Kusumi 	if (crp->crp_etype) {
1020*f603807bSTomohiro Kusumi 		kprintf("dm_target_crypt: dmtc_crypto_cb_read_done "
1021*f603807bSTomohiro Kusumi 			"crp_etype = %d\n",
1022*f603807bSTomohiro Kusumi 			crp->crp_etype);
1023*f603807bSTomohiro Kusumi 		bio->bio_buf->b_error = crp->crp_etype;
1024*f603807bSTomohiro Kusumi 	}
1025*f603807bSTomohiro Kusumi 
1026*f603807bSTomohiro Kusumi 	/*
1027*f603807bSTomohiro Kusumi 	 * On the last chunk of the decryption we do any required copybacks
1028*f603807bSTomohiro Kusumi 	 * and complete the I/O.
1029*f603807bSTomohiro Kusumi 	 */
1030*f603807bSTomohiro Kusumi 	n = atomic_fetchadd_int(&bio->bio_caller_info3.value, -1);
1031*f603807bSTomohiro Kusumi #if 0
1032*f603807bSTomohiro Kusumi 	kprintf("dmtc_crypto_cb_read_done %p, n = %d\n", bio, n);
1033*f603807bSTomohiro Kusumi #endif
1034*f603807bSTomohiro Kusumi 
1035*f603807bSTomohiro Kusumi 	KTR_LOG(dmcrypt_crypto_cb_read_done, crp, bio->bio_buf, n);
1036*f603807bSTomohiro Kusumi 
1037*f603807bSTomohiro Kusumi 	if (n == 1) {
1038*f603807bSTomohiro Kusumi 		/*
1039*f603807bSTomohiro Kusumi 		 * For the B_HASBOGUS case we didn't decrypt in place,
1040*f603807bSTomohiro Kusumi 		 * so we need to copy stuff back into the buf.
1041*f603807bSTomohiro Kusumi 		 *
1042*f603807bSTomohiro Kusumi 		 * (disabled for now).
1043*f603807bSTomohiro Kusumi 		 */
1044*f603807bSTomohiro Kusumi 		dmtc = bio->bio_caller_info2.ptr;
1045*f603807bSTomohiro Kusumi 		if (bio->bio_buf->b_error) {
1046*f603807bSTomohiro Kusumi 			bio->bio_buf->b_flags |= B_ERROR;
1047*f603807bSTomohiro Kusumi 		}
1048*f603807bSTomohiro Kusumi #if 0
1049*f603807bSTomohiro Kusumi 		else if (bio->bio_buf->b_flags & B_HASBOGUS) {
1050*f603807bSTomohiro Kusumi 			memcpy(bio->bio_buf->b_data, dmtc->data_buf,
1051*f603807bSTomohiro Kusumi 			       bio->bio_buf->b_bcount);
1052*f603807bSTomohiro Kusumi 		}
1053*f603807bSTomohiro Kusumi #endif
1054*f603807bSTomohiro Kusumi 		mpipe_free(&dmtc->priv->read_mpipe, dmtc->free_addr);
1055*f603807bSTomohiro Kusumi 		obio = pop_bio(bio);
1056*f603807bSTomohiro Kusumi 		biodone(obio);
1057*f603807bSTomohiro Kusumi 	}
1058*f603807bSTomohiro Kusumi 	return 0;
1059*f603807bSTomohiro Kusumi }
1060*f603807bSTomohiro Kusumi /* END OF STRATEGY READ SECTION */
1061*f603807bSTomohiro Kusumi 
1062*f603807bSTomohiro Kusumi /*
1063*f603807bSTomohiro Kusumi  * STRATEGY WRITE PATH PART 1/3
1064*f603807bSTomohiro Kusumi  */
1065*f603807bSTomohiro Kusumi 
1066*f603807bSTomohiro Kusumi static void
1067*f603807bSTomohiro Kusumi dmtc_crypto_write_retry(void *arg1, void *arg2)
1068*f603807bSTomohiro Kusumi {
1069*f603807bSTomohiro Kusumi 	dm_target_crypt_config_t *priv = arg1;
1070*f603807bSTomohiro Kusumi 	struct bio *bio = arg2;
1071*f603807bSTomohiro Kusumi 
1072*f603807bSTomohiro Kusumi 	KTR_LOG(dmcrypt_crypto_write_retry, bio->bio_buf);
1073*f603807bSTomohiro Kusumi 
1074*f603807bSTomohiro Kusumi 	dmtc_crypto_write_start(priv, bio);
1075*f603807bSTomohiro Kusumi }
1076*f603807bSTomohiro Kusumi 
1077*f603807bSTomohiro Kusumi static void
1078*f603807bSTomohiro Kusumi dmtc_crypto_write_start(dm_target_crypt_config_t *priv, struct bio *bio)
1079*f603807bSTomohiro Kusumi {
1080*f603807bSTomohiro Kusumi 	struct dmtc_helper *dmtc;
1081*f603807bSTomohiro Kusumi 	struct cryptodesc *crd;
1082*f603807bSTomohiro Kusumi 	struct cryptop *crp;
1083*f603807bSTomohiro Kusumi 	int i, bytes, sectors, sz;
1084*f603807bSTomohiro Kusumi 	off_t isector;
1085*f603807bSTomohiro Kusumi 	u_char *ptr, *space;
1086*f603807bSTomohiro Kusumi 
1087*f603807bSTomohiro Kusumi 	/*
1088*f603807bSTomohiro Kusumi 	 * Use b_bcount for consistency
1089*f603807bSTomohiro Kusumi 	 */
1090*f603807bSTomohiro Kusumi 	bytes = bio->bio_buf->b_bcount;
1091*f603807bSTomohiro Kusumi 
1092*f603807bSTomohiro Kusumi 	isector = bio->bio_offset / DEV_BSIZE;	/* ivgen salt base? */
1093*f603807bSTomohiro Kusumi 	sectors = bytes / DEV_BSIZE;		/* Number of sectors */
1094*f603807bSTomohiro Kusumi 	sz = sectors * (sizeof(*crp) + sizeof(*crd));
1095*f603807bSTomohiro Kusumi 
1096*f603807bSTomohiro Kusumi 	/*
1097*f603807bSTomohiro Kusumi 	 * For writes and reads with bogus page don't decrypt in place.
1098*f603807bSTomohiro Kusumi 	 */
1099*f603807bSTomohiro Kusumi 	space = mpipe_alloc_callback(&priv->write_mpipe,
1100*f603807bSTomohiro Kusumi 				     dmtc_crypto_write_retry, priv, bio);
1101*f603807bSTomohiro Kusumi 	if (space == NULL)
1102*f603807bSTomohiro Kusumi 		return;
1103*f603807bSTomohiro Kusumi 
1104*f603807bSTomohiro Kusumi 	dmtc = (struct dmtc_helper *)space;
1105*f603807bSTomohiro Kusumi 	dmtc->free_addr = space;
1106*f603807bSTomohiro Kusumi 	space += sizeof(struct dmtc_helper);
1107*f603807bSTomohiro Kusumi 	memcpy(space + sz, bio->bio_buf->b_data, bytes);
1108*f603807bSTomohiro Kusumi 
1109*f603807bSTomohiro Kusumi 	bio->bio_caller_info2.ptr = dmtc;
1110*f603807bSTomohiro Kusumi 	bio->bio_buf->b_error = 0;
1111*f603807bSTomohiro Kusumi 
1112*f603807bSTomohiro Kusumi 	dmtc->orig_buf = bio->bio_buf->b_data;
1113*f603807bSTomohiro Kusumi 	dmtc->data_buf = space + sz;
1114*f603807bSTomohiro Kusumi 	dmtc->priv = priv;
1115*f603807bSTomohiro Kusumi 
1116*f603807bSTomohiro Kusumi 	/*
1117*f603807bSTomohiro Kusumi 	 * Load crypto descriptors (crp/crd loop)
1118*f603807bSTomohiro Kusumi 	 */
1119*f603807bSTomohiro Kusumi 	bzero(space, sz);
1120*f603807bSTomohiro Kusumi 	ptr = space;
1121*f603807bSTomohiro Kusumi 	bio->bio_caller_info3.value = sectors;
1122*f603807bSTomohiro Kusumi 	cpu_sfence();
1123*f603807bSTomohiro Kusumi #if 0
1124*f603807bSTomohiro Kusumi 	kprintf("Write, bytes = %d (b_bcount), "
1125*f603807bSTomohiro Kusumi 		"sectors = %d (bio = %p, b_cmd = %d)\n",
1126*f603807bSTomohiro Kusumi 		bytes, sectors, bio, bio->bio_buf->b_cmd);
1127*f603807bSTomohiro Kusumi #endif
1128*f603807bSTomohiro Kusumi 	for (i = 0; i < sectors; i++) {
1129*f603807bSTomohiro Kusumi 		crp = (struct cryptop *)ptr;
1130*f603807bSTomohiro Kusumi 		ptr += sizeof(*crp);
1131*f603807bSTomohiro Kusumi 		crd = (struct cryptodesc *)ptr;
1132*f603807bSTomohiro Kusumi 		ptr += sizeof (*crd);
1133*f603807bSTomohiro Kusumi 
1134*f603807bSTomohiro Kusumi 		crp->crp_buf = dmtc->data_buf + i * DEV_BSIZE;
1135*f603807bSTomohiro Kusumi 
1136*f603807bSTomohiro Kusumi 		crp->crp_sid = priv->crypto_sid;
1137*f603807bSTomohiro Kusumi 		crp->crp_ilen = crp->crp_olen = DEV_BSIZE;
1138*f603807bSTomohiro Kusumi 
1139*f603807bSTomohiro Kusumi 		crp->crp_opaque = (void *)bio;
1140*f603807bSTomohiro Kusumi 
1141*f603807bSTomohiro Kusumi 		crp->crp_callback = dmtc_crypto_cb_write_done;
1142*f603807bSTomohiro Kusumi 		crp->crp_desc = crd;
1143*f603807bSTomohiro Kusumi 		crp->crp_etype = 0;
1144*f603807bSTomohiro Kusumi 		crp->crp_flags = CRYPTO_F_CBIFSYNC | CRYPTO_F_REL |
1145*f603807bSTomohiro Kusumi 				 CRYPTO_F_BATCH;
1146*f603807bSTomohiro Kusumi 
1147*f603807bSTomohiro Kusumi 		crd->crd_alg = priv->crypto_alg;
1148*f603807bSTomohiro Kusumi #if 0
1149*f603807bSTomohiro Kusumi 		crd->crd_key = (caddr_t)priv->crypto_key;
1150*f603807bSTomohiro Kusumi 		crd->crd_klen = priv->crypto_klen;
1151*f603807bSTomohiro Kusumi #endif
1152*f603807bSTomohiro Kusumi 
1153*f603807bSTomohiro Kusumi 		crd->crd_skip = 0;
1154*f603807bSTomohiro Kusumi 		crd->crd_len = DEV_BSIZE /* XXX */;
1155*f603807bSTomohiro Kusumi 		crd->crd_flags = CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
1156*f603807bSTomohiro Kusumi 		crd->crd_next = NULL;
1157*f603807bSTomohiro Kusumi 
1158*f603807bSTomohiro Kusumi 		crd->crd_flags |= CRD_F_ENCRYPT;
1159*f603807bSTomohiro Kusumi 
1160*f603807bSTomohiro Kusumi 		/*
1161*f603807bSTomohiro Kusumi 		 * Note: last argument is used to generate salt(?) and is
1162*f603807bSTomohiro Kusumi 		 *	 a 64 bit value, but the original code passed an
1163*f603807bSTomohiro Kusumi 		 *	 int.  Changing it now will break pre-existing
1164*f603807bSTomohiro Kusumi 		 *	 crypt volumes.
1165*f603807bSTomohiro Kusumi 		 */
1166*f603807bSTomohiro Kusumi 
1167*f603807bSTomohiro Kusumi 		KTR_LOG(dmcrypt_crypto_write_start, crp, bio->bio_buf,
1168*f603807bSTomohiro Kusumi 		    i, sectors);
1169*f603807bSTomohiro Kusumi 
1170*f603807bSTomohiro Kusumi 		priv->ivgen->gen_iv(priv, crd->crd_iv, sizeof(crd->crd_iv),
1171*f603807bSTomohiro Kusumi 				    isector + i, crp);
1172*f603807bSTomohiro Kusumi 	}
1173*f603807bSTomohiro Kusumi }
1174*f603807bSTomohiro Kusumi 
1175*f603807bSTomohiro Kusumi /*
1176*f603807bSTomohiro Kusumi  * STRATEGY WRITE PATH PART 2/3
1177*f603807bSTomohiro Kusumi  */
1178*f603807bSTomohiro Kusumi static int
1179*f603807bSTomohiro Kusumi dmtc_crypto_cb_write_done(struct cryptop *crp)
1180*f603807bSTomohiro Kusumi {
1181*f603807bSTomohiro Kusumi 	struct dmtc_helper *dmtc;
1182*f603807bSTomohiro Kusumi 	dm_target_crypt_config_t *priv;
1183*f603807bSTomohiro Kusumi 	struct bio *bio, *obio;
1184*f603807bSTomohiro Kusumi 	int n;
1185*f603807bSTomohiro Kusumi 
1186*f603807bSTomohiro Kusumi 	if (crp->crp_etype == EAGAIN)
1187*f603807bSTomohiro Kusumi 		return crypto_dispatch(crp);
1188*f603807bSTomohiro Kusumi 
1189*f603807bSTomohiro Kusumi 	bio = (struct bio *)crp->crp_opaque;
1190*f603807bSTomohiro Kusumi 	KKASSERT(bio != NULL);
1191*f603807bSTomohiro Kusumi 
1192*f603807bSTomohiro Kusumi 	/*
1193*f603807bSTomohiro Kusumi 	 * Cumulative error
1194*f603807bSTomohiro Kusumi 	 */
1195*f603807bSTomohiro Kusumi 	if (crp->crp_etype != 0) {
1196*f603807bSTomohiro Kusumi 		kprintf("dm_target_crypt: dmtc_crypto_cb_write_done "
1197*f603807bSTomohiro Kusumi 			"crp_etype = %d\n",
1198*f603807bSTomohiro Kusumi 		crp->crp_etype);
1199*f603807bSTomohiro Kusumi 		bio->bio_buf->b_error = crp->crp_etype;
1200*f603807bSTomohiro Kusumi 	}
1201*f603807bSTomohiro Kusumi 
1202*f603807bSTomohiro Kusumi 	/*
1203*f603807bSTomohiro Kusumi 	 * On the last chunk of the encryption we issue the write
1204*f603807bSTomohiro Kusumi 	 */
1205*f603807bSTomohiro Kusumi 	n = atomic_fetchadd_int(&bio->bio_caller_info3.value, -1);
1206*f603807bSTomohiro Kusumi #if 0
1207*f603807bSTomohiro Kusumi 	kprintf("dmtc_crypto_cb_write_done %p, n = %d\n", bio, n);
1208*f603807bSTomohiro Kusumi #endif
1209*f603807bSTomohiro Kusumi 
1210*f603807bSTomohiro Kusumi 	KTR_LOG(dmcrypt_crypto_cb_write_done, crp, bio->bio_buf, n);
1211*f603807bSTomohiro Kusumi 
1212*f603807bSTomohiro Kusumi 	if (n == 1) {
1213*f603807bSTomohiro Kusumi 		dmtc = bio->bio_caller_info2.ptr;
1214*f603807bSTomohiro Kusumi 		priv = (dm_target_crypt_config_t *)bio->bio_caller_info1.ptr;
1215*f603807bSTomohiro Kusumi 
1216*f603807bSTomohiro Kusumi 		if (bio->bio_buf->b_error) {
1217*f603807bSTomohiro Kusumi 			bio->bio_buf->b_flags |= B_ERROR;
1218*f603807bSTomohiro Kusumi 			mpipe_free(&dmtc->priv->write_mpipe, dmtc->free_addr);
1219*f603807bSTomohiro Kusumi 			obio = pop_bio(bio);
1220*f603807bSTomohiro Kusumi 			biodone(obio);
1221*f603807bSTomohiro Kusumi 		} else {
1222*f603807bSTomohiro Kusumi 			dmtc->orig_buf = bio->bio_buf->b_data;
1223*f603807bSTomohiro Kusumi 			bio->bio_buf->b_data = dmtc->data_buf;
1224*f603807bSTomohiro Kusumi 			bio->bio_done = dmtc_bio_write_done;
1225*f603807bSTomohiro Kusumi 			vn_strategy(priv->pdev->pdev_vnode, bio);
1226*f603807bSTomohiro Kusumi 		}
1227*f603807bSTomohiro Kusumi 	}
1228*f603807bSTomohiro Kusumi 	return 0;
1229*f603807bSTomohiro Kusumi }
1230*f603807bSTomohiro Kusumi 
1231*f603807bSTomohiro Kusumi /*
1232*f603807bSTomohiro Kusumi  * STRATEGY WRITE PATH PART 3/3
1233*f603807bSTomohiro Kusumi  */
1234*f603807bSTomohiro Kusumi static void
1235*f603807bSTomohiro Kusumi dmtc_bio_write_done(struct bio *bio)
1236*f603807bSTomohiro Kusumi {
1237*f603807bSTomohiro Kusumi 	struct dmtc_helper *dmtc;
1238*f603807bSTomohiro Kusumi 	struct bio *obio;
1239*f603807bSTomohiro Kusumi 
1240*f603807bSTomohiro Kusumi 	dmtc = bio->bio_caller_info2.ptr;
1241*f603807bSTomohiro Kusumi 	bio->bio_buf->b_data = dmtc->orig_buf;
1242*f603807bSTomohiro Kusumi 	mpipe_free(&dmtc->priv->write_mpipe, dmtc->free_addr);
1243*f603807bSTomohiro Kusumi 
1244*f603807bSTomohiro Kusumi 	KTR_LOG(dmcrypt_bio_write_done, bio->bio_buf);
1245*f603807bSTomohiro Kusumi 
1246*f603807bSTomohiro Kusumi 	obio = pop_bio(bio);
1247*f603807bSTomohiro Kusumi 	biodone(obio);
1248*f603807bSTomohiro Kusumi }
1249*f603807bSTomohiro Kusumi /* END OF STRATEGY WRITE SECTION */
1250*f603807bSTomohiro Kusumi 
1251*f603807bSTomohiro Kusumi 
1252*f603807bSTomohiro Kusumi 
1253*f603807bSTomohiro Kusumi /* DUMPING MAGIC */
1254*f603807bSTomohiro Kusumi 
1255*f603807bSTomohiro Kusumi extern int tsleep_crypto_dump;
1256*f603807bSTomohiro Kusumi 
1257*f603807bSTomohiro Kusumi static int
1258*f603807bSTomohiro Kusumi dm_target_crypt_dump(dm_table_entry_t *table_en, void *data, size_t length, off_t offset)
1259*f603807bSTomohiro Kusumi {
1260*f603807bSTomohiro Kusumi 	static struct dmtc_dump_helper dump_helper;
1261*f603807bSTomohiro Kusumi 	dm_target_crypt_config_t *priv;
1262*f603807bSTomohiro Kusumi 	int id;
1263*f603807bSTomohiro Kusumi 	static int first_call = 1;
1264*f603807bSTomohiro Kusumi 
1265*f603807bSTomohiro Kusumi 	priv = table_en->target_config;
1266*f603807bSTomohiro Kusumi 
1267*f603807bSTomohiro Kusumi 	if (first_call) {
1268*f603807bSTomohiro Kusumi 		first_call = 0;
1269*f603807bSTomohiro Kusumi 		dump_reactivate_cpus();
1270*f603807bSTomohiro Kusumi 	}
1271*f603807bSTomohiro Kusumi 
1272*f603807bSTomohiro Kusumi 	/* Magically enable tsleep */
1273*f603807bSTomohiro Kusumi 	tsleep_crypto_dump = 1;
1274*f603807bSTomohiro Kusumi 	id = 0;
1275*f603807bSTomohiro Kusumi 
1276*f603807bSTomohiro Kusumi 	/*
1277*f603807bSTomohiro Kusumi 	 * 0 length means flush buffers and return
1278*f603807bSTomohiro Kusumi 	 */
1279*f603807bSTomohiro Kusumi 	if (length == 0) {
1280*f603807bSTomohiro Kusumi 		if (priv->pdev->pdev_vnode->v_rdev == NULL) {
1281*f603807bSTomohiro Kusumi 			tsleep_crypto_dump = 0;
1282*f603807bSTomohiro Kusumi 			return ENXIO;
1283*f603807bSTomohiro Kusumi 		}
1284*f603807bSTomohiro Kusumi 		dev_ddump(priv->pdev->pdev_vnode->v_rdev,
1285*f603807bSTomohiro Kusumi 		    data, 0, offset, 0);
1286*f603807bSTomohiro Kusumi 		tsleep_crypto_dump = 0;
1287*f603807bSTomohiro Kusumi 		return 0;
1288*f603807bSTomohiro Kusumi 	}
1289*f603807bSTomohiro Kusumi 
1290*f603807bSTomohiro Kusumi 	bzero(&dump_helper, sizeof(dump_helper));
1291*f603807bSTomohiro Kusumi 	dump_helper.priv = priv;
1292*f603807bSTomohiro Kusumi 	dump_helper.data = data;
1293*f603807bSTomohiro Kusumi 	dump_helper.length = length;
1294*f603807bSTomohiro Kusumi 	dump_helper.offset = offset +
1295*f603807bSTomohiro Kusumi 	    priv->block_offset * DEV_BSIZE;
1296*f603807bSTomohiro Kusumi 	dump_helper.ident = &id;
1297*f603807bSTomohiro Kusumi 	dmtc_crypto_dump_start(priv, &dump_helper);
1298*f603807bSTomohiro Kusumi 
1299*f603807bSTomohiro Kusumi 	/*
1300*f603807bSTomohiro Kusumi 	 * Hackery to make stuff appear synchronous. The crypto callback will
1301*f603807bSTomohiro Kusumi 	 * set id to 1 and call wakeup on it. If the request completed
1302*f603807bSTomohiro Kusumi 	 * synchronously, id will be 1 and we won't bother to sleep. If not,
1303*f603807bSTomohiro Kusumi 	 * the crypto request will complete asynchronously and we sleep until
1304*f603807bSTomohiro Kusumi 	 * it's done.
1305*f603807bSTomohiro Kusumi 	 */
1306*f603807bSTomohiro Kusumi 	if (id == 0)
1307*f603807bSTomohiro Kusumi 		tsleep(&dump_helper, 0, "cryptdump", 0);
1308*f603807bSTomohiro Kusumi 
1309*f603807bSTomohiro Kusumi 	dump_helper.offset = dm_pdev_correct_dump_offset(priv->pdev,
1310*f603807bSTomohiro Kusumi 	    dump_helper.offset);
1311*f603807bSTomohiro Kusumi 
1312*f603807bSTomohiro Kusumi 	dev_ddump(priv->pdev->pdev_vnode->v_rdev,
1313*f603807bSTomohiro Kusumi 	    dump_helper.space, 0, dump_helper.offset,
1314*f603807bSTomohiro Kusumi 	    dump_helper.length);
1315*f603807bSTomohiro Kusumi 
1316*f603807bSTomohiro Kusumi 	tsleep_crypto_dump = 0;
1317*f603807bSTomohiro Kusumi 	return 0;
1318*f603807bSTomohiro Kusumi }
1319*f603807bSTomohiro Kusumi 
1320*f603807bSTomohiro Kusumi static void
1321*f603807bSTomohiro Kusumi dmtc_crypto_dump_start(dm_target_crypt_config_t *priv, struct dmtc_dump_helper *dump_helper)
1322*f603807bSTomohiro Kusumi {
1323*f603807bSTomohiro Kusumi 	struct cryptodesc *crd;
1324*f603807bSTomohiro Kusumi 	struct cryptop *crp;
1325*f603807bSTomohiro Kusumi 	int i, bytes, sectors;
1326*f603807bSTomohiro Kusumi 	off_t isector;
1327*f603807bSTomohiro Kusumi 
1328*f603807bSTomohiro Kusumi 	bytes = dump_helper->length;
1329*f603807bSTomohiro Kusumi 
1330*f603807bSTomohiro Kusumi 	isector = dump_helper->offset / DEV_BSIZE;	/* ivgen salt base? */
1331*f603807bSTomohiro Kusumi 	sectors = bytes / DEV_BSIZE;		/* Number of sectors */
1332*f603807bSTomohiro Kusumi 	dump_helper->sectors = sectors;
1333*f603807bSTomohiro Kusumi #if 0
1334*f603807bSTomohiro Kusumi 	kprintf("Dump, bytes = %d, "
1335*f603807bSTomohiro Kusumi 		"sectors = %d, LENGTH=%zu\n", bytes, sectors, dump_helper->length);
1336*f603807bSTomohiro Kusumi #endif
1337*f603807bSTomohiro Kusumi 	KKASSERT(dump_helper->length <= 65536);
1338*f603807bSTomohiro Kusumi 
1339*f603807bSTomohiro Kusumi 	memcpy(dump_helper->space, dump_helper->data, bytes);
1340*f603807bSTomohiro Kusumi 
1341*f603807bSTomohiro Kusumi 	cpu_sfence();
1342*f603807bSTomohiro Kusumi 
1343*f603807bSTomohiro Kusumi 	for (i = 0; i < sectors; i++) {
1344*f603807bSTomohiro Kusumi 		crp = &dump_helper->crp[i];
1345*f603807bSTomohiro Kusumi 		crd = &dump_helper->crd[i];
1346*f603807bSTomohiro Kusumi 
1347*f603807bSTomohiro Kusumi 		crp->crp_buf = dump_helper->space + i * DEV_BSIZE;
1348*f603807bSTomohiro Kusumi 
1349*f603807bSTomohiro Kusumi 		crp->crp_sid = priv->crypto_sid;
1350*f603807bSTomohiro Kusumi 		crp->crp_ilen = crp->crp_olen = DEV_BSIZE;
1351*f603807bSTomohiro Kusumi 
1352*f603807bSTomohiro Kusumi 		crp->crp_opaque = (void *)dump_helper;
1353*f603807bSTomohiro Kusumi 
1354*f603807bSTomohiro Kusumi 		crp->crp_callback = dmtc_crypto_cb_dump_done;
1355*f603807bSTomohiro Kusumi 		crp->crp_desc = crd;
1356*f603807bSTomohiro Kusumi 		crp->crp_etype = 0;
1357*f603807bSTomohiro Kusumi 		crp->crp_flags = CRYPTO_F_CBIFSYNC | CRYPTO_F_REL |
1358*f603807bSTomohiro Kusumi 				 CRYPTO_F_BATCH;
1359*f603807bSTomohiro Kusumi 
1360*f603807bSTomohiro Kusumi 		crd->crd_alg = priv->crypto_alg;
1361*f603807bSTomohiro Kusumi 
1362*f603807bSTomohiro Kusumi 		crd->crd_skip = 0;
1363*f603807bSTomohiro Kusumi 		crd->crd_len = DEV_BSIZE /* XXX */;
1364*f603807bSTomohiro Kusumi 		crd->crd_flags = CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
1365*f603807bSTomohiro Kusumi 		crd->crd_next = NULL;
1366*f603807bSTomohiro Kusumi 
1367*f603807bSTomohiro Kusumi 		crd->crd_flags |= CRD_F_ENCRYPT;
1368*f603807bSTomohiro Kusumi 
1369*f603807bSTomohiro Kusumi 		/*
1370*f603807bSTomohiro Kusumi 		 * Note: last argument is used to generate salt(?) and is
1371*f603807bSTomohiro Kusumi 		 *	 a 64 bit value, but the original code passed an
1372*f603807bSTomohiro Kusumi 		 *	 int.  Changing it now will break pre-existing
1373*f603807bSTomohiro Kusumi 		 *	 crypt volumes.
1374*f603807bSTomohiro Kusumi 		 */
1375*f603807bSTomohiro Kusumi 		priv->ivgen->gen_iv(priv, crd->crd_iv, sizeof(crd->crd_iv),
1376*f603807bSTomohiro Kusumi 				    isector + i, crp);
1377*f603807bSTomohiro Kusumi 	}
1378*f603807bSTomohiro Kusumi }
1379*f603807bSTomohiro Kusumi 
1380*f603807bSTomohiro Kusumi static int
1381*f603807bSTomohiro Kusumi dmtc_crypto_cb_dump_done(struct cryptop *crp)
1382*f603807bSTomohiro Kusumi {
1383*f603807bSTomohiro Kusumi 	struct dmtc_dump_helper *dump_helper;
1384*f603807bSTomohiro Kusumi 	int n;
1385*f603807bSTomohiro Kusumi 
1386*f603807bSTomohiro Kusumi 	if (crp->crp_etype == EAGAIN)
1387*f603807bSTomohiro Kusumi 		return crypto_dispatch(crp);
1388*f603807bSTomohiro Kusumi 
1389*f603807bSTomohiro Kusumi 	dump_helper = (struct dmtc_dump_helper *)crp->crp_opaque;
1390*f603807bSTomohiro Kusumi 	KKASSERT(dump_helper != NULL);
1391*f603807bSTomohiro Kusumi 
1392*f603807bSTomohiro Kusumi 	if (crp->crp_etype != 0) {
1393*f603807bSTomohiro Kusumi 		kprintf("dm_target_crypt: dmtc_crypto_cb_dump_done "
1394*f603807bSTomohiro Kusumi 			"crp_etype = %d\n",
1395*f603807bSTomohiro Kusumi 		crp->crp_etype);
1396*f603807bSTomohiro Kusumi 		return crp->crp_etype;
1397*f603807bSTomohiro Kusumi 	}
1398*f603807bSTomohiro Kusumi 
1399*f603807bSTomohiro Kusumi 	/*
1400*f603807bSTomohiro Kusumi 	 * On the last chunk of the encryption we return control
1401*f603807bSTomohiro Kusumi 	 */
1402*f603807bSTomohiro Kusumi 	n = atomic_fetchadd_int(&dump_helper->sectors, -1);
1403*f603807bSTomohiro Kusumi 
1404*f603807bSTomohiro Kusumi 	if (n == 1) {
1405*f603807bSTomohiro Kusumi 		atomic_add_int(dump_helper->ident, 1);
1406*f603807bSTomohiro Kusumi 		wakeup(dump_helper);
1407*f603807bSTomohiro Kusumi 	}
1408*f603807bSTomohiro Kusumi 
1409*f603807bSTomohiro Kusumi 	return 0;
1410*f603807bSTomohiro Kusumi }
1411*f603807bSTomohiro Kusumi 
1412*f603807bSTomohiro Kusumi static int
1413*f603807bSTomohiro Kusumi dmtc_mod_handler(module_t mod, int type, void *unused)
1414*f603807bSTomohiro Kusumi {
1415*f603807bSTomohiro Kusumi 	dm_target_t *dmt = NULL;
1416*f603807bSTomohiro Kusumi 	int err = 0;
1417*f603807bSTomohiro Kusumi 
1418*f603807bSTomohiro Kusumi 	switch (type) {
1419*f603807bSTomohiro Kusumi 	case MOD_LOAD:
1420*f603807bSTomohiro Kusumi 		if ((dmt = dm_target_lookup("crypt")) != NULL) {
1421*f603807bSTomohiro Kusumi 			dm_target_unbusy(dmt);
1422*f603807bSTomohiro Kusumi 			return EEXIST;
1423*f603807bSTomohiro Kusumi 		}
1424*f603807bSTomohiro Kusumi 		dmt = dm_target_alloc("crypt");
1425*f603807bSTomohiro Kusumi 		dmt->version[0] = 1;
1426*f603807bSTomohiro Kusumi 		dmt->version[1] = 6;
1427*f603807bSTomohiro Kusumi 		dmt->version[2] = 0;
1428*f603807bSTomohiro Kusumi 		dmt->init = &dm_target_crypt_init;
1429*f603807bSTomohiro Kusumi 		dmt->destroy = &dm_target_crypt_destroy;
1430*f603807bSTomohiro Kusumi 		dmt->strategy = &dm_target_crypt_strategy;
1431*f603807bSTomohiro Kusumi 		dmt->table = &dm_target_crypt_table;
1432*f603807bSTomohiro Kusumi 		dmt->dump = &dm_target_crypt_dump;
1433*f603807bSTomohiro Kusumi 
1434*f603807bSTomohiro Kusumi 		err = dm_target_insert(dmt);
1435*f603807bSTomohiro Kusumi 		if (!err)
1436*f603807bSTomohiro Kusumi 			kprintf("dm_target_crypt: Successfully initialized\n");
1437*f603807bSTomohiro Kusumi 		break;
1438*f603807bSTomohiro Kusumi 
1439*f603807bSTomohiro Kusumi 	case MOD_UNLOAD:
1440*f603807bSTomohiro Kusumi 		err = dm_target_remove("crypt");
1441*f603807bSTomohiro Kusumi 		if (err == 0) {
1442*f603807bSTomohiro Kusumi 			kprintf("dm_target_crypt: unloaded\n");
1443*f603807bSTomohiro Kusumi 		}
1444*f603807bSTomohiro Kusumi 		break;
1445*f603807bSTomohiro Kusumi 	}
1446*f603807bSTomohiro Kusumi 
1447*f603807bSTomohiro Kusumi 	return err;
1448*f603807bSTomohiro Kusumi }
1449*f603807bSTomohiro Kusumi 
1450*f603807bSTomohiro Kusumi DM_TARGET_MODULE(dm_target_crypt, dmtc_mod_handler);
1451