diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/md/dm-crypt.c | 48 |
1 files changed, 35 insertions, 13 deletions
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index dc4403bcc6a0..e0ebe685be6a 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c | |||
@@ -64,6 +64,7 @@ struct dm_crypt_request { | |||
64 | struct convert_context *ctx; | 64 | struct convert_context *ctx; |
65 | struct scatterlist sg_in; | 65 | struct scatterlist sg_in; |
66 | struct scatterlist sg_out; | 66 | struct scatterlist sg_out; |
67 | sector_t iv_sector; | ||
67 | }; | 68 | }; |
68 | 69 | ||
69 | struct crypt_config; | 70 | struct crypt_config; |
@@ -74,7 +75,10 @@ struct crypt_iv_operations { | |||
74 | void (*dtr)(struct crypt_config *cc); | 75 | void (*dtr)(struct crypt_config *cc); |
75 | int (*init)(struct crypt_config *cc); | 76 | int (*init)(struct crypt_config *cc); |
76 | int (*wipe)(struct crypt_config *cc); | 77 | int (*wipe)(struct crypt_config *cc); |
77 | int (*generator)(struct crypt_config *cc, u8 *iv, sector_t sector); | 78 | int (*generator)(struct crypt_config *cc, u8 *iv, |
79 | struct dm_crypt_request *dmreq); | ||
80 | int (*post)(struct crypt_config *cc, u8 *iv, | ||
81 | struct dm_crypt_request *dmreq); | ||
78 | }; | 82 | }; |
79 | 83 | ||
80 | struct iv_essiv_private { | 84 | struct iv_essiv_private { |
@@ -168,6 +172,7 @@ static struct kmem_cache *_crypt_io_pool; | |||
168 | 172 | ||
169 | static void clone_init(struct dm_crypt_io *, struct bio *); | 173 | static void clone_init(struct dm_crypt_io *, struct bio *); |
170 | static void kcryptd_queue_crypt(struct dm_crypt_io *io); | 174 | static void kcryptd_queue_crypt(struct dm_crypt_io *io); |
175 | static u8 *iv_of_dmreq(struct crypt_config *cc, struct dm_crypt_request *dmreq); | ||
171 | 176 | ||
172 | static struct crypt_cpu *this_crypt_config(struct crypt_config *cc) | 177 | static struct crypt_cpu *this_crypt_config(struct crypt_config *cc) |
173 | { | 178 | { |
@@ -205,19 +210,20 @@ static struct crypto_ablkcipher *any_tfm(struct crypt_config *cc) | |||
205 | * http://article.gmane.org/gmane.linux.kernel.device-mapper.dm-crypt/454 | 210 | * http://article.gmane.org/gmane.linux.kernel.device-mapper.dm-crypt/454 |
206 | */ | 211 | */ |
207 | 212 | ||
208 | static int crypt_iv_plain_gen(struct crypt_config *cc, u8 *iv, sector_t sector) | 213 | static int crypt_iv_plain_gen(struct crypt_config *cc, u8 *iv, |
214 | struct dm_crypt_request *dmreq) | ||
209 | { | 215 | { |
210 | memset(iv, 0, cc->iv_size); | 216 | memset(iv, 0, cc->iv_size); |
211 | *(u32 *)iv = cpu_to_le32(sector & 0xffffffff); | 217 | *(u32 *)iv = cpu_to_le32(dmreq->iv_sector & 0xffffffff); |
212 | 218 | ||
213 | return 0; | 219 | return 0; |
214 | } | 220 | } |
215 | 221 | ||
216 | static int crypt_iv_plain64_gen(struct crypt_config *cc, u8 *iv, | 222 | static int crypt_iv_plain64_gen(struct crypt_config *cc, u8 *iv, |
217 | sector_t sector) | 223 | struct dm_crypt_request *dmreq) |
218 | { | 224 | { |
219 | memset(iv, 0, cc->iv_size); | 225 | memset(iv, 0, cc->iv_size); |
220 | *(u64 *)iv = cpu_to_le64(sector); | 226 | *(u64 *)iv = cpu_to_le64(dmreq->iv_sector); |
221 | 227 | ||
222 | return 0; | 228 | return 0; |
223 | } | 229 | } |
@@ -378,12 +384,13 @@ bad: | |||
378 | return err; | 384 | return err; |
379 | } | 385 | } |
380 | 386 | ||
381 | static int crypt_iv_essiv_gen(struct crypt_config *cc, u8 *iv, sector_t sector) | 387 | static int crypt_iv_essiv_gen(struct crypt_config *cc, u8 *iv, |
388 | struct dm_crypt_request *dmreq) | ||
382 | { | 389 | { |
383 | struct crypto_cipher *essiv_tfm = this_crypt_config(cc)->iv_private; | 390 | struct crypto_cipher *essiv_tfm = this_crypt_config(cc)->iv_private; |
384 | 391 | ||
385 | memset(iv, 0, cc->iv_size); | 392 | memset(iv, 0, cc->iv_size); |
386 | *(u64 *)iv = cpu_to_le64(sector); | 393 | *(u64 *)iv = cpu_to_le64(dmreq->iv_sector); |
387 | crypto_cipher_encrypt_one(essiv_tfm, iv, iv); | 394 | crypto_cipher_encrypt_one(essiv_tfm, iv, iv); |
388 | 395 | ||
389 | return 0; | 396 | return 0; |
@@ -417,19 +424,21 @@ static void crypt_iv_benbi_dtr(struct crypt_config *cc) | |||
417 | { | 424 | { |
418 | } | 425 | } |
419 | 426 | ||
420 | static int crypt_iv_benbi_gen(struct crypt_config *cc, u8 *iv, sector_t sector) | 427 | static int crypt_iv_benbi_gen(struct crypt_config *cc, u8 *iv, |
428 | struct dm_crypt_request *dmreq) | ||
421 | { | 429 | { |
422 | __be64 val; | 430 | __be64 val; |
423 | 431 | ||
424 | memset(iv, 0, cc->iv_size - sizeof(u64)); /* rest is cleared below */ | 432 | memset(iv, 0, cc->iv_size - sizeof(u64)); /* rest is cleared below */ |
425 | 433 | ||
426 | val = cpu_to_be64(((u64)sector << cc->iv_gen_private.benbi.shift) + 1); | 434 | val = cpu_to_be64(((u64)dmreq->iv_sector << cc->iv_gen_private.benbi.shift) + 1); |
427 | put_unaligned(val, (__be64 *)(iv + cc->iv_size - sizeof(u64))); | 435 | put_unaligned(val, (__be64 *)(iv + cc->iv_size - sizeof(u64))); |
428 | 436 | ||
429 | return 0; | 437 | return 0; |
430 | } | 438 | } |
431 | 439 | ||
432 | static int crypt_iv_null_gen(struct crypt_config *cc, u8 *iv, sector_t sector) | 440 | static int crypt_iv_null_gen(struct crypt_config *cc, u8 *iv, |
441 | struct dm_crypt_request *dmreq) | ||
433 | { | 442 | { |
434 | memset(iv, 0, cc->iv_size); | 443 | memset(iv, 0, cc->iv_size); |
435 | 444 | ||
@@ -489,6 +498,13 @@ static struct ablkcipher_request *req_of_dmreq(struct crypt_config *cc, | |||
489 | return (struct ablkcipher_request *)((char *)dmreq - cc->dmreq_start); | 498 | return (struct ablkcipher_request *)((char *)dmreq - cc->dmreq_start); |
490 | } | 499 | } |
491 | 500 | ||
501 | static u8 *iv_of_dmreq(struct crypt_config *cc, | ||
502 | struct dm_crypt_request *dmreq) | ||
503 | { | ||
504 | return (u8 *)ALIGN((unsigned long)(dmreq + 1), | ||
505 | crypto_ablkcipher_alignmask(any_tfm(cc)) + 1); | ||
506 | } | ||
507 | |||
492 | static int crypt_convert_block(struct crypt_config *cc, | 508 | static int crypt_convert_block(struct crypt_config *cc, |
493 | struct convert_context *ctx, | 509 | struct convert_context *ctx, |
494 | struct ablkcipher_request *req) | 510 | struct ablkcipher_request *req) |
@@ -500,9 +516,9 @@ static int crypt_convert_block(struct crypt_config *cc, | |||
500 | int r = 0; | 516 | int r = 0; |
501 | 517 | ||
502 | dmreq = dmreq_of_req(cc, req); | 518 | dmreq = dmreq_of_req(cc, req); |
503 | iv = (u8 *)ALIGN((unsigned long)(dmreq + 1), | 519 | iv = iv_of_dmreq(cc, dmreq); |
504 | crypto_ablkcipher_alignmask(any_tfm(cc)) + 1); | ||
505 | 520 | ||
521 | dmreq->iv_sector = ctx->sector; | ||
506 | dmreq->ctx = ctx; | 522 | dmreq->ctx = ctx; |
507 | sg_init_table(&dmreq->sg_in, 1); | 523 | sg_init_table(&dmreq->sg_in, 1); |
508 | sg_set_page(&dmreq->sg_in, bv_in->bv_page, 1 << SECTOR_SHIFT, | 524 | sg_set_page(&dmreq->sg_in, bv_in->bv_page, 1 << SECTOR_SHIFT, |
@@ -525,7 +541,7 @@ static int crypt_convert_block(struct crypt_config *cc, | |||
525 | } | 541 | } |
526 | 542 | ||
527 | if (cc->iv_gen_ops) { | 543 | if (cc->iv_gen_ops) { |
528 | r = cc->iv_gen_ops->generator(cc, iv, ctx->sector); | 544 | r = cc->iv_gen_ops->generator(cc, iv, dmreq); |
529 | if (r < 0) | 545 | if (r < 0) |
530 | return r; | 546 | return r; |
531 | } | 547 | } |
@@ -538,6 +554,9 @@ static int crypt_convert_block(struct crypt_config *cc, | |||
538 | else | 554 | else |
539 | r = crypto_ablkcipher_decrypt(req); | 555 | r = crypto_ablkcipher_decrypt(req); |
540 | 556 | ||
557 | if (!r && cc->iv_gen_ops && cc->iv_gen_ops->post) | ||
558 | r = cc->iv_gen_ops->post(cc, iv, dmreq); | ||
559 | |||
541 | return r; | 560 | return r; |
542 | } | 561 | } |
543 | 562 | ||
@@ -1005,6 +1024,9 @@ static void kcryptd_async_done(struct crypto_async_request *async_req, | |||
1005 | return; | 1024 | return; |
1006 | } | 1025 | } |
1007 | 1026 | ||
1027 | if (!error && cc->iv_gen_ops && cc->iv_gen_ops->post) | ||
1028 | error = cc->iv_gen_ops->post(cc, iv_of_dmreq(cc, dmreq), dmreq); | ||
1029 | |||
1008 | mempool_free(req_of_dmreq(cc, dmreq), cc->req_pool); | 1030 | mempool_free(req_of_dmreq(cc, dmreq), cc->req_pool); |
1009 | 1031 | ||
1010 | if (!atomic_dec_and_test(&ctx->pending)) | 1032 | if (!atomic_dec_and_test(&ctx->pending)) |