diff options
author | Milan Broz <mbroz@redhat.com> | 2008-02-07 21:11:14 -0500 |
---|---|---|
committer | Alasdair G Kergon <agk@redhat.com> | 2008-02-07 21:11:14 -0500 |
commit | 3a7f6c990ad04e6f576a159876c602d14d6f7fef (patch) | |
tree | dc120485f8801050fa640f22c1bdeae1429728e0 /drivers/md/dm-crypt.c | |
parent | 95497a960015c89c7c585d5fb953bc2816dba1e5 (diff) |
dm crypt: use async crypto
dm-crypt: Use crypto ablkcipher interface
Move encrypt/decrypt core to async crypto call.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Milan Broz <mbroz@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Diffstat (limited to 'drivers/md/dm-crypt.c')
-rw-r--r-- | drivers/md/dm-crypt.c | 131 |
1 files changed, 72 insertions, 59 deletions
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index c45bd0e59dcc..b04f98df94ea 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c | |||
@@ -123,7 +123,7 @@ struct crypt_config { | |||
123 | 123 | ||
124 | char cipher[CRYPTO_MAX_ALG_NAME]; | 124 | char cipher[CRYPTO_MAX_ALG_NAME]; |
125 | char chainmode[CRYPTO_MAX_ALG_NAME]; | 125 | char chainmode[CRYPTO_MAX_ALG_NAME]; |
126 | struct crypto_blkcipher *tfm; | 126 | struct crypto_ablkcipher *tfm; |
127 | unsigned long flags; | 127 | unsigned long flags; |
128 | unsigned int key_size; | 128 | unsigned int key_size; |
129 | u8 key[0]; | 129 | u8 key[0]; |
@@ -217,7 +217,7 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, | |||
217 | return PTR_ERR(essiv_tfm); | 217 | return PTR_ERR(essiv_tfm); |
218 | } | 218 | } |
219 | if (crypto_cipher_blocksize(essiv_tfm) != | 219 | if (crypto_cipher_blocksize(essiv_tfm) != |
220 | crypto_blkcipher_ivsize(cc->tfm)) { | 220 | crypto_ablkcipher_ivsize(cc->tfm)) { |
221 | ti->error = "Block size of ESSIV cipher does " | 221 | ti->error = "Block size of ESSIV cipher does " |
222 | "not match IV size of block cipher"; | 222 | "not match IV size of block cipher"; |
223 | crypto_free_cipher(essiv_tfm); | 223 | crypto_free_cipher(essiv_tfm); |
@@ -254,7 +254,7 @@ static int crypt_iv_essiv_gen(struct crypt_config *cc, u8 *iv, sector_t sector) | |||
254 | static int crypt_iv_benbi_ctr(struct crypt_config *cc, struct dm_target *ti, | 254 | static int crypt_iv_benbi_ctr(struct crypt_config *cc, struct dm_target *ti, |
255 | const char *opts) | 255 | const char *opts) |
256 | { | 256 | { |
257 | unsigned int bs = crypto_blkcipher_blocksize(cc->tfm); | 257 | unsigned bs = crypto_ablkcipher_blocksize(cc->tfm); |
258 | int log = ilog2(bs); | 258 | int log = ilog2(bs); |
259 | 259 | ||
260 | /* we need to calculate how far we must shift the sector count | 260 | /* we need to calculate how far we must shift the sector count |
@@ -318,38 +318,6 @@ static struct crypt_iv_operations crypt_iv_null_ops = { | |||
318 | .generator = crypt_iv_null_gen | 318 | .generator = crypt_iv_null_gen |
319 | }; | 319 | }; |
320 | 320 | ||
321 | static int | ||
322 | crypt_convert_scatterlist(struct crypt_config *cc, struct scatterlist *out, | ||
323 | struct scatterlist *in, unsigned int length, | ||
324 | int write, sector_t sector) | ||
325 | { | ||
326 | u8 iv[cc->iv_size] __attribute__ ((aligned(__alignof__(u64)))); | ||
327 | struct blkcipher_desc desc = { | ||
328 | .tfm = cc->tfm, | ||
329 | .info = iv, | ||
330 | .flags = CRYPTO_TFM_REQ_MAY_SLEEP, | ||
331 | }; | ||
332 | int r; | ||
333 | |||
334 | if (cc->iv_gen_ops) { | ||
335 | r = cc->iv_gen_ops->generator(cc, iv, sector); | ||
336 | if (r < 0) | ||
337 | return r; | ||
338 | |||
339 | if (write) | ||
340 | r = crypto_blkcipher_encrypt_iv(&desc, out, in, length); | ||
341 | else | ||
342 | r = crypto_blkcipher_decrypt_iv(&desc, out, in, length); | ||
343 | } else { | ||
344 | if (write) | ||
345 | r = crypto_blkcipher_encrypt(&desc, out, in, length); | ||
346 | else | ||
347 | r = crypto_blkcipher_decrypt(&desc, out, in, length); | ||
348 | } | ||
349 | |||
350 | return r; | ||
351 | } | ||
352 | |||
353 | static void crypt_convert_init(struct crypt_config *cc, | 321 | static void crypt_convert_init(struct crypt_config *cc, |
354 | struct convert_context *ctx, | 322 | struct convert_context *ctx, |
355 | struct bio *bio_out, struct bio *bio_in, | 323 | struct bio *bio_out, struct bio *bio_in, |
@@ -374,18 +342,25 @@ static void crypt_convert_init(struct crypt_config *cc, | |||
374 | } | 342 | } |
375 | 343 | ||
376 | static int crypt_convert_block(struct crypt_config *cc, | 344 | static int crypt_convert_block(struct crypt_config *cc, |
377 | struct convert_context *ctx) | 345 | struct convert_context *ctx, |
346 | struct ablkcipher_request *req) | ||
378 | { | 347 | { |
379 | struct bio_vec *bv_in = bio_iovec_idx(ctx->bio_in, ctx->idx_in); | 348 | struct bio_vec *bv_in = bio_iovec_idx(ctx->bio_in, ctx->idx_in); |
380 | struct bio_vec *bv_out = bio_iovec_idx(ctx->bio_out, ctx->idx_out); | 349 | struct bio_vec *bv_out = bio_iovec_idx(ctx->bio_out, ctx->idx_out); |
381 | struct dm_crypt_request dmreq; | 350 | struct dm_crypt_request *dmreq; |
351 | u8 *iv; | ||
352 | int r = 0; | ||
382 | 353 | ||
383 | sg_init_table(&dmreq.sg_in, 1); | 354 | dmreq = (struct dm_crypt_request *)((char *)req + cc->dmreq_start); |
384 | sg_set_page(&dmreq.sg_in, bv_in->bv_page, 1 << SECTOR_SHIFT, | 355 | iv = (u8 *)ALIGN((unsigned long)(dmreq + 1), |
356 | crypto_ablkcipher_alignmask(cc->tfm) + 1); | ||
357 | |||
358 | sg_init_table(&dmreq->sg_in, 1); | ||
359 | sg_set_page(&dmreq->sg_in, bv_in->bv_page, 1 << SECTOR_SHIFT, | ||
385 | bv_in->bv_offset + ctx->offset_in); | 360 | bv_in->bv_offset + ctx->offset_in); |
386 | 361 | ||
387 | sg_init_table(&dmreq.sg_out, 1); | 362 | sg_init_table(&dmreq->sg_out, 1); |
388 | sg_set_page(&dmreq.sg_out, bv_out->bv_page, 1 << SECTOR_SHIFT, | 363 | sg_set_page(&dmreq->sg_out, bv_out->bv_page, 1 << SECTOR_SHIFT, |
389 | bv_out->bv_offset + ctx->offset_out); | 364 | bv_out->bv_offset + ctx->offset_out); |
390 | 365 | ||
391 | ctx->offset_in += 1 << SECTOR_SHIFT; | 366 | ctx->offset_in += 1 << SECTOR_SHIFT; |
@@ -400,10 +375,21 @@ static int crypt_convert_block(struct crypt_config *cc, | |||
400 | ctx->idx_out++; | 375 | ctx->idx_out++; |
401 | } | 376 | } |
402 | 377 | ||
403 | return crypt_convert_scatterlist(cc, &dmreq.sg_out, &dmreq.sg_in, | 378 | if (cc->iv_gen_ops) { |
404 | dmreq.sg_in.length, | 379 | r = cc->iv_gen_ops->generator(cc, iv, ctx->sector); |
405 | bio_data_dir(ctx->bio_in) == WRITE, | 380 | if (r < 0) |
406 | ctx->sector); | 381 | return r; |
382 | } | ||
383 | |||
384 | ablkcipher_request_set_crypt(req, &dmreq->sg_in, &dmreq->sg_out, | ||
385 | 1 << SECTOR_SHIFT, iv); | ||
386 | |||
387 | if (bio_data_dir(ctx->bio_in) == WRITE) | ||
388 | r = crypto_ablkcipher_encrypt(req); | ||
389 | else | ||
390 | r = crypto_ablkcipher_decrypt(req); | ||
391 | |||
392 | return r; | ||
407 | } | 393 | } |
408 | 394 | ||
409 | static void kcryptd_async_done(struct crypto_async_request *async_req, | 395 | static void kcryptd_async_done(struct crypto_async_request *async_req, |
@@ -429,11 +415,27 @@ static int crypt_convert(struct crypt_config *cc, | |||
429 | 415 | ||
430 | while(ctx->idx_in < ctx->bio_in->bi_vcnt && | 416 | while(ctx->idx_in < ctx->bio_in->bi_vcnt && |
431 | ctx->idx_out < ctx->bio_out->bi_vcnt) { | 417 | ctx->idx_out < ctx->bio_out->bi_vcnt) { |
432 | r = crypt_convert_block(cc, ctx); | ||
433 | if (r < 0) | ||
434 | break; | ||
435 | 418 | ||
436 | ctx->sector++; | 419 | crypt_alloc_req(cc, ctx); |
420 | |||
421 | r = crypt_convert_block(cc, ctx, cc->req); | ||
422 | |||
423 | switch (r) { | ||
424 | case -EBUSY: | ||
425 | wait_for_completion(&ctx->restart); | ||
426 | INIT_COMPLETION(ctx->restart); | ||
427 | /* fall through*/ | ||
428 | case -EINPROGRESS: | ||
429 | atomic_inc(&ctx->pending); | ||
430 | cc->req = NULL; | ||
431 | r = 0; | ||
432 | /* fall through*/ | ||
433 | case 0: | ||
434 | ctx->sector++; | ||
435 | continue; | ||
436 | } | ||
437 | |||
438 | break; | ||
437 | } | 439 | } |
438 | 440 | ||
439 | /* | 441 | /* |
@@ -696,9 +698,12 @@ static void kcryptd_crypt_write_convert_loop(struct dm_crypt_io *io) | |||
696 | 698 | ||
697 | r = crypt_convert(cc, &io->ctx); | 699 | r = crypt_convert(cc, &io->ctx); |
698 | 700 | ||
699 | kcryptd_crypt_write_io_submit(io, r, 0); | 701 | if (r != -EINPROGRESS) { |
700 | if (unlikely(r < 0)) | 702 | kcryptd_crypt_write_io_submit(io, r, 0); |
701 | return; | 703 | if (unlikely(r < 0)) |
704 | return; | ||
705 | } else | ||
706 | atomic_inc(&io->pending); | ||
702 | 707 | ||
703 | /* out of memory -> run queues */ | 708 | /* out of memory -> run queues */ |
704 | if (unlikely(remaining)) | 709 | if (unlikely(remaining)) |
@@ -734,12 +739,17 @@ static void kcryptd_crypt_read_convert(struct dm_crypt_io *io) | |||
734 | struct crypt_config *cc = io->target->private; | 739 | struct crypt_config *cc = io->target->private; |
735 | int r = 0; | 740 | int r = 0; |
736 | 741 | ||
742 | atomic_inc(&io->pending); | ||
743 | |||
737 | crypt_convert_init(cc, &io->ctx, io->base_bio, io->base_bio, | 744 | crypt_convert_init(cc, &io->ctx, io->base_bio, io->base_bio, |
738 | io->sector); | 745 | io->sector); |
739 | 746 | ||
740 | r = crypt_convert(cc, &io->ctx); | 747 | r = crypt_convert(cc, &io->ctx); |
741 | 748 | ||
742 | kcryptd_crypt_read_done(io, r); | 749 | if (r != -EINPROGRESS) |
750 | kcryptd_crypt_read_done(io, r); | ||
751 | |||
752 | crypt_dec_pending(io); | ||
743 | } | 753 | } |
744 | 754 | ||
745 | static void kcryptd_async_done(struct crypto_async_request *async_req, | 755 | static void kcryptd_async_done(struct crypto_async_request *async_req, |
@@ -856,7 +866,7 @@ static int crypt_wipe_key(struct crypt_config *cc) | |||
856 | static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) | 866 | static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) |
857 | { | 867 | { |
858 | struct crypt_config *cc; | 868 | struct crypt_config *cc; |
859 | struct crypto_blkcipher *tfm; | 869 | struct crypto_ablkcipher *tfm; |
860 | char *tmp; | 870 | char *tmp; |
861 | char *cipher; | 871 | char *cipher; |
862 | char *chainmode; | 872 | char *chainmode; |
@@ -910,7 +920,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
910 | goto bad_cipher; | 920 | goto bad_cipher; |
911 | } | 921 | } |
912 | 922 | ||
913 | tfm = crypto_alloc_blkcipher(cc->cipher, 0, CRYPTO_ALG_ASYNC); | 923 | tfm = crypto_alloc_ablkcipher(cc->cipher, 0, 0); |
914 | if (IS_ERR(tfm)) { | 924 | if (IS_ERR(tfm)) { |
915 | ti->error = "Error allocating crypto tfm"; | 925 | ti->error = "Error allocating crypto tfm"; |
916 | goto bad_cipher; | 926 | goto bad_cipher; |
@@ -944,7 +954,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
944 | cc->iv_gen_ops->ctr(cc, ti, ivopts) < 0) | 954 | cc->iv_gen_ops->ctr(cc, ti, ivopts) < 0) |
945 | goto bad_ivmode; | 955 | goto bad_ivmode; |
946 | 956 | ||
947 | cc->iv_size = crypto_blkcipher_ivsize(tfm); | 957 | cc->iv_size = crypto_ablkcipher_ivsize(tfm); |
948 | if (cc->iv_size) | 958 | if (cc->iv_size) |
949 | /* at least a 64 bit sector number should fit in our buffer */ | 959 | /* at least a 64 bit sector number should fit in our buffer */ |
950 | cc->iv_size = max(cc->iv_size, | 960 | cc->iv_size = max(cc->iv_size, |
@@ -965,7 +975,10 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
965 | } | 975 | } |
966 | 976 | ||
967 | cc->dmreq_start = sizeof(struct ablkcipher_request); | 977 | cc->dmreq_start = sizeof(struct ablkcipher_request); |
978 | cc->dmreq_start += crypto_ablkcipher_reqsize(tfm); | ||
968 | cc->dmreq_start = ALIGN(cc->dmreq_start, crypto_tfm_ctx_alignment()); | 979 | cc->dmreq_start = ALIGN(cc->dmreq_start, crypto_tfm_ctx_alignment()); |
980 | cc->dmreq_start += crypto_ablkcipher_alignmask(tfm) & | ||
981 | ~(crypto_tfm_ctx_alignment() - 1); | ||
969 | 982 | ||
970 | cc->req_pool = mempool_create_kmalloc_pool(MIN_IOS, cc->dmreq_start + | 983 | cc->req_pool = mempool_create_kmalloc_pool(MIN_IOS, cc->dmreq_start + |
971 | sizeof(struct dm_crypt_request) + cc->iv_size); | 984 | sizeof(struct dm_crypt_request) + cc->iv_size); |
@@ -987,7 +1000,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
987 | goto bad_bs; | 1000 | goto bad_bs; |
988 | } | 1001 | } |
989 | 1002 | ||
990 | if (crypto_blkcipher_setkey(tfm, cc->key, key_size) < 0) { | 1003 | if (crypto_ablkcipher_setkey(tfm, cc->key, key_size) < 0) { |
991 | ti->error = "Error setting key"; | 1004 | ti->error = "Error setting key"; |
992 | goto bad_device; | 1005 | goto bad_device; |
993 | } | 1006 | } |
@@ -1055,7 +1068,7 @@ bad_slab_pool: | |||
1055 | if (cc->iv_gen_ops && cc->iv_gen_ops->dtr) | 1068 | if (cc->iv_gen_ops && cc->iv_gen_ops->dtr) |
1056 | cc->iv_gen_ops->dtr(cc); | 1069 | cc->iv_gen_ops->dtr(cc); |
1057 | bad_ivmode: | 1070 | bad_ivmode: |
1058 | crypto_free_blkcipher(tfm); | 1071 | crypto_free_ablkcipher(tfm); |
1059 | bad_cipher: | 1072 | bad_cipher: |
1060 | /* Must zero key material before freeing */ | 1073 | /* Must zero key material before freeing */ |
1061 | memset(cc, 0, sizeof(*cc) + cc->key_size * sizeof(u8)); | 1074 | memset(cc, 0, sizeof(*cc) + cc->key_size * sizeof(u8)); |
@@ -1081,7 +1094,7 @@ static void crypt_dtr(struct dm_target *ti) | |||
1081 | kfree(cc->iv_mode); | 1094 | kfree(cc->iv_mode); |
1082 | if (cc->iv_gen_ops && cc->iv_gen_ops->dtr) | 1095 | if (cc->iv_gen_ops && cc->iv_gen_ops->dtr) |
1083 | cc->iv_gen_ops->dtr(cc); | 1096 | cc->iv_gen_ops->dtr(cc); |
1084 | crypto_free_blkcipher(cc->tfm); | 1097 | crypto_free_ablkcipher(cc->tfm); |
1085 | dm_put_device(ti, cc->dev); | 1098 | dm_put_device(ti, cc->dev); |
1086 | 1099 | ||
1087 | /* Must zero key material before freeing */ | 1100 | /* Must zero key material before freeing */ |