Blame view

drivers/md/dm-crypt.c 33.3 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
  /*
   * Copyright (C) 2003 Christophe Saout <christophe@saout.de>
   * Copyright (C) 2004 Clemens Fruhwirth <clemens@endorphin.org>
542da3176   Milan Broz   dm crypt: make wi...
4
   * Copyright (C) 2006-2009 Red Hat, Inc. All rights reserved.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
6
7
   *
   * This file is released under the GPL.
   */
43d690348   Milan Broz   dm crypt: add com...
8
  #include <linux/completion.h>
d1806f6a9   Herbert Xu   [BLOCK] dm-crypt:...
9
  #include <linux/err.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
11
12
13
14
15
16
17
18
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/kernel.h>
  #include <linux/bio.h>
  #include <linux/blkdev.h>
  #include <linux/mempool.h>
  #include <linux/slab.h>
  #include <linux/crypto.h>
  #include <linux/workqueue.h>
3fcfab16c   Andrew Morton   [PATCH] separate ...
19
  #include <linux/backing-dev.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
  #include <asm/atomic.h>
378f058cc   David Hardeman   [PATCH] Use sg_se...
21
  #include <linux/scatterlist.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
  #include <asm/page.h>
48527fa7c   Rik Snel   [BLOCK] dm-crypt:...
23
  #include <asm/unaligned.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24

586e80e6e   Mikulas Patocka   dm: remove dm hea...
25
  #include <linux/device-mapper.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26

72d948616   Alasdair G Kergon   [PATCH] dm: impro...
27
  #define DM_MSG_PREFIX "crypt"
e48d4bbf9   Milan Broz   [PATCH] dm crypt:...
28
  #define MESG_STR(x) x, sizeof(x)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
30
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
32
33
   * context holding the current state of a multi-part conversion
   */
  struct convert_context {
43d690348   Milan Broz   dm crypt: add com...
34
  	struct completion restart;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
36
37
38
39
40
41
  	struct bio *bio_in;
  	struct bio *bio_out;
  	unsigned int offset_in;
  	unsigned int offset_out;
  	unsigned int idx_in;
  	unsigned int idx_out;
  	sector_t sector;
43d690348   Milan Broz   dm crypt: add com...
42
  	atomic_t pending;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43
  };
53017030e   Milan Broz   dm crypt: move co...
44
45
46
47
48
49
50
51
52
53
54
55
  /*
   * per bio private data
   */
  struct dm_crypt_io {
  	struct dm_target *target;
  	struct bio *base_bio;
  	struct work_struct work;
  
  	struct convert_context ctx;
  
  	atomic_t pending;
  	int error;
0c395b0f8   Milan Broz   dm crypt: store s...
56
  	sector_t sector;
393b47ef2   Milan Broz   dm crypt: fix asy...
57
  	struct dm_crypt_io *base_io;
53017030e   Milan Broz   dm crypt: move co...
58
  };
