diff options
-rw-r--r-- | fs/ecryptfs/crypto.c | 141 | ||||
-rw-r--r-- | fs/ecryptfs/ecryptfs_kernel.h | 3 |
2 files changed, 103 insertions, 41 deletions
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index d5c25db4398f..f71ec125290d 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c | |||
@@ -243,7 +243,7 @@ void ecryptfs_destroy_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat) | |||
243 | struct ecryptfs_key_sig *key_sig, *key_sig_tmp; | 243 | struct ecryptfs_key_sig *key_sig, *key_sig_tmp; |
244 | 244 | ||
245 | if (crypt_stat->tfm) | 245 | if (crypt_stat->tfm) |
246 | crypto_free_blkcipher(crypt_stat->tfm); | 246 | crypto_free_ablkcipher(crypt_stat->tfm); |
247 | if (crypt_stat->hash_tfm) | 247 | if (crypt_stat->hash_tfm) |
248 | crypto_free_hash(crypt_stat->hash_tfm); | 248 | crypto_free_hash(crypt_stat->hash_tfm); |
249 | list_for_each_entry_safe(key_sig, key_sig_tmp, | 249 | list_for_each_entry_safe(key_sig, key_sig_tmp, |
@@ -319,6 +319,22 @@ int virt_to_scatterlist(const void *addr, int size, struct scatterlist *sg, | |||
319 | return i; | 319 | return i; |
320 | } | 320 | } |
321 | 321 | ||
322 | struct extent_crypt_result { | ||
323 | struct completion completion; | ||
324 | int rc; | ||
325 | }; | ||
326 | |||
327 | static void extent_crypt_complete(struct crypto_async_request *req, int rc) | ||
328 | { | ||
329 | struct extent_crypt_result *ecr = req->data; | ||
330 | |||
331 | if (rc == -EINPROGRESS) | ||
332 | return; | ||
333 | |||
334 | ecr->rc = rc; | ||
335 | complete(&ecr->completion); | ||
336 | } | ||
337 | |||
322 | /** | 338 | /** |
323 | * encrypt_scatterlist | 339 | * encrypt_scatterlist |
324 | * @crypt_stat: Pointer to the crypt_stat struct to initialize. | 340 | * @crypt_stat: Pointer to the crypt_stat struct to initialize. |
@@ -334,11 +350,8 @@ static int encrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, | |||
334 | struct scatterlist *src_sg, int size, | 350 | struct scatterlist *src_sg, int size, |
335 | unsigned char *iv) | 351 | unsigned char *iv) |
336 | { | 352 | { |
337 | struct blkcipher_desc desc = { | 353 | struct ablkcipher_request *req = NULL; |
338 | .tfm = crypt_stat->tfm, | 354 | struct extent_crypt_result ecr; |
339 | .info = iv, | ||
340 | .flags = CRYPTO_TFM_REQ_MAY_SLEEP | ||
341 | }; | ||
342 | int rc = 0; | 355 | int rc = 0; |
343 | 356 | ||
344 | BUG_ON(!crypt_stat || !crypt_stat->tfm | 357 | BUG_ON(!crypt_stat || !crypt_stat->tfm |
@@ -349,24 +362,47 @@ static int encrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, | |||
349 | ecryptfs_dump_hex(crypt_stat->key, | 362 | ecryptfs_dump_hex(crypt_stat->key, |
350 | crypt_stat->key_size); | 363 | crypt_stat->key_size); |
351 | } | 364 | } |
352 | /* Consider doing this once, when the file is opened */ | 365 | |
366 | init_completion(&ecr.completion); | ||
367 | |||
353 | mutex_lock(&crypt_stat->cs_tfm_mutex); | 368 | mutex_lock(&crypt_stat->cs_tfm_mutex); |
354 | if (!(crypt_stat->flags & ECRYPTFS_KEY_SET)) { | 369 | req = ablkcipher_request_alloc(crypt_stat->tfm, GFP_NOFS); |
355 | rc = crypto_blkcipher_setkey(crypt_stat->tfm, crypt_stat->key, | 370 | if (!req) { |
356 | crypt_stat->key_size); | ||
357 | crypt_stat->flags |= ECRYPTFS_KEY_SET; | ||
358 | } | ||
359 | if (rc) { | ||
360 | ecryptfs_printk(KERN_ERR, "Error setting key; rc = [%d]\n", | ||
361 | rc); | ||
362 | mutex_unlock(&crypt_stat->cs_tfm_mutex); | 371 | mutex_unlock(&crypt_stat->cs_tfm_mutex); |
363 | rc = -EINVAL; | 372 | rc = -ENOMEM; |
364 | goto out; | 373 | goto out; |
365 | } | 374 | } |
366 | ecryptfs_printk(KERN_DEBUG, "Encrypting [%d] bytes.\n", size); | 375 | |
367 | crypto_blkcipher_encrypt_iv(&desc, dest_sg, src_sg, size); | 376 | ablkcipher_request_set_callback(req, |
377 | CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, | ||
378 | extent_crypt_complete, &ecr); | ||
379 | /* Consider doing this once, when the file is opened */ | ||
380 | if (!(crypt_stat->flags & ECRYPTFS_KEY_SET)) { | ||
381 | rc = crypto_ablkcipher_setkey(crypt_stat->tfm, crypt_stat->key, | ||
382 | crypt_stat->key_size); | ||
383 | if (rc) { | ||
384 | ecryptfs_printk(KERN_ERR, | ||
385 | "Error setting key; rc = [%d]\n", | ||
386 | rc); | ||
387 | mutex_unlock(&crypt_stat->cs_tfm_mutex); | ||
388 | rc = -EINVAL; | ||
389 | goto out; | ||
390 | } | ||
391 | crypt_stat->flags |= ECRYPTFS_KEY_SET; | ||
392 | } | ||
368 | mutex_unlock(&crypt_stat->cs_tfm_mutex); | 393 | mutex_unlock(&crypt_stat->cs_tfm_mutex); |
394 | ecryptfs_printk(KERN_DEBUG, "Encrypting [%d] bytes.\n", size); | ||
395 | ablkcipher_request_set_crypt(req, src_sg, dest_sg, size, iv); | ||
396 | rc = crypto_ablkcipher_encrypt(req); | ||
397 | if (rc == -EINPROGRESS || rc == -EBUSY) { | ||
398 | struct extent_crypt_result *ecr = req->base.data; | ||
399 | |||
400 | wait_for_completion(&ecr->completion); | ||
401 | rc = ecr->rc; | ||
402 | INIT_COMPLETION(ecr->completion); | ||
403 | } | ||
369 | out: | 404 | out: |
405 | ablkcipher_request_free(req); | ||
370 | return rc; | 406 | return rc; |
371 | } | 407 | } |
372 | 408 | ||
@@ -624,35 +660,61 @@ static int decrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, | |||
624 | struct scatterlist *src_sg, int size, | 660 | struct scatterlist *src_sg, int size, |
625 | unsigned char *iv) | 661 | unsigned char *iv) |
626 | { | 662 | { |
627 | struct blkcipher_desc desc = { | 663 | struct ablkcipher_request *req = NULL; |
628 | .tfm = crypt_stat->tfm, | 664 | struct extent_crypt_result ecr; |
629 | .info = iv, | ||
630 | .flags = CRYPTO_TFM_REQ_MAY_SLEEP | ||
631 | }; | ||
632 | int rc = 0; | 665 | int rc = 0; |
633 | 666 | ||
634 | /* Consider doing this once, when the file is opened */ | 667 | BUG_ON(!crypt_stat || !crypt_stat->tfm |
668 | || !(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED)); | ||
669 | if (unlikely(ecryptfs_verbosity > 0)) { | ||
670 | ecryptfs_printk(KERN_DEBUG, "Key size [%zd]; key:\n", | ||
671 | crypt_stat->key_size); | ||
672 | ecryptfs_dump_hex(crypt_stat->key, | ||
673 | crypt_stat->key_size); | ||
674 | } | ||
675 | |||
676 | init_completion(&ecr.completion); | ||
677 | |||
635 | mutex_lock(&crypt_stat->cs_tfm_mutex); | 678 | mutex_lock(&crypt_stat->cs_tfm_mutex); |
636 | rc = crypto_blkcipher_setkey(crypt_stat->tfm, crypt_stat->key, | 679 | req = ablkcipher_request_alloc(crypt_stat->tfm, GFP_NOFS); |
637 | crypt_stat->key_size); | 680 | if (!req) { |
638 | if (rc) { | ||
639 | ecryptfs_printk(KERN_ERR, "Error setting key; rc = [%d]\n", | ||
640 | rc); | ||
641 | mutex_unlock(&crypt_stat->cs_tfm_mutex); | 681 | mutex_unlock(&crypt_stat->cs_tfm_mutex); |
642 | rc = -EINVAL; | 682 | rc = -ENOMEM; |
643 | goto out; | 683 | goto out; |
644 | } | 684 | } |
645 | ecryptfs_printk(KERN_DEBUG, "Decrypting [%d] bytes.\n", size); | 685 | |
646 | rc = crypto_blkcipher_decrypt_iv(&desc, dest_sg, src_sg, size); | 686 | ablkcipher_request_set_callback(req, |
687 | CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, | ||
688 | extent_crypt_complete, &ecr); | ||
689 | /* Consider doing this once, when the file is opened */ | ||
690 | if (!(crypt_stat->flags & ECRYPTFS_KEY_SET)) { | ||
691 | rc = crypto_ablkcipher_setkey(crypt_stat->tfm, crypt_stat->key, | ||
692 | crypt_stat->key_size); | ||
693 | if (rc) { | ||
694 | ecryptfs_printk(KERN_ERR, | ||
695 | "Error setting key; rc = [%d]\n", | ||
696 | rc); | ||
697 | mutex_unlock(&crypt_stat->cs_tfm_mutex); | ||
698 | rc = -EINVAL; | ||
699 | goto out; | ||
700 | } | ||
701 | crypt_stat->flags |= ECRYPTFS_KEY_SET; | ||
702 | } | ||
647 | mutex_unlock(&crypt_stat->cs_tfm_mutex); | 703 | mutex_unlock(&crypt_stat->cs_tfm_mutex); |
648 | if (rc) { | 704 | ecryptfs_printk(KERN_DEBUG, "Decrypting [%d] bytes.\n", size); |
649 | ecryptfs_printk(KERN_ERR, "Error decrypting; rc = [%d]\n", | 705 | ablkcipher_request_set_crypt(req, src_sg, dest_sg, size, iv); |
650 | rc); | 706 | rc = crypto_ablkcipher_decrypt(req); |
651 | goto out; | 707 | if (rc == -EINPROGRESS || rc == -EBUSY) { |
708 | struct extent_crypt_result *ecr = req->base.data; | ||
709 | |||
710 | wait_for_completion(&ecr->completion); | ||
711 | rc = ecr->rc; | ||
712 | INIT_COMPLETION(ecr->completion); | ||
652 | } | 713 | } |
653 | rc = size; | ||
654 | out: | 714 | out: |
715 | ablkcipher_request_free(req); | ||
655 | return rc; | 716 | return rc; |
717 | |||
656 | } | 718 | } |
657 | 719 | ||
658 | /** | 720 | /** |
@@ -746,8 +808,7 @@ int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat) | |||
746 | crypt_stat->cipher, "cbc"); | 808 | crypt_stat->cipher, "cbc"); |
747 | if (rc) | 809 | if (rc) |
748 | goto out_unlock; | 810 | goto out_unlock; |
749 | crypt_stat->tfm = crypto_alloc_blkcipher(full_alg_name, 0, | 811 | crypt_stat->tfm = crypto_alloc_ablkcipher(full_alg_name, 0, 0); |
750 | CRYPTO_ALG_ASYNC); | ||
751 | kfree(full_alg_name); | 812 | kfree(full_alg_name); |
752 | if (IS_ERR(crypt_stat->tfm)) { | 813 | if (IS_ERR(crypt_stat->tfm)) { |
753 | rc = PTR_ERR(crypt_stat->tfm); | 814 | rc = PTR_ERR(crypt_stat->tfm); |
@@ -757,7 +818,7 @@ int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat) | |||
757 | crypt_stat->cipher); | 818 | crypt_stat->cipher); |
758 | goto out_unlock; | 819 | goto out_unlock; |
759 | } | 820 | } |
760 | crypto_blkcipher_set_flags(crypt_stat->tfm, CRYPTO_TFM_REQ_WEAK_KEY); | 821 | crypto_ablkcipher_set_flags(crypt_stat->tfm, CRYPTO_TFM_REQ_WEAK_KEY); |
761 | rc = 0; | 822 | rc = 0; |
762 | out_unlock: | 823 | out_unlock: |
763 | mutex_unlock(&crypt_stat->cs_tfm_mutex); | 824 | mutex_unlock(&crypt_stat->cs_tfm_mutex); |
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index dd299b389d4e..f622a733f7ad 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/nsproxy.h> | 38 | #include <linux/nsproxy.h> |
39 | #include <linux/backing-dev.h> | 39 | #include <linux/backing-dev.h> |
40 | #include <linux/ecryptfs.h> | 40 | #include <linux/ecryptfs.h> |
41 | #include <linux/crypto.h> | ||
41 | 42 | ||
42 | #define ECRYPTFS_DEFAULT_IV_BYTES 16 | 43 | #define ECRYPTFS_DEFAULT_IV_BYTES 16 |
43 | #define ECRYPTFS_DEFAULT_EXTENT_SIZE 4096 | 44 | #define ECRYPTFS_DEFAULT_EXTENT_SIZE 4096 |
@@ -233,7 +234,7 @@ struct ecryptfs_crypt_stat { | |||
233 | size_t extent_shift; | 234 | size_t extent_shift; |
234 | unsigned int extent_mask; | 235 | unsigned int extent_mask; |
235 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat; | 236 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat; |
236 | struct crypto_blkcipher *tfm; | 237 | struct crypto_ablkcipher *tfm; |
237 | struct crypto_hash *hash_tfm; /* Crypto context for generating | 238 | struct crypto_hash *hash_tfm; /* Crypto context for generating |
238 | * the initialization vectors */ | 239 | * the initialization vectors */ |
239 | unsigned char cipher[ECRYPTFS_MAX_CIPHER_NAME_SIZE]; | 240 | unsigned char cipher[ECRYPTFS_MAX_CIPHER_NAME_SIZE]; |