01482b767   Milan Broz   dm crypt: extract...
59
  struct dm_crypt_request {
b2174eebd   Huang Ying   dm crypt: fix kcr...
60
  	struct convert_context *ctx;
01482b767   Milan Broz   dm crypt: extract...
61
62
63
  	struct scatterlist sg_in;
  	struct scatterlist sg_out;
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
65
66
67
  struct crypt_config;
  
  struct crypt_iv_operations {
  	int (*ctr)(struct crypt_config *cc, struct dm_target *ti,
d469f8419   Milan Broz   dm crypt: tidy wh...
68
  		   const char *opts);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
  	void (*dtr)(struct crypt_config *cc);
b95bf2d3d   Milan Broz   dm crypt: separat...
70
  	int (*init)(struct crypt_config *cc);
542da3176   Milan Broz   dm crypt: make wi...
71
  	int (*wipe)(struct crypt_config *cc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
73
  	int (*generator)(struct crypt_config *cc, u8 *iv, sector_t sector);
  };
604735927   Milan Broz   dm crypt: move pr...
74
75
  struct iv_essiv_private {
  	struct crypto_cipher *tfm;
b95bf2d3d   Milan Broz   dm crypt: separat...
76
77
  	struct crypto_hash *hash_tfm;
  	u8 *salt;
604735927   Milan Broz   dm crypt: move pr...
78
79
80
81
82
  };
  
  struct iv_benbi_private {
  	int shift;
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
83
84
85
86
  /*
   * Crypt: maps a linear range of a block device
   * and encrypts / decrypts at the same time.
   */
e48d4bbf9   Milan Broz   [PATCH] dm crypt:...
87
  enum flags { DM_CRYPT_SUSPENDED, DM_CRYPT_KEY_VALID };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
88
89
90
91
92
  struct crypt_config {
  	struct dm_dev *dev;
  	sector_t start;
  
  	/*
ddd42edfd   Milan Broz   dm crypt: add asy...
93
94
  	 * pool for per bio private data, crypto requests and
  	 * encryption requeusts/buffer pages
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
96
  	 */
  	mempool_t *io_pool;
ddd42edfd   Milan Broz   dm crypt: add asy...
97
  	mempool_t *req_pool;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
  	mempool_t *page_pool;
6a24c7184   Milan Broz   [PATCH] dm crypt:...
99
  	struct bio_set *bs;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100

cabf08e4d   Milan Broz   dm crypt: add pos...
101
102
  	struct workqueue_struct *io_queue;
  	struct workqueue_struct *crypt_queue;
3f1e9070f   Milan Broz   dm crypt: fix ctx...
103

5ebaee6d2   Milan Broz   dm crypt: simplif...
104
105
  	char *cipher;
  	char *cipher_mode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
106
  	struct crypt_iv_operations *iv_gen_ops;
79066ad32   Herbert Xu   [CRYPTO] dm-crypt...
107
  	union {
604735927   Milan Broz   dm crypt: move pr...
108
109
  		struct iv_essiv_private essiv;
  		struct iv_benbi_private benbi;
79066ad32   Herbert Xu   [CRYPTO] dm-crypt...
110
  	} iv_gen_private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
112
  	sector_t iv_offset;
  	unsigned int iv_size;
ddd42edfd   Milan Broz   dm crypt: add asy...
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
  	/*
  	 * Layout of each crypto request:
  	 *
  	 *   struct ablkcipher_request
  	 *      context
  	 *      padding
  	 *   struct dm_crypt_request
  	 *      padding
  	 *   IV
  	 *
  	 * The padding is added so that dm_crypt_request and the IV are
  	 * correctly aligned.
  	 */
  	unsigned int dmreq_start;
  	struct ablkcipher_request *req;
3a7f6c990   Milan Broz   dm crypt: use asy...
128
  	struct crypto_ablkcipher *tfm;
e48d4bbf9   Milan Broz   [PATCH] dm crypt:...
129
  	unsigned long flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
130
131
132
  	unsigned int key_size;
  	u8 key[0];
  };
6a24c7184   Milan Broz   [PATCH] dm crypt:...
133
  #define MIN_IOS        16
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
135
  #define MIN_POOL_PAGES 32
  #define MIN_BIO_PAGES  8
e18b890bb   Christoph Lameter   [PATCH] slab: rem...
136
  static struct kmem_cache *_crypt_io_pool;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137

028867ac2   Alasdair G Kergon   dm: use kmem_cach...
138
  static void clone_init(struct dm_crypt_io *, struct bio *);
395b167ca   Alasdair G Kergon   dm crypt: move qu...
139
  static void kcryptd_queue_crypt(struct dm_crypt_io *io);
027581f35   Olaf Kirch   dm crypt: fix cal...
140

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
142
143
   * Different IV generation algorithms:
   *
3c164bd81   Rik Snel   [BLOCK] dm-crypt:...
144
   * plain: the initial vector is the 32-bit little-endian version of the sector
3a4fa0a25   Robert P. J. Day   Fix misspellings ...
145
   *        number, padded with zeros if necessary.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146
   *
61afef614   Milan Broz   dm crypt: add pla...
147
148
149
   * plain64: the initial vector is the 64-bit little-endian version of the sector
   *        number, padded with zeros if necessary.
   *
3c164bd81   Rik Snel   [BLOCK] dm-crypt:...
150
151
152
   * essiv: "encrypted sector|salt initial vector", the sector number is
   *        encrypted with the bulk cipher using a salt as key. The salt
   *        should be derived from the bulk cipher's key via hashing.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153
   *
48527fa7c   Rik Snel   [BLOCK] dm-crypt:...
154
155
156
   * benbi: the 64-bit "big-endian 'narrow block'-count", starting at 1
   *        (needed for LRW-32-AES and possible other narrow block modes)
   *
46b477306   Ludwig Nussel   dm crypt: add nul...
157
158
159
   * null: the initial vector is always zero.  Provides compatibility with
   *       obsolete loop_fish2 devices.  Do not use for new devices.
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
160
161
162
163
164
165
166
167
168
169
170
   * plumb: unimplemented, see:
   * http://article.gmane.org/gmane.linux.kernel.device-mapper.dm-crypt/454
   */
  
  static int crypt_iv_plain_gen(struct crypt_config *cc, u8 *iv, sector_t sector)
  {
  	memset(iv, 0, cc->iv_size);
  	*(u32 *)iv = cpu_to_le32(sector & 0xffffffff);
  
  	return 0;
  }
61afef614   Milan Broz   dm crypt: add pla...
171
172
173
174
175
176
177
178
  static int crypt_iv_plain64_gen(struct crypt_config *cc, u8 *iv,
  				sector_t sector)
  {
  	memset(iv, 0, cc->iv_size);
  	*(u64 *)iv = cpu_to_le64(sector);
  
  	return 0;
  }
b95bf2d3d   Milan Broz   dm crypt: separat...
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
  /* Initialise ESSIV - compute salt but no local memory allocations */
  static int crypt_iv_essiv_init(struct crypt_config *cc)
  {
  	struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv;
  	struct hash_desc desc;
  	struct scatterlist sg;
  	int err;
  
  	sg_init_one(&sg, cc->key, cc->key_size);
  	desc.tfm = essiv->hash_tfm;
  	desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
  
  	err = crypto_hash_digest(&desc, &sg, cc->key_size, essiv->salt);
  	if (err)
  		return err;
  
  	return crypto_cipher_setkey(essiv->tfm, essiv->salt,
  				    crypto_hash_digestsize(essiv->hash_tfm));
  }
542da3176   Milan Broz   dm crypt: make wi...
198
199
200
201
202
203
204
205
206
207
  /* Wipe salt and reset key derived from volume key */
  static int crypt_iv_essiv_wipe(struct crypt_config *cc)
  {
  	struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv;
  	unsigned salt_size = crypto_hash_digestsize(essiv->hash_tfm);
  
  	memset(essiv->salt, 0, salt_size);
  
  	return crypto_cipher_setkey(essiv->tfm, essiv->salt, salt_size);
  }
604735927   Milan Broz   dm crypt: move pr...
208
209
210
211
212
213
  static void crypt_iv_essiv_dtr(struct crypt_config *cc)
  {
  	struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv;
  
  	crypto_free_cipher(essiv->tfm);
  	essiv->tfm = NULL;
b95bf2d3d   Milan Broz   dm crypt: separat...
214
215
216
217
218
219
  
  	crypto_free_hash(essiv->hash_tfm);
  	essiv->hash_tfm = NULL;
  
  	kzfree(essiv->salt);
  	essiv->salt = NULL;
604735927   Milan Broz   dm crypt: move pr...
220
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221
  static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti,
d469f8419   Milan Broz   dm crypt: tidy wh...
222
  			      const char *opts)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
223
  {
5861f1be0   Milan Broz   dm crypt: restruc...
224
225
  	struct crypto_cipher *essiv_tfm = NULL;
  	struct crypto_hash *hash_tfm = NULL;
5861f1be0   Milan Broz   dm crypt: restruc...
226
  	u8 *salt = NULL;
d1806f6a9   Herbert Xu   [BLOCK] dm-crypt:...
227
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
228

5861f1be0   Milan Broz   dm crypt: restruc...
229
  	if (!opts) {
72d948616   Alasdair G Kergon   [PATCH] dm: impro...
230
  		ti->error = "Digest algorithm missing for ESSIV mode";
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
231
232
  		return -EINVAL;
  	}
b95bf2d3d   Milan Broz   dm crypt: separat...
233
  	/* Allocate hash algorithm */
350586879   Herbert Xu   [CRYPTO] users: U...
234
235
  	hash_tfm = crypto_alloc_hash(opts, 0, CRYPTO_ALG_ASYNC);
  	if (IS_ERR(hash_tfm)) {
72d948616   Alasdair G Kergon   [PATCH] dm: impro...
236
  		ti->error = "Error initializing ESSIV hash";
5861f1be0   Milan Broz   dm crypt: restruc...
237
238
  		err = PTR_ERR(hash_tfm);
  		goto bad;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
239
  	}
b95bf2d3d   Milan Broz   dm crypt: separat...
240
  	salt = kzalloc(crypto_hash_digestsize(hash_tfm), GFP_KERNEL);
5861f1be0   Milan Broz   dm crypt: restruc...
241
  	if (!salt) {
72d948616   Alasdair G Kergon   [PATCH] dm: impro...
242
  		ti->error = "Error kmallocing salt storage in ESSIV";
5861f1be0   Milan Broz   dm crypt: restruc...
243
244
  		err = -ENOMEM;
  		goto bad;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
245
  	}
b95bf2d3d   Milan Broz   dm crypt: separat...
246
  	/* Allocate essiv_tfm */
d1806f6a9   Herbert Xu   [BLOCK] dm-crypt:...
247
248
  	essiv_tfm = crypto_alloc_cipher(cc->cipher, 0, CRYPTO_ALG_ASYNC);
  	if (IS_ERR(essiv_tfm)) {
72d948616   Alasdair G Kergon   [PATCH] dm: impro...
249
  		ti->error = "Error allocating crypto tfm for ESSIV";
5861f1be0   Milan Broz   dm crypt: restruc...
250
251
  		err = PTR_ERR(essiv_tfm);
  		goto bad;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
252
  	}
d1806f6a9   Herbert Xu   [BLOCK] dm-crypt:...
253
  	if (crypto_cipher_blocksize(essiv_tfm) !=
3a7f6c990   Milan Broz   dm crypt: use asy...
254
  	    crypto_ablkcipher_ivsize(cc->tfm)) {
72d948616   Alasdair G Kergon   [PATCH] dm: impro...
255
  		ti->error = "Block size of ESSIV cipher does "
d469f8419   Milan Broz   dm crypt: tidy wh...
256
  			    "not match IV size of block cipher";
5861f1be0   Milan Broz   dm crypt: restruc...
257
258
  		err = -EINVAL;
  		goto bad;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
259
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
260

b95bf2d3d   Milan Broz   dm crypt: separat...
261
  	cc->iv_gen_private.essiv.salt = salt;
604735927   Milan Broz   dm crypt: move pr...
262
  	cc->iv_gen_private.essiv.tfm = essiv_tfm;
b95bf2d3d   Milan Broz   dm crypt: separat...
263
  	cc->iv_gen_private.essiv.hash_tfm = hash_tfm;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
264
  	return 0;
5861f1be0   Milan Broz   dm crypt: restruc...
265
266
267
268
269
270
  
  bad:
  	if (essiv_tfm && !IS_ERR(essiv_tfm))
  		crypto_free_cipher(essiv_tfm);
  	if (hash_tfm && !IS_ERR(hash_tfm))
  		crypto_free_hash(hash_tfm);
b95bf2d3d   Milan Broz   dm crypt: separat...
271
  	kfree(salt);
5861f1be0   Milan Broz   dm crypt: restruc...
272
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
273
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
274
275
  static int crypt_iv_essiv_gen(struct crypt_config *cc, u8 *iv, sector_t sector)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
276
277
  	memset(iv, 0, cc->iv_size);
  	*(u64 *)iv = cpu_to_le64(sector);
604735927   Milan Broz   dm crypt: move pr...
278
  	crypto_cipher_encrypt_one(cc->iv_gen_private.essiv.tfm, iv, iv);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279
280
  	return 0;
  }
48527fa7c   Rik Snel   [BLOCK] dm-crypt:...
281
282
283
  static int crypt_iv_benbi_ctr(struct crypt_config *cc, struct dm_target *ti,
  			      const char *opts)
  {
3a7f6c990   Milan Broz   dm crypt: use asy...
284
  	unsigned bs = crypto_ablkcipher_blocksize(cc->tfm);
f0d1b0b30   David Howells   [PATCH] LOG2: Imp...
285
  	int log = ilog2(bs);
48527fa7c   Rik Snel   [BLOCK] dm-crypt:...
286
287
288
289
290
291
292
293
294
295
296
297
298
  
  	/* we need to calculate how far we must shift the sector count
  	 * to get the cipher block count, we use this shift in _gen */
  
  	if (1 << log != bs) {
  		ti->error = "cypher blocksize is not a power of 2";
  		return -EINVAL;
  	}
  
  	if (log > 9) {
  		ti->error = "cypher blocksize is > 512";
  		return -EINVAL;
  	}
604735927   Milan Broz   dm crypt: move pr...
299
  	cc->iv_gen_private.benbi.shift = 9 - log;
48527fa7c   Rik Snel   [BLOCK] dm-crypt:...
300
301
302
303
304
305
  
  	return 0;
  }
  
  static void crypt_iv_benbi_dtr(struct crypt_config *cc)
  {
48527fa7c   Rik Snel   [BLOCK] dm-crypt:...
306
307
308
309
  }
  
  static int crypt_iv_benbi_gen(struct crypt_config *cc, u8 *iv, sector_t sector)
  {
79066ad32   Herbert Xu   [CRYPTO] dm-crypt...
310
  	__be64 val;
48527fa7c   Rik Snel   [BLOCK] dm-crypt:...
311
  	memset(iv, 0, cc->iv_size - sizeof(u64)); /* rest is cleared below */
79066ad32   Herbert Xu   [CRYPTO] dm-crypt...
312

604735927   Milan Broz   dm crypt: move pr...
313
  	val = cpu_to_be64(((u64)sector << cc->iv_gen_private.benbi.shift) + 1);
79066ad32   Herbert Xu   [CRYPTO] dm-crypt...
314
  	put_unaligned(val, (__be64 *)(iv + cc->iv_size - sizeof(u64)));
48527fa7c   Rik Snel   [BLOCK] dm-crypt:...
315

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
316
317
  	return 0;
  }
46b477306   Ludwig Nussel   dm crypt: add nul...
318
319
320
321
322
323
  static int crypt_iv_null_gen(struct crypt_config *cc, u8 *iv, sector_t sector)
  {
  	memset(iv, 0, cc->iv_size);
  
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
324
325
326
  static struct crypt_iv_operations crypt_iv_plain_ops = {
  	.generator = crypt_iv_plain_gen
  };
61afef614   Milan Broz   dm crypt: add pla...
327
328
329
  static struct crypt_iv_operations crypt_iv_plain64_ops = {
  	.generator = crypt_iv_plain64_gen
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
330
331
332
  static struct crypt_iv_operations crypt_iv_essiv_ops = {
  	.ctr       = crypt_iv_essiv_ctr,
  	.dtr       = crypt_iv_essiv_dtr,
b95bf2d3d   Milan Broz   dm crypt: separat...
333
  	.init      = crypt_iv_essiv_init,
542da3176   Milan Broz   dm crypt: make wi...
334
  	.wipe      = crypt_iv_essiv_wipe,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
335
336
  	.generator = crypt_iv_essiv_gen
  };
48527fa7c   Rik Snel   [BLOCK] dm-crypt:...
337
338
339
340
341
  static struct crypt_iv_operations crypt_iv_benbi_ops = {
  	.ctr	   = crypt_iv_benbi_ctr,
  	.dtr	   = crypt_iv_benbi_dtr,
  	.generator = crypt_iv_benbi_gen
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
342

46b477306   Ludwig Nussel   dm crypt: add nul...
343
344
345
  static struct crypt_iv_operations crypt_iv_null_ops = {
  	.generator = crypt_iv_null_gen
  };
d469f8419   Milan Broz   dm crypt: tidy wh...
346
347
348
  static void crypt_convert_init(struct crypt_config *cc,
  			       struct convert_context *ctx,
  			       struct bio *bio_out, struct bio *bio_in,
fcd369daa   Milan Broz   dm crypt: remove ...
349
  			       sector_t sector)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
350
351
352
353
354
355
356
357
  {
  	ctx->bio_in = bio_in;
  	ctx->bio_out = bio_out;
  	ctx->offset_in = 0;
  	ctx->offset_out = 0;
  	ctx->idx_in = bio_in ? bio_in->bi_idx : 0;
  	ctx->idx_out = bio_out ? bio_out->bi_idx : 0;
  	ctx->sector = sector + cc->iv_offset;
43d690348   Milan Broz   dm crypt: add com...
358
  	init_completion(&ctx->restart);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
359
  }
b2174eebd   Huang Ying   dm crypt: fix kcr...
360
361
362
363
364
365
366
367
368
369
370
  static struct dm_crypt_request *dmreq_of_req(struct crypt_config *cc,
  					     struct ablkcipher_request *req)
  {
  	return (struct dm_crypt_request *)((char *)req + cc->dmreq_start);
  }
  
  static struct ablkcipher_request *req_of_dmreq(struct crypt_config *cc,
  					       struct dm_crypt_request *dmreq)
  {
  	return (struct ablkcipher_request *)((char *)dmreq - cc->dmreq_start);
  }
01482b767   Milan Broz   dm crypt: extract...
371
  static int crypt_convert_block(struct crypt_config *cc,
3a7f6c990   Milan Broz   dm crypt: use asy...
372
373
  			       struct convert_context *ctx,
  			       struct ablkcipher_request *req)
01482b767   Milan Broz   dm crypt: extract...
374
375
376
  {
  	struct bio_vec *bv_in = bio_iovec_idx(ctx->bio_in, ctx->idx_in);
  	struct bio_vec *bv_out = bio_iovec_idx(ctx->bio_out, ctx->idx_out);
3a7f6c990   Milan Broz   dm crypt: use asy...
377
378
379
  	struct dm_crypt_request *dmreq;
  	u8 *iv;
  	int r = 0;
b2174eebd   Huang Ying   dm crypt: fix kcr...
380
  	dmreq = dmreq_of_req(cc, req);
3a7f6c990   Milan Broz   dm crypt: use asy...
381
382
  	iv = (u8 *)ALIGN((unsigned long)(dmreq + 1),
  			 crypto_ablkcipher_alignmask(cc->tfm) + 1);
01482b767   Milan Broz   dm crypt: extract...
383

b2174eebd   Huang Ying   dm crypt: fix kcr...
384
  	dmreq->ctx = ctx;
3a7f6c990   Milan Broz   dm crypt: use asy...
385
386
  	sg_init_table(&dmreq->sg_in, 1);
  	sg_set_page(&dmreq->sg_in, bv_in->bv_page, 1 << SECTOR_SHIFT,
01482b767   Milan Broz   dm crypt: extract...
387
  		    bv_in->bv_offset + ctx->offset_in);
3a7f6c990   Milan Broz   dm crypt: use asy...
388
389
  	sg_init_table(&dmreq->sg_out, 1);
  	sg_set_page(&dmreq->sg_out, bv_out->bv_page, 1 << SECTOR_SHIFT,
01482b767   Milan Broz   dm crypt: extract...
390
391
392
393
394
395
396
397
398
399
400
401
402
  		    bv_out->bv_offset + ctx->offset_out);
  
  	ctx->offset_in += 1 << SECTOR_SHIFT;
  	if (ctx->offset_in >= bv_in->bv_len) {
  		ctx->offset_in = 0;
  		ctx->idx_in++;
  	}
  
  	ctx->offset_out += 1 << SECTOR_SHIFT;
  	if (ctx->offset_out >= bv_out->bv_len) {
  		ctx->offset_out = 0;
  		ctx->idx_out++;
  	}
3a7f6c990   Milan Broz   dm crypt: use asy...
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
  	if (cc->iv_gen_ops) {
  		r = cc->iv_gen_ops->generator(cc, iv, ctx->sector);
  		if (r < 0)
  			return r;
  	}
  
  	ablkcipher_request_set_crypt(req, &dmreq->sg_in, &dmreq->sg_out,
  				     1 << SECTOR_SHIFT, iv);
  
  	if (bio_data_dir(ctx->bio_in) == WRITE)
  		r = crypto_ablkcipher_encrypt(req);
  	else
  		r = crypto_ablkcipher_decrypt(req);
  
  	return r;
01482b767   Milan Broz   dm crypt: extract...
418
  }
95497a960   Milan Broz   dm crypt: prepare...
419
420
  static void kcryptd_async_done(struct crypto_async_request *async_req,
  			       int error);
ddd42edfd   Milan Broz   dm crypt: add asy...
421
422
423
424
425
  static void crypt_alloc_req(struct crypt_config *cc,
  			    struct convert_context *ctx)
  {
  	if (!cc->req)
  		cc->req = mempool_alloc(cc->req_pool, GFP_NOIO);
95497a960   Milan Broz   dm crypt: prepare...
426
427
  	ablkcipher_request_set_tfm(cc->req, cc->tfm);
  	ablkcipher_request_set_callback(cc->req, CRYPTO_TFM_REQ_MAY_BACKLOG |
b2174eebd   Huang Ying   dm crypt: fix kcr...
428
429
430
  					CRYPTO_TFM_REQ_MAY_SLEEP,
  					kcryptd_async_done,
  					dmreq_of_req(cc, cc->req));
ddd42edfd   Milan Broz   dm crypt: add asy...
431
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
432
433
434
435
  /*
   * Encrypt / decrypt data from one bio to another one (can be the same one)
   */
  static int crypt_convert(struct crypt_config *cc,
d469f8419   Milan Broz   dm crypt: tidy wh...
436
  			 struct convert_context *ctx)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
437
  {
3f1e9070f   Milan Broz   dm crypt: fix ctx...
438
  	int r;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
439

c8081618a   Milan Broz   dm crypt: tidy ct...
440
  	atomic_set(&ctx->pending, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
441
442
  	while(ctx->idx_in < ctx->bio_in->bi_vcnt &&
  	      ctx->idx_out < ctx->bio_out->bi_vcnt) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
443

3a7f6c990   Milan Broz   dm crypt: use asy...
444
  		crypt_alloc_req(cc, ctx);
3f1e9070f   Milan Broz   dm crypt: fix ctx...
445
  		atomic_inc(&ctx->pending);
3a7f6c990   Milan Broz   dm crypt: use asy...
446
447
448
  		r = crypt_convert_block(cc, ctx, cc->req);
  
  		switch (r) {
3f1e9070f   Milan Broz   dm crypt: fix ctx...
449
  		/* async */
3a7f6c990   Milan Broz   dm crypt: use asy...
450
451
452
453
454
  		case -EBUSY:
  			wait_for_completion(&ctx->restart);
  			INIT_COMPLETION(ctx->restart);
  			/* fall through*/
  		case -EINPROGRESS:
3a7f6c990   Milan Broz   dm crypt: use asy...
455
  			cc->req = NULL;
3f1e9070f   Milan Broz   dm crypt: fix ctx...
456
457
458
459
  			ctx->sector++;
  			continue;
  
  		/* sync */
3a7f6c990   Milan Broz   dm crypt: use asy...
460
  		case 0:
3f1e9070f   Milan Broz   dm crypt: fix ctx...
461
  			atomic_dec(&ctx->pending);
3a7f6c990   Milan Broz   dm crypt: use asy...
462
  			ctx->sector++;
c7f1b2044   Milan Broz   dm crypt: use con...
463
  			cond_resched();
3a7f6c990   Milan Broz   dm crypt: use asy...
464
  			continue;
3a7f6c990   Milan Broz   dm crypt: use asy...
465

3f1e9070f   Milan Broz   dm crypt: fix ctx...
466
467
468
469
470
  		/* error */
  		default:
  			atomic_dec(&ctx->pending);
  			return r;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
471
  	}
3f1e9070f   Milan Broz   dm crypt: fix ctx...
472
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
473
  }
d469f8419   Milan Broz   dm crypt: tidy wh...
474
475
  static void dm_crypt_bio_destructor(struct bio *bio)
  {
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
476
  	struct dm_crypt_io *io = bio->bi_private;
6a24c7184   Milan Broz   [PATCH] dm crypt:...
477
478
479
  	struct crypt_config *cc = io->target->private;
  
  	bio_free(bio, cc->bs);
d469f8419   Milan Broz   dm crypt: tidy wh...
480
  }
6a24c7184   Milan Broz   [PATCH] dm crypt:...
481

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
482
483
484
  /*
   * Generate a new unfragmented bio with the given size
   * This should never violate the device limitations
933f01d43   Milan Broz   dm crypt: avoid u...
485
486
   * May return a smaller bio when running out of pages, indicated by
   * *out_of_pages set to 1.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
487
   */
933f01d43   Milan Broz   dm crypt: avoid u...
488
489
  static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned size,
  				      unsigned *out_of_pages)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
490
  {
027581f35   Olaf Kirch   dm crypt: fix cal...
491
  	struct crypt_config *cc = io->target->private;
8b0044571   Milan Broz   [PATCH] dm crypt:...
492
  	struct bio *clone;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
493
  	unsigned int nr_iovecs = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
b4e3ca1ab   Al Viro   [PATCH] gfp_t: re...
494
  	gfp_t gfp_mask = GFP_NOIO | __GFP_HIGHMEM;
91e106259   Milan Broz   dm crypt: use bio...
495
496
  	unsigned i, len;
  	struct page *page;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
497

2f9941b6c   Olaf Kirch   dm crypt: fix rem...
498
  	clone = bio_alloc_bioset(GFP_NOIO, nr_iovecs, cc->bs);
8b0044571   Milan Broz   [PATCH] dm crypt:...
499
  	if (!clone)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
500
  		return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
501

027581f35   Olaf Kirch   dm crypt: fix cal...
502
  	clone_init(io, clone);
933f01d43   Milan Broz   dm crypt: avoid u...
503
  	*out_of_pages = 0;
6a24c7184   Milan Broz   [PATCH] dm crypt:...
504

f97380bca   Olaf Kirch   dm crypt: use sma...
505
  	for (i = 0; i < nr_iovecs; i++) {
91e106259   Milan Broz   dm crypt: use bio...
506
  		page = mempool_alloc(cc->page_pool, gfp_mask);
933f01d43   Milan Broz   dm crypt: avoid u...
507
508
  		if (!page) {
  			*out_of_pages = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
509
  			break;
933f01d43   Milan Broz   dm crypt: avoid u...
510
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
511
512
513
514
515
516
  
  		/*
  		 * if additional pages cannot be allocated without waiting,
  		 * return a partially allocated bio, the caller will then try
  		 * to allocate additional bios while submitting this partial bio
  		 */
f97380bca   Olaf Kirch   dm crypt: use sma...
517
  		if (i == (MIN_BIO_PAGES - 1))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
518
  			gfp_mask = (gfp_mask | __GFP_NOWARN) & ~__GFP_WAIT;
91e106259   Milan Broz   dm crypt: use bio...
519
520
521
522
523
524
  		len = (size > PAGE_SIZE) ? PAGE_SIZE : size;
  
  		if (!bio_add_page(clone, page, len, 0)) {
  			mempool_free(page, cc->page_pool);
  			break;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
525

91e106259   Milan Broz   dm crypt: use bio...
526
  		size -= len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
527
  	}
8b0044571   Milan Broz   [PATCH] dm crypt:...
528
529
  	if (!clone->bi_size) {
  		bio_put(clone);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
530
531
  		return NULL;
  	}
8b0044571   Milan Broz   [PATCH] dm crypt:...
532
  	return clone;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
533
  }
644bd2f04   Neil Brown   Fix memory leak i...
534
  static void crypt_free_buffer_pages(struct crypt_config *cc, struct bio *clone)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
535
  {
644bd2f04   Neil Brown   Fix memory leak i...
536
  	unsigned int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
537
  	struct bio_vec *bv;
644bd2f04   Neil Brown   Fix memory leak i...
538
  	for (i = 0; i < clone->bi_vcnt; i++) {
8b0044571   Milan Broz   [PATCH] dm crypt:...
539
  		bv = bio_iovec_idx(clone, i);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
540
541
542
543
544
  		BUG_ON(!bv->bv_page);
  		mempool_free(bv->bv_page, cc->page_pool);
  		bv->bv_page = NULL;
  	}
  }
dc440d1e5   Milan Broz   dm crypt: tidy cr...
545
546
547
548
549
550
551
552
553
554
555
  static struct dm_crypt_io *crypt_io_alloc(struct dm_target *ti,
  					  struct bio *bio, sector_t sector)
  {
  	struct crypt_config *cc = ti->private;
  	struct dm_crypt_io *io;
  
  	io = mempool_alloc(cc->io_pool, GFP_NOIO);
  	io->target = ti;
  	io->base_bio = bio;
  	io->sector = sector;
  	io->error = 0;
393b47ef2   Milan Broz   dm crypt: fix asy...
556
  	io->base_io = NULL;
dc440d1e5   Milan Broz   dm crypt: tidy cr...
557
558
559
560
  	atomic_set(&io->pending, 0);
  
  	return io;
  }
3e1a8bdd0   Milan Broz   dm crypt: tidy in...
561
562
563
564
  static void crypt_inc_pending(struct dm_crypt_io *io)
  {
  	atomic_inc(&io->pending);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
565
566
567
  /*
   * One of the bios was finished. Check for completion of
   * the whole request and correctly clean up the buffer.
393b47ef2   Milan Broz   dm crypt: fix asy...
568
   * If base_io is set, wait for the last fragment to complete.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
569
   */
5742fd777   Milan Broz   dm crypt: move er...
570
  static void crypt_dec_pending(struct dm_crypt_io *io)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
571
  {
5742fd777   Milan Broz   dm crypt: move er...
572
  	struct crypt_config *cc = io->target->private;
b35f8caa0   Milan Broz   dm crypt: wait fo...
573
574
575
  	struct bio *base_bio = io->base_bio;
  	struct dm_crypt_io *base_io = io->base_io;
  	int error = io->error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
576
577
578
  
  	if (!atomic_dec_and_test(&io->pending))
  		return;
b35f8caa0   Milan Broz   dm crypt: wait fo...
579
580
581
582
  	mempool_free(io, cc->io_pool);
  
  	if (likely(!base_io))
  		bio_endio(base_bio, error);
393b47ef2   Milan Broz   dm crypt: fix asy...
583
  	else {
b35f8caa0   Milan Broz   dm crypt: wait fo...
584
585
586
  		if (error && !base_io->error)
  			base_io->error = error;
  		crypt_dec_pending(base_io);
393b47ef2   Milan Broz   dm crypt: fix asy...
587
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
588
589
590
  }
  
  /*
cabf08e4d   Milan Broz   dm crypt: add pos...
591
   * kcryptd/kcryptd_io:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
592
593
   *
   * Needed because it would be very unwise to do decryption in an
23541d2d2   Milan Broz   [PATCH] dm crypt:...
594
   * interrupt context.
cabf08e4d   Milan Broz   dm crypt: add pos...
595
596
597
598
599
600
601
602
   *
   * kcryptd performs the actual encryption or decryption.
   *
   * kcryptd_io performs the IO submission.
   *
   * They must be separated as otherwise the final stages could be
   * starved by new requests which can block in the first stages due
   * to memory allocation.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
603
   */
6712ecf8f   NeilBrown   Drop 'size' argum...
604
  static void crypt_endio(struct bio *clone, int error)
8b0044571   Milan Broz   [PATCH] dm crypt:...
605
  {
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
606
  	struct dm_crypt_io *io = clone->bi_private;
8b0044571   Milan Broz   [PATCH] dm crypt:...
607
  	struct crypt_config *cc = io->target->private;
ee7a491e6   Milan Broz   dm crypt: tidy cr...
608
  	unsigned rw = bio_data_dir(clone);
8b0044571   Milan Broz   [PATCH] dm crypt:...
609

adfe47702   Milan Broz   dm crypt: fix wri...
610
611
  	if (unlikely(!bio_flagged(clone, BIO_UPTODATE) && !error))
  		error = -EIO;
8b0044571   Milan Broz   [PATCH] dm crypt:...
612
  	/*
6712ecf8f   NeilBrown   Drop 'size' argum...
613
  	 * free the processed pages
8b0044571   Milan Broz   [PATCH] dm crypt:...
614
  	 */
ee7a491e6   Milan Broz   dm crypt: tidy cr...
615
  	if (rw == WRITE)
644bd2f04   Neil Brown   Fix memory leak i...
616
  		crypt_free_buffer_pages(cc, clone);
8b0044571   Milan Broz   [PATCH] dm crypt:...
617
618
  
  	bio_put(clone);
8b0044571   Milan Broz   [PATCH] dm crypt:...
619

ee7a491e6   Milan Broz   dm crypt: tidy cr...
620
621
622
623
  	if (rw == READ && !error) {
  		kcryptd_queue_crypt(io);
  		return;
  	}
5742fd777   Milan Broz   dm crypt: move er...
624
625
626
627
628
  
  	if (unlikely(error))
  		io->error = error;
  
  	crypt_dec_pending(io);
8b0044571   Milan Broz   [PATCH] dm crypt:...
629
  }
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
630
  static void clone_init(struct dm_crypt_io *io, struct bio *clone)
8b0044571   Milan Broz   [PATCH] dm crypt:...
631
632
633
634
635
636
637
  {
  	struct crypt_config *cc = io->target->private;
  
  	clone->bi_private = io;
  	clone->bi_end_io  = crypt_endio;
  	clone->bi_bdev    = cc->dev->bdev;
  	clone->bi_rw      = io->base_bio->bi_rw;
027581f35   Olaf Kirch   dm crypt: fix cal...
638
  	clone->bi_destructor = dm_crypt_bio_destructor;
8b0044571   Milan Broz   [PATCH] dm crypt:...
639
  }
4e4eef64e   Milan Broz   dm crypt: adjust ...
640
  static void kcryptd_io_read(struct dm_crypt_io *io)
8b0044571   Milan Broz   [PATCH] dm crypt:...
641
642
643
644
  {
  	struct crypt_config *cc = io->target->private;
  	struct bio *base_bio = io->base_bio;
  	struct bio *clone;
93e605c23   Milan Broz   [PATCH] dm crypt:...
645

3e1a8bdd0   Milan Broz   dm crypt: tidy in...
646
  	crypt_inc_pending(io);
8b0044571   Milan Broz   [PATCH] dm crypt:...
647
648
649
650
651
652
  
  	/*
  	 * The block layer might modify the bvec array, so always
  	 * copy the required bvecs because we need the original
  	 * one in order to decrypt the whole bio data *afterwards*.
  	 */
6a24c7184   Milan Broz   [PATCH] dm crypt:...
653
  	clone = bio_alloc_bioset(GFP_NOIO, bio_segments(base_bio), cc->bs);
93e605c23   Milan Broz   [PATCH] dm crypt:...
654
  	if (unlikely(!clone)) {
5742fd777   Milan Broz   dm crypt: move er...
655
656
  		io->error = -ENOMEM;
  		crypt_dec_pending(io);
23541d2d2   Milan Broz   [PATCH] dm crypt:...
657
  		return;
93e605c23   Milan Broz   [PATCH] dm crypt:...
658
  	}
8b0044571   Milan Broz   [PATCH] dm crypt:...
659
660
661
662
663
  
  	clone_init(io, clone);
  	clone->bi_idx = 0;
  	clone->bi_vcnt = bio_segments(base_bio);
  	clone->bi_size = base_bio->bi_size;
0c395b0f8   Milan Broz   dm crypt: store s...
664
  	clone->bi_sector = cc->start + io->sector;
8b0044571   Milan Broz   [PATCH] dm crypt:...
665
666
  	memcpy(clone->bi_io_vec, bio_iovec(base_bio),
  	       sizeof(struct bio_vec) * clone->bi_vcnt);
8b0044571   Milan Broz   [PATCH] dm crypt:...
667

93e605c23   Milan Broz   [PATCH] dm crypt:...
668
  	generic_make_request(clone);
8b0044571   Milan Broz   [PATCH] dm crypt:...
669
  }
4e4eef64e   Milan Broz   dm crypt: adjust ...
670
671
  static void kcryptd_io_write(struct dm_crypt_io *io)
  {
95497a960   Milan Broz   dm crypt: prepare...
672
  	struct bio *clone = io->ctx.bio_out;
95497a960   Milan Broz   dm crypt: prepare...
673
  	generic_make_request(clone);
4e4eef64e   Milan Broz   dm crypt: adjust ...
674
  }
395b167ca   Alasdair G Kergon   dm crypt: move qu...
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
  static void kcryptd_io(struct work_struct *work)
  {
  	struct dm_crypt_io *io = container_of(work, struct dm_crypt_io, work);
  
  	if (bio_data_dir(io->base_bio) == READ)
  		kcryptd_io_read(io);
  	else
  		kcryptd_io_write(io);
  }
  
  static void kcryptd_queue_io(struct dm_crypt_io *io)
  {
  	struct crypt_config *cc = io->target->private;
  
  	INIT_WORK(&io->work, kcryptd_io);
  	queue_work(cc->io_queue, &io->work);
  }
95497a960   Milan Broz   dm crypt: prepare...
692
693
  static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io,
  					  int error, int async)
4e4eef64e   Milan Broz   dm crypt: adjust ...
694
  {
dec1cedf9   Milan Broz   dm crypt: abstrac...
695
696
697
698
699
700
701
  	struct bio *clone = io->ctx.bio_out;
  	struct crypt_config *cc = io->target->private;
  
  	if (unlikely(error < 0)) {
  		crypt_free_buffer_pages(cc, clone);
  		bio_put(clone);
  		io->error = -EIO;
6c031f41d   Milan Broz   dm crypt: move de...
702
  		crypt_dec_pending(io);
dec1cedf9   Milan Broz   dm crypt: abstrac...
703
704
705
706
707
708
709
  		return;
  	}
  
  	/* crypt_convert should have filled the clone bio */
  	BUG_ON(io->ctx.idx_out < clone->bi_vcnt);
  
  	clone->bi_sector = cc->start + io->sector;
899c95d36   Milan Broz   dm crypt: tidy io...
710

95497a960   Milan Broz   dm crypt: prepare...
711
712
  	if (async)
  		kcryptd_queue_io(io);
1e37bb8e5   Alasdair G Kergon   dm crypt: remove ...
713
  	else
95497a960   Milan Broz   dm crypt: prepare...
714
  		generic_make_request(clone);
4e4eef64e   Milan Broz   dm crypt: adjust ...
715
  }
fc5a5e9aa   Milan Broz   dm crypt: tidy wr...
716
  static void kcryptd_crypt_write_convert(struct dm_crypt_io *io)
8b0044571   Milan Broz   [PATCH] dm crypt:...
717
718
  {
  	struct crypt_config *cc = io->target->private;
8b0044571   Milan Broz   [PATCH] dm crypt:...
719
  	struct bio *clone;
393b47ef2   Milan Broz   dm crypt: fix asy...
720
  	struct dm_crypt_io *new_io;
c8081618a   Milan Broz   dm crypt: tidy ct...
721
  	int crypt_finished;
933f01d43   Milan Broz   dm crypt: avoid u...
722
  	unsigned out_of_pages = 0;
dec1cedf9   Milan Broz   dm crypt: abstrac...
723
  	unsigned remaining = io->base_bio->bi_size;
b635b00e0   Milan Broz   dm crypt: tidy se...
724
  	sector_t sector = io->sector;
dec1cedf9   Milan Broz   dm crypt: abstrac...
725
  	int r;
8b0044571   Milan Broz   [PATCH] dm crypt:...
726

93e605c23   Milan Broz   [PATCH] dm crypt:...
727
  	/*
fc5a5e9aa   Milan Broz   dm crypt: tidy wr...
728
729
730
  	 * Prevent io from disappearing until this function completes.
  	 */
  	crypt_inc_pending(io);
b635b00e0   Milan Broz   dm crypt: tidy se...
731
  	crypt_convert_init(cc, &io->ctx, NULL, io->base_bio, sector);
fc5a5e9aa   Milan Broz   dm crypt: tidy wr...
732
733
  
  	/*
93e605c23   Milan Broz   [PATCH] dm crypt:...
734
735
736
737
  	 * The allocated buffers can be smaller than the whole bio,
  	 * so repeat the whole process until all the data can be handled.
  	 */
  	while (remaining) {
933f01d43   Milan Broz   dm crypt: avoid u...
738
  		clone = crypt_alloc_buffer(io, remaining, &out_of_pages);
23541d2d2   Milan Broz   [PATCH] dm crypt:...
739
  		if (unlikely(!clone)) {
5742fd777   Milan Broz   dm crypt: move er...
740
  			io->error = -ENOMEM;
fc5a5e9aa   Milan Broz   dm crypt: tidy wr...
741
  			break;
23541d2d2   Milan Broz   [PATCH] dm crypt:...
742
  		}
93e605c23   Milan Broz   [PATCH] dm crypt:...
743

53017030e   Milan Broz   dm crypt: move co...
744
745
  		io->ctx.bio_out = clone;
  		io->ctx.idx_out = 0;
93e605c23   Milan Broz   [PATCH] dm crypt:...
746

dec1cedf9   Milan Broz   dm crypt: abstrac...
747
  		remaining -= clone->bi_size;
b635b00e0   Milan Broz   dm crypt: tidy se...
748
  		sector += bio_sectors(clone);
93e605c23   Milan Broz   [PATCH] dm crypt:...
749

4e5940989   Milan Broz   dm crypt: fix asy...
750
  		crypt_inc_pending(io);
dec1cedf9   Milan Broz   dm crypt: abstrac...
751
  		r = crypt_convert(cc, &io->ctx);
c8081618a   Milan Broz   dm crypt: tidy ct...
752
  		crypt_finished = atomic_dec_and_test(&io->ctx.pending);
f97380bca   Olaf Kirch   dm crypt: use sma...
753

c8081618a   Milan Broz   dm crypt: tidy ct...
754
755
  		/* Encryption was already finished, submit io now */
  		if (crypt_finished) {
3a7f6c990   Milan Broz   dm crypt: use asy...
756
  			kcryptd_crypt_write_io_submit(io, r, 0);
c8081618a   Milan Broz   dm crypt: tidy ct...
757
758
759
760
761
  
  			/*
  			 * If there was an error, do not try next fragments.
  			 * For async, error is processed in async handler.
  			 */
6c031f41d   Milan Broz   dm crypt: move de...
762
  			if (unlikely(r < 0))
fc5a5e9aa   Milan Broz   dm crypt: tidy wr...
763
  				break;
b635b00e0   Milan Broz   dm crypt: tidy se...
764
765
  
  			io->sector = sector;
4e5940989   Milan Broz   dm crypt: fix asy...
766
  		}
93e605c23   Milan Broz   [PATCH] dm crypt:...
767

933f01d43   Milan Broz   dm crypt: avoid u...
768
769
770
771
772
  		/*
  		 * Out of memory -> run queues
  		 * But don't wait if split was due to the io size restriction
  		 */
  		if (unlikely(out_of_pages))
8aa7e847d   Jens Axboe   Fix congestion_wa...
773
  			congestion_wait(BLK_RW_ASYNC, HZ/100);
933f01d43   Milan Broz   dm crypt: avoid u...
774

393b47ef2   Milan Broz   dm crypt: fix asy...
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
  		/*
  		 * With async crypto it is unsafe to share the crypto context
  		 * between fragments, so switch to a new dm_crypt_io structure.
  		 */
  		if (unlikely(!crypt_finished && remaining)) {
  			new_io = crypt_io_alloc(io->target, io->base_bio,
  						sector);
  			crypt_inc_pending(new_io);
  			crypt_convert_init(cc, &new_io->ctx, NULL,
  					   io->base_bio, sector);
  			new_io->ctx.idx_in = io->ctx.idx_in;
  			new_io->ctx.offset_in = io->ctx.offset_in;
  
  			/*
  			 * Fragments after the first use the base_io
  			 * pending count.
  			 */
  			if (!io->base_io)
  				new_io->base_io = io;
  			else {
  				new_io->base_io = io->base_io;
  				crypt_inc_pending(io->base_io);
  				crypt_dec_pending(io);
  			}
  
  			io = new_io;
  		}
93e605c23   Milan Broz   [PATCH] dm crypt:...
802
  	}
899c95d36   Milan Broz   dm crypt: tidy io...
803
804
  
  	crypt_dec_pending(io);
84131db68   Milan Broz   dm crypt: introdu...
805
  }
4e4eef64e   Milan Broz   dm crypt: adjust ...
806
  static void kcryptd_crypt_read_done(struct dm_crypt_io *io, int error)
5742fd777   Milan Broz   dm crypt: move er...
807
808
809
810
811
812
  {
  	if (unlikely(error < 0))
  		io->error = -EIO;
  
  	crypt_dec_pending(io);
  }
4e4eef64e   Milan Broz   dm crypt: adjust ...
813
  static void kcryptd_crypt_read_convert(struct dm_crypt_io *io)
8b0044571   Milan Broz   [PATCH] dm crypt:...
814
815
  {
  	struct crypt_config *cc = io->target->private;
5742fd777   Milan Broz   dm crypt: move er...
816
  	int r = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
817

3e1a8bdd0   Milan Broz   dm crypt: tidy in...
818
  	crypt_inc_pending(io);
3a7f6c990   Milan Broz   dm crypt: use asy...
819

53017030e   Milan Broz   dm crypt: move co...
820
  	crypt_convert_init(cc, &io->ctx, io->base_bio, io->base_bio,
0c395b0f8   Milan Broz   dm crypt: store s...
821
  			   io->sector);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
822

5742fd777   Milan Broz   dm crypt: move er...
823
  	r = crypt_convert(cc, &io->ctx);
3f1e9070f   Milan Broz   dm crypt: fix ctx...
824
  	if (atomic_dec_and_test(&io->ctx.pending))
3a7f6c990   Milan Broz   dm crypt: use asy...
825
826
827
  		kcryptd_crypt_read_done(io, r);
  
  	crypt_dec_pending(io);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
828
  }
95497a960   Milan Broz   dm crypt: prepare...
829
830
831
  static void kcryptd_async_done(struct crypto_async_request *async_req,
  			       int error)
  {
b2174eebd   Huang Ying   dm crypt: fix kcr...
832
833
  	struct dm_crypt_request *dmreq = async_req->data;
  	struct convert_context *ctx = dmreq->ctx;
95497a960   Milan Broz   dm crypt: prepare...
834
835
836
837
838
839
840
  	struct dm_crypt_io *io = container_of(ctx, struct dm_crypt_io, ctx);
  	struct crypt_config *cc = io->target->private;
  
  	if (error == -EINPROGRESS) {
  		complete(&ctx->restart);
  		return;
  	}
b2174eebd   Huang Ying   dm crypt: fix kcr...
841
  	mempool_free(req_of_dmreq(cc, dmreq), cc->req_pool);
95497a960   Milan Broz   dm crypt: prepare...
842
843
844
845
846
847
848
849
850
  
  	if (!atomic_dec_and_test(&ctx->pending))
  		return;
  
  	if (bio_data_dir(io->base_bio) == READ)
  		kcryptd_crypt_read_done(io, error);
  	else
  		kcryptd_crypt_write_io_submit(io, error, 1);
  }
395b167ca   Alasdair G Kergon   dm crypt: move qu...
851
  static void kcryptd_crypt(struct work_struct *work)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
852
  {
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
853
  	struct dm_crypt_io *io = container_of(work, struct dm_crypt_io, work);
8b0044571   Milan Broz   [PATCH] dm crypt:...
854

cabf08e4d   Milan Broz   dm crypt: add pos...
855
  	if (bio_data_dir(io->base_bio) == READ)
395b167ca   Alasdair G Kergon   dm crypt: move qu...
856
  		kcryptd_crypt_read_convert(io);
4e4eef64e   Milan Broz   dm crypt: adjust ...
857
  	else
395b167ca   Alasdair G Kergon   dm crypt: move qu...
858
  		kcryptd_crypt_write_convert(io);
cabf08e4d   Milan Broz   dm crypt: add pos...
859
  }
395b167ca   Alasdair G Kergon   dm crypt: move qu...
860
  static void kcryptd_queue_crypt(struct dm_crypt_io *io)
cabf08e4d   Milan Broz   dm crypt: add pos...
861
  {
395b167ca   Alasdair G Kergon   dm crypt: move qu...
862
  	struct crypt_config *cc = io->target->private;
cabf08e4d   Milan Broz   dm crypt: add pos...
863

395b167ca   Alasdair G Kergon   dm crypt: move qu...
864
865
  	INIT_WORK(&io->work, kcryptd_crypt);
  	queue_work(cc->crypt_queue, &io->work);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
866
867
868
869
870
871
872
873
874
875
876
877
  }
  
  /*
   * Decode key from its hex representation
   */
  static int crypt_decode_key(u8 *key, char *hex, unsigned int size)
  {
  	char buffer[3];
  	char *endp;
  	unsigned int i;
  
  	buffer[2] = '\0';
8b0044571   Milan Broz   [PATCH] dm crypt:...
878
  	for (i = 0; i < size; i++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
  		buffer[0] = *hex++;
  		buffer[1] = *hex++;
  
  		key[i] = (u8)simple_strtoul(buffer, &endp, 16);
  
  		if (endp != &buffer[2])
  			return -EINVAL;
  	}
  
  	if (*hex != '\0')
  		return -EINVAL;
  
  	return 0;
  }
  
  /*
   * Encode key into its hex representation
   */
  static void crypt_encode_key(char *hex, u8 *key, unsigned int size)
  {
  	unsigned int i;
8b0044571   Milan Broz   [PATCH] dm crypt:...
900
  	for (i = 0; i < size; i++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
901
902
903
904
905
  		sprintf(hex, "%02x", *key);
  		hex += 2;
  		key++;
  	}
  }
e48d4bbf9   Milan Broz   [PATCH] dm crypt:...
906
907
908
909
910
911
912
913
914
915
  static int crypt_set_key(struct crypt_config *cc, char *key)
  {
  	unsigned key_size = strlen(key) >> 1;
  
  	if (cc->key_size && cc->key_size != key_size)
  		return -EINVAL;
  
  	cc->key_size = key_size; /* initial settings */
  
  	if ((!key_size && strcmp(key, "-")) ||
d469f8419   Milan Broz   dm crypt: tidy wh...
916
  	   (key_size && crypt_decode_key(cc->key, key, key_size) < 0))
e48d4bbf9   Milan Broz   [PATCH] dm crypt:...
917
918
919
  		return -EINVAL;
  
  	set_bit(DM_CRYPT_KEY_VALID, &cc->flags);
0b4309581   Milan Broz   dm crypt: make wi...
920
  	return crypto_ablkcipher_setkey(cc->tfm, cc->key, cc->key_size);
e48d4bbf9   Milan Broz   [PATCH] dm crypt:...
921
922
923
924
925
926
  }
  
  static int crypt_wipe_key(struct crypt_config *cc)
  {
  	clear_bit(DM_CRYPT_KEY_VALID, &cc->flags);
  	memset(&cc->key, 0, cc->key_size * sizeof(u8));
0b4309581   Milan Broz   dm crypt: make wi...
927
  	return crypto_ablkcipher_setkey(cc->tfm, cc->key, cc->key_size);
e48d4bbf9   Milan Broz   [PATCH] dm crypt:...
928
  }
28513fccf   Milan Broz   dm crypt: simplif...
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
  static void crypt_dtr(struct dm_target *ti)
  {
  	struct crypt_config *cc = ti->private;
  
  	ti->private = NULL;
  
  	if (!cc)
  		return;
  
  	if (cc->io_queue)
  		destroy_workqueue(cc->io_queue);
  	if (cc->crypt_queue)
  		destroy_workqueue(cc->crypt_queue);
  
  	if (cc->bs)
  		bioset_free(cc->bs);
  
  	if (cc->page_pool)
  		mempool_destroy(cc->page_pool);
  	if (cc->req_pool)
  		mempool_destroy(cc->req_pool);
  	if (cc->io_pool)
  		mempool_destroy(cc->io_pool);
  
  	if (cc->iv_gen_ops && cc->iv_gen_ops->dtr)
  		cc->iv_gen_ops->dtr(cc);
  
  	if (cc->tfm && !IS_ERR(cc->tfm))
  		crypto_free_ablkcipher(cc->tfm);
  
  	if (cc->dev)
  		dm_put_device(ti, cc->dev);
5ebaee6d2   Milan Broz   dm crypt: simplif...
961
962
  	kzfree(cc->cipher);
  	kzfree(cc->cipher_mode);
28513fccf   Milan Broz   dm crypt: simplif...
963
964
965
966
  
  	/* Must zero key material before freeing */
  	kzfree(cc);
  }
5ebaee6d2   Milan Broz   dm crypt: simplif...
967
968
  static int crypt_ctr_cipher(struct dm_target *ti,
  			    char *cipher_in, char *key)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
969
  {
5ebaee6d2   Milan Broz   dm crypt: simplif...
970
971
972
  	struct crypt_config *cc = ti->private;
  	char *tmp, *cipher, *chainmode, *ivmode, *ivopts;
  	char *cipher_api = NULL;
28513fccf   Milan Broz   dm crypt: simplif...
973
  	int ret = -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
974

5ebaee6d2   Milan Broz   dm crypt: simplif...
975
976
977
  	/* Convert to crypto api definition? */
  	if (strchr(cipher_in, '(')) {
  		ti->error = "Bad cipher specification";
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
978
979
  		return -EINVAL;
  	}
5ebaee6d2   Milan Broz   dm crypt: simplif...
980
981
982
983
984
  	/*
  	 * Legacy dm-crypt cipher specification
  	 * cipher-mode-iv:ivopts
  	 */
  	tmp = cipher_in;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
985
  	cipher = strsep(&tmp, "-");
5ebaee6d2   Milan Broz   dm crypt: simplif...
986
987
988
989
990
991
992
993
994
995
  
  	cc->cipher = kstrdup(cipher, GFP_KERNEL);
  	if (!cc->cipher)
  		goto bad_mem;
  
  	if (tmp) {
  		cc->cipher_mode = kstrdup(tmp, GFP_KERNEL);
  		if (!cc->cipher_mode)
  			goto bad_mem;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
996
997
998
999
1000
  	chainmode = strsep(&tmp, "-");
  	ivopts = strsep(&tmp, "-");
  	ivmode = strsep(&ivopts, ":");
  
  	if (tmp)
5ebaee6d2   Milan Broz   dm crypt: simplif...
1001
  		DMWARN("Ignoring unexpected additional cipher options");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1002

5ebaee6d2   Milan Broz   dm crypt: simplif...
1003
1004
1005
1006
  	/* Compatibility mode for old dm-crypt mappings */
  	if (!chainmode || (!strcmp(chainmode, "plain") && !ivmode)) {
  		kfree(cc->cipher_mode);
  		cc->cipher_mode = kstrdup("cbc-plain", GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1007
1008
1009
  		chainmode = "cbc";
  		ivmode = "plain";
  	}
d1806f6a9   Herbert Xu   [BLOCK] dm-crypt:...
1010
  	if (strcmp(chainmode, "ecb") && !ivmode) {
5ebaee6d2   Milan Broz   dm crypt: simplif...
1011
1012
  		ti->error = "IV mechanism required";
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1013
  	}
5ebaee6d2   Milan Broz   dm crypt: simplif...
1014
1015
1016
1017
1018
1019
1020
1021
1022
  	cipher_api = kmalloc(CRYPTO_MAX_ALG_NAME, GFP_KERNEL);
  	if (!cipher_api)
  		goto bad_mem;
  
  	ret = snprintf(cipher_api, CRYPTO_MAX_ALG_NAME,
  		       "%s(%s)", chainmode, cipher);
  	if (ret < 0) {
  		kfree(cipher_api);
  		goto bad_mem;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1023
  	}
5ebaee6d2   Milan Broz   dm crypt: simplif...
1024
1025
  	/* Allocate cipher */
  	cc->tfm = crypto_alloc_ablkcipher(cipher_api, 0, 0);
28513fccf   Milan Broz   dm crypt: simplif...
1026
  	if (IS_ERR(cc->tfm)) {
5ebaee6d2   Milan Broz   dm crypt: simplif...
1027
  		ret = PTR_ERR(cc->tfm);
72d948616   Alasdair G Kergon   [PATCH] dm: impro...
1028
  		ti->error = "Error allocating crypto tfm";
28513fccf   Milan Broz   dm crypt: simplif...
1029
  		goto bad;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1030
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1031

5ebaee6d2   Milan Broz   dm crypt: simplif...
1032
1033
  	/* Initialize and set key */
  	ret = crypt_set_key(cc, key);
28513fccf   Milan Broz   dm crypt: simplif...
1034
  	if (ret < 0) {
0b4309581   Milan Broz   dm crypt: make wi...
1035
  		ti->error = "Error decoding and setting key";
28513fccf   Milan Broz   dm crypt: simplif...
1036
  		goto bad;
0b4309581   Milan Broz   dm crypt: make wi...
1037
  	}
5ebaee6d2   Milan Broz   dm crypt: simplif...
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
  	/* Initialize IV */
  	cc->iv_size = crypto_ablkcipher_ivsize(cc->tfm);
  	if (cc->iv_size)
  		/* at least a 64 bit sector number should fit in our buffer */
  		cc->iv_size = max(cc->iv_size,
  				  (unsigned int)(sizeof(u64) / sizeof(u8)));
  	else if (ivmode) {
  		DMWARN("Selected cipher does not support IVs");
  		ivmode = NULL;
  	}
  
  	/* Choose ivmode, see comments at iv code. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1050
1051
1052
1053
  	if (ivmode == NULL)
  		cc->iv_gen_ops = NULL;
  	else if (strcmp(ivmode, "plain") == 0)
  		cc->iv_gen_ops = &crypt_iv_plain_ops;
61afef614   Milan Broz   dm crypt: add pla...
1054
1055
  	else if (strcmp(ivmode, "plain64") == 0)
  		cc->iv_gen_ops = &crypt_iv_plain64_ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1056
1057
  	else if (strcmp(ivmode, "essiv") == 0)
  		cc->iv_gen_ops = &crypt_iv_essiv_ops;
48527fa7c   Rik Snel   [BLOCK] dm-crypt:...
1058
1059
  	else if (strcmp(ivmode, "benbi") == 0)
  		cc->iv_gen_ops = &crypt_iv_benbi_ops;
46b477306   Ludwig Nussel   dm crypt: add nul...
1060
1061
  	else if (strcmp(ivmode, "null") == 0)
  		cc->iv_gen_ops = &crypt_iv_null_ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1062
  	else {
5ebaee6d2   Milan Broz   dm crypt: simplif...
1063
  		ret = -EINVAL;
72d948616   Alasdair G Kergon   [PATCH] dm: impro...
1064
  		ti->error = "Invalid IV mode";
28513fccf   Milan Broz   dm crypt: simplif...
1065
  		goto bad;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1066
  	}
28513fccf   Milan Broz   dm crypt: simplif...
1067
1068
1069
1070
1071
1072
1073
1074
  	/* Allocate IV */
  	if (cc->iv_gen_ops && cc->iv_gen_ops->ctr) {
  		ret = cc->iv_gen_ops->ctr(cc, ti, ivopts);
  		if (ret < 0) {
  			ti->error = "Error creating IV";
  			goto bad;
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1075

28513fccf   Milan Broz   dm crypt: simplif...
1076
1077
1078
1079
1080
1081
1082
  	/* Initialize IV (set keys for ESSIV etc) */
  	if (cc->iv_gen_ops && cc->iv_gen_ops->init) {
  		ret = cc->iv_gen_ops->init(cc);
  		if (ret < 0) {
  			ti->error = "Error initialising IV";
  			goto bad;
  		}
b95bf2d3d   Milan Broz   dm crypt: separat...
1083
  	}
5ebaee6d2   Milan Broz   dm crypt: simplif...
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
  	ret = 0;
  bad:
  	kfree(cipher_api);
  	return ret;
  
  bad_mem:
  	ti->error = "Cannot allocate cipher strings";
  	return -ENOMEM;
  }
  
  /*
   * Construct an encryption mapping:
   * <cipher> <key> <iv_offset> <dev_path> <start>
   */
  static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
  {
  	struct crypt_config *cc;
  	unsigned int key_size;
  	unsigned long long tmpll;
  	int ret;
  
  	if (argc != 5) {
  		ti->error = "Not enough arguments";
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1108
  	}
5ebaee6d2   Milan Broz   dm crypt: simplif...
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
  	key_size = strlen(argv[1]) >> 1;
  
  	cc = kzalloc(sizeof(*cc) + key_size * sizeof(u8), GFP_KERNEL);
  	if (!cc) {
  		ti->error = "Cannot allocate encryption context";
  		return -ENOMEM;
  	}
  
  	ti->private = cc;
  	ret = crypt_ctr_cipher(ti, argv[0], argv[1]);
  	if (ret < 0)
  		goto bad;
28513fccf   Milan Broz   dm crypt: simplif...
1121
  	ret = -ENOMEM;
93d2341c7   Matthew Dobson   [PATCH] mempool: ...
1122
  	cc->io_pool = mempool_create_slab_pool(MIN_IOS, _crypt_io_pool);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1123
  	if (!cc->io_pool) {
72d948616   Alasdair G Kergon   [PATCH] dm: impro...
1124
  		ti->error = "Cannot allocate crypt io mempool";
28513fccf   Milan Broz   dm crypt: simplif...
1125
  		goto bad;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1126
  	}
ddd42edfd   Milan Broz   dm crypt: add asy...
1127
  	cc->dmreq_start = sizeof(struct ablkcipher_request);
28513fccf   Milan Broz   dm crypt: simplif...
1128
  	cc->dmreq_start += crypto_ablkcipher_reqsize(cc->tfm);
ddd42edfd   Milan Broz   dm crypt: add asy...
1129
  	cc->dmreq_start = ALIGN(cc->dmreq_start, crypto_tfm_ctx_alignment());
28513fccf   Milan Broz   dm crypt: simplif...
1130
  	cc->dmreq_start += crypto_ablkcipher_alignmask(cc->tfm) &
3a7f6c990   Milan Broz   dm crypt: use asy...
1131
  			   ~(crypto_tfm_ctx_alignment() - 1);
ddd42edfd   Milan Broz   dm crypt: add asy...
1132
1133
1134
1135
1136
  
  	cc->req_pool = mempool_create_kmalloc_pool(MIN_IOS, cc->dmreq_start +
  			sizeof(struct dm_crypt_request) + cc->iv_size);
  	if (!cc->req_pool) {
  		ti->error = "Cannot allocate crypt request mempool";
28513fccf   Milan Broz   dm crypt: simplif...
1137
  		goto bad;
ddd42edfd   Milan Broz   dm crypt: add asy...
1138
1139
  	}
  	cc->req = NULL;
a19b27ce3   Matthew Dobson   [PATCH] mempool: ...
1140
  	cc->page_pool = mempool_create_page_pool(MIN_POOL_PAGES, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1141
  	if (!cc->page_pool) {
72d948616   Alasdair G Kergon   [PATCH] dm: impro...
1142
  		ti->error = "Cannot allocate page mempool";
28513fccf   Milan Broz   dm crypt: simplif...
1143
  		goto bad;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1144
  	}
bb799ca02   Jens Axboe   bio: allow indivi...
1145
  	cc->bs = bioset_create(MIN_IOS, 0);
6a24c7184   Milan Broz   [PATCH] dm crypt:...
1146
1147
  	if (!cc->bs) {
  		ti->error = "Cannot allocate crypt bioset";
28513fccf   Milan Broz   dm crypt: simplif...
1148
  		goto bad;
6a24c7184   Milan Broz   [PATCH] dm crypt:...
1149
  	}
28513fccf   Milan Broz   dm crypt: simplif...
1150
  	ret = -EINVAL;
4ee218cd6   Andrew Morton   [PATCH] dm: remov...
1151
  	if (sscanf(argv[2], "%llu", &tmpll) != 1) {
72d948616   Alasdair G Kergon   [PATCH] dm: impro...
1152
  		ti->error = "Invalid iv_offset sector";
28513fccf   Milan Broz   dm crypt: simplif...
1153
  		goto bad;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1154
  	}
4ee218cd6   Andrew Morton   [PATCH] dm: remov...
1155
  	cc->iv_offset = tmpll;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1156

28513fccf   Milan Broz   dm crypt: simplif...
1157
1158
1159
1160
  	if (dm_get_device(ti, argv[3], dm_table_get_mode(ti->table), &cc->dev)) {
  		ti->error = "Device lookup failed";
  		goto bad;
  	}
4ee218cd6   Andrew Morton   [PATCH] dm: remov...
1161
  	if (sscanf(argv[4], "%llu", &tmpll) != 1) {
72d948616   Alasdair G Kergon   [PATCH] dm: impro...
1162
  		ti->error = "Invalid device sector";
28513fccf   Milan Broz   dm crypt: simplif...
1163
  		goto bad;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1164
  	}
4ee218cd6   Andrew Morton   [PATCH] dm: remov...
1165
  	cc->start = tmpll;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1166

28513fccf   Milan Broz   dm crypt: simplif...
1167
  	ret = -ENOMEM;
cabf08e4d   Milan Broz   dm crypt: add pos...
1168
1169
1170
  	cc->io_queue = create_singlethread_workqueue("kcryptd_io");
  	if (!cc->io_queue) {
  		ti->error = "Couldn't create kcryptd io queue";
28513fccf   Milan Broz   dm crypt: simplif...
1171
  		goto bad;
cabf08e4d   Milan Broz   dm crypt: add pos...
1172
1173
1174
1175
  	}
  
  	cc->crypt_queue = create_singlethread_workqueue("kcryptd");
  	if (!cc->crypt_queue) {
9934a8bea   Milan Broz   dm crypt: use per...
1176
  		ti->error = "Couldn't create kcryptd queue";
28513fccf   Milan Broz   dm crypt: simplif...
1177
  		goto bad;
9934a8bea   Milan Broz   dm crypt: use per...
1178
  	}
647c7db14   Mikulas Patocka   dm crypt: support...
1179
  	ti->num_flush_requests = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1180
  	return 0;
28513fccf   Milan Broz   dm crypt: simplif...
1181
1182
1183
  bad:
  	crypt_dtr(ti);
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1184
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1185
1186
1187
  static int crypt_map(struct dm_target *ti, struct bio *bio,
  		     union map_info *map_context)
  {
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
1188
  	struct dm_crypt_io *io;
647c7db14   Mikulas Patocka   dm crypt: support...
1189
1190
1191
1192
1193
1194
1195
  	struct crypt_config *cc;
  
  	if (unlikely(bio_empty_barrier(bio))) {
  		cc = ti->private;
  		bio->bi_bdev = cc->dev->bdev;
  		return DM_MAPIO_REMAPPED;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1196

b441a262e   Alasdair G Kergon   dm: use dm_target...
1197
  	io = crypt_io_alloc(ti, bio, dm_target_offset(ti, bio->bi_sector));
cabf08e4d   Milan Broz   dm crypt: add pos...
1198
1199
1200
1201
1202
  
  	if (bio_data_dir(io->base_bio) == READ)
  		kcryptd_queue_io(io);
  	else
  		kcryptd_queue_crypt(io);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1203

d2a7ad29a   Kiyoshi Ueda   [PATCH] dm: map a...
1204
  	return DM_MAPIO_SUBMITTED;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1205
1206
1207
1208
1209
  }
  
  static int crypt_status(struct dm_target *ti, status_type_t type,
  			char *result, unsigned int maxlen)
  {
5ebaee6d2   Milan Broz   dm crypt: simplif...
1210
  	struct crypt_config *cc = ti->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1211
1212
1213
1214
1215
1216
1217
1218
  	unsigned int sz = 0;
  
  	switch (type) {
  	case STATUSTYPE_INFO:
  		result[0] = '\0';
  		break;
  
  	case STATUSTYPE_TABLE:
5ebaee6d2   Milan Broz   dm crypt: simplif...
1219
1220
  		if (cc->cipher_mode)
  			DMEMIT("%s-%s ", cc->cipher, cc->cipher_mode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1221
  		else
5ebaee6d2   Milan Broz   dm crypt: simplif...
1222
  			DMEMIT("%s ", cc->cipher);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
  
  		if (cc->key_size > 0) {
  			if ((maxlen - sz) < ((cc->key_size << 1) + 1))
  				return -ENOMEM;
  
  			crypt_encode_key(result + sz, cc->key, cc->key_size);
  			sz += cc->key_size << 1;
  		} else {
  			if (sz >= maxlen)
  				return -ENOMEM;
  			result[sz++] = '-';
  		}
4ee218cd6   Andrew Morton   [PATCH] dm: remov...
1235
1236
  		DMEMIT(" %llu %s %llu", (unsigned long long)cc->iv_offset,
  				cc->dev->name, (unsigned long long)cc->start);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1237
1238
1239
1240
  		break;
  	}
  	return 0;
  }
e48d4bbf9   Milan Broz   [PATCH] dm crypt:...
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
  static void crypt_postsuspend(struct dm_target *ti)
  {
  	struct crypt_config *cc = ti->private;
  
  	set_bit(DM_CRYPT_SUSPENDED, &cc->flags);
  }
  
  static int crypt_preresume(struct dm_target *ti)
  {
  	struct crypt_config *cc = ti->private;
  
  	if (!test_bit(DM_CRYPT_KEY_VALID, &cc->flags)) {
  		DMERR("aborting resume - crypt key is not set.");
  		return -EAGAIN;
  	}
  
  	return 0;
  }
  
  static void crypt_resume(struct dm_target *ti)
  {
  	struct crypt_config *cc = ti->private;
  
  	clear_bit(DM_CRYPT_SUSPENDED, &cc->flags);
  }
  
  /* Message interface
   *	key set <key>
   *	key wipe
   */
  static int crypt_message(struct dm_target *ti, unsigned argc, char **argv)
  {
  	struct crypt_config *cc = ti->private;
542da3176   Milan Broz   dm crypt: make wi...
1274
  	int ret = -EINVAL;
e48d4bbf9   Milan Broz   [PATCH] dm crypt:...
1275
1276
1277
1278
1279
1280
1281
1282
1283
  
  	if (argc < 2)
  		goto error;
  
  	if (!strnicmp(argv[0], MESG_STR("key"))) {
  		if (!test_bit(DM_CRYPT_SUSPENDED, &cc->flags)) {
  			DMWARN("not suspended during key manipulation.");
  			return -EINVAL;
  		}
542da3176   Milan Broz   dm crypt: make wi...
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
  		if (argc == 3 && !strnicmp(argv[1], MESG_STR("set"))) {
  			ret = crypt_set_key(cc, argv[2]);
  			if (ret)
  				return ret;
  			if (cc->iv_gen_ops && cc->iv_gen_ops->init)
  				ret = cc->iv_gen_ops->init(cc);
  			return ret;
  		}
  		if (argc == 2 && !strnicmp(argv[1], MESG_STR("wipe"))) {
  			if (cc->iv_gen_ops && cc->iv_gen_ops->wipe) {
  				ret = cc->iv_gen_ops->wipe(cc);
  				if (ret)
  					return ret;
  			}
e48d4bbf9   Milan Broz   [PATCH] dm crypt:...
1298
  			return crypt_wipe_key(cc);
542da3176   Milan Broz   dm crypt: make wi...
1299
  		}
e48d4bbf9   Milan Broz   [PATCH] dm crypt:...
1300
1301
1302
1303
1304
1305
  	}
  
  error:
  	DMWARN("unrecognised message received.");
  	return -EINVAL;
  }
d41e26b90   Milan Broz   dm crypt: add merge
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
  static int crypt_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
  		       struct bio_vec *biovec, int max_size)
  {
  	struct crypt_config *cc = ti->private;
  	struct request_queue *q = bdev_get_queue(cc->dev->bdev);
  
  	if (!q->merge_bvec_fn)
  		return max_size;
  
  	bvm->bi_bdev = cc->dev->bdev;
b441a262e   Alasdair G Kergon   dm: use dm_target...
1316
  	bvm->bi_sector = cc->start + dm_target_offset(ti, bvm->bi_sector);
d41e26b90   Milan Broz   dm crypt: add merge
1317
1318
1319
  
  	return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
  }
af4874e03   Mike Snitzer   dm target:s intro...
1320
1321
1322
1323
  static int crypt_iterate_devices(struct dm_target *ti,
  				 iterate_devices_callout_fn fn, void *data)
  {
  	struct crypt_config *cc = ti->private;
5dea271b6   Mike Snitzer   dm table: pass co...
1324
  	return fn(ti, cc->dev, cc->start, ti->len, data);
af4874e03   Mike Snitzer   dm target:s intro...
1325
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1326
1327
  static struct target_type crypt_target = {
  	.name   = "crypt",
af4874e03   Mike Snitzer   dm target:s intro...
1328
  	.version = {1, 7, 0},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1329
1330
1331
1332
1333
  	.module = THIS_MODULE,
  	.ctr    = crypt_ctr,
  	.dtr    = crypt_dtr,
  	.map    = crypt_map,
  	.status = crypt_status,
e48d4bbf9   Milan Broz   [PATCH] dm crypt:...
1334
1335
1336
1337
  	.postsuspend = crypt_postsuspend,
  	.preresume = crypt_preresume,
  	.resume = crypt_resume,
  	.message = crypt_message,
d41e26b90   Milan Broz   dm crypt: add merge
1338
  	.merge  = crypt_merge,
af4874e03   Mike Snitzer   dm target:s intro...
1339
  	.iterate_devices = crypt_iterate_devices,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1340
1341
1342
1343
1344
  };
  
  static int __init dm_crypt_init(void)
  {
  	int r;
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
1345
  	_crypt_io_pool = KMEM_CACHE(dm_crypt_io, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1346
1347
  	if (!_crypt_io_pool)
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1348
1349
  	r = dm_register_target(&crypt_target);
  	if (r < 0) {
72d948616   Alasdair G Kergon   [PATCH] dm: impro...
1350
  		DMERR("register failed %d", r);
9934a8bea   Milan Broz   dm crypt: use per...
1351
  		kmem_cache_destroy(_crypt_io_pool);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1352
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1353
1354
1355
1356
1357
  	return r;
  }
  
  static void __exit dm_crypt_exit(void)
  {
10d3bd09a   Mikulas Patocka   dm: consolidate t...
1358
  	dm_unregister_target(&crypt_target);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1359
1360
1361
1362
1363
1364
1365
1366
1367
  	kmem_cache_destroy(_crypt_io_pool);
  }
  
  module_init(dm_crypt_init);
  module_exit(dm_crypt_exit);
  
  MODULE_AUTHOR("Christophe Saout <christophe@saout.de>");
  MODULE_DESCRIPTION(DM_NAME " target for transparent encryption / decryption");
  MODULE_LICENSE("GPL");