Replace the explicit EBOIV handling in the dm-crypt driver with calls
into the crypto API, which now possesses the capability to perform
this processing within the crypto subsystem.

Signed-off-by: Gilad Ben-Yossef <gi...@benyossef.com>

---
 drivers/md/Kconfig    |  1 +
 drivers/md/dm-crypt.c | 61 ++++++++++++++-----------------------------
 2 files changed, 20 insertions(+), 42 deletions(-)

diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig
index 30ba3573626c..ca6e56a72281 100644
--- a/drivers/md/Kconfig
+++ b/drivers/md/Kconfig
@@ -273,6 +273,7 @@ config DM_CRYPT
        select CRYPTO
        select CRYPTO_CBC
        select CRYPTO_ESSIV
+       select CRYPTO_EBOIV
        help
          This device-mapper target allows you to create a device that
          transparently encrypts the data on it. You'll need to activate
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 148960721254..cad8f4e3f5d9 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -716,47 +716,18 @@ static int crypt_iv_random_gen(struct crypt_config *cc, 
u8 *iv,
        return 0;
 }
 
-static int crypt_iv_eboiv_ctr(struct crypt_config *cc, struct dm_target *ti,
-                           const char *opts)
-{
-       if (crypt_integrity_aead(cc)) {
-               ti->error = "AEAD transforms not supported for EBOIV";
-               return -EINVAL;
-       }
-
-       if (crypto_skcipher_blocksize(any_tfm(cc)) != cc->iv_size) {
-               ti->error = "Block size of EBOIV cipher does "
-                           "not match IV size of block cipher";
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
 static int crypt_iv_eboiv_gen(struct crypt_config *cc, u8 *iv,
                            struct dm_crypt_request *dmreq)
 {
-       u8 buf[MAX_CIPHER_BLOCKSIZE] __aligned(__alignof__(__le64));
-       struct skcipher_request *req;
-       struct scatterlist src, dst;
-       struct crypto_wait wait;
-       int err;
-
-       req = skcipher_request_alloc(any_tfm(cc), GFP_NOIO);
-       if (!req)
-               return -ENOMEM;
-
-       memset(buf, 0, cc->iv_size);
-       *(__le64 *)buf = cpu_to_le64(dmreq->iv_sector * cc->sector_size);
 
-       sg_init_one(&src, page_address(ZERO_PAGE(0)), cc->iv_size);
-       sg_init_one(&dst, iv, cc->iv_size);
-       skcipher_request_set_crypt(req, &src, &dst, cc->iv_size, buf);
-       skcipher_request_set_callback(req, 0, crypto_req_done, &wait);
-       err = crypto_wait_req(crypto_skcipher_encrypt(req), &wait);
-       skcipher_request_free(req);
+       /*
+        * ESSIV encryption of the IV is handled by the crypto API,
+        * so compute and pass the sector offset here.
+        */
+       memset(iv, 0, cc->iv_size);
+       *(__le64 *)iv = cpu_to_le64(dmreq->iv_sector * cc->sector_size);
 
-       return err;
+       return 0;
 }
 
 static void crypt_iv_elephant_dtr(struct crypt_config *cc)
@@ -777,13 +748,9 @@ static int crypt_iv_elephant_ctr(struct crypt_config *cc, 
struct dm_target *ti,
        if (IS_ERR(elephant->tfm)) {
                r = PTR_ERR(elephant->tfm);
                elephant->tfm = NULL;
-               return r;
        }
 
-       r = crypt_iv_eboiv_ctr(cc, ti, NULL);
-       if (r)
-               crypt_iv_elephant_dtr(cc);
-       return r;
+       return 0;
 }
 
 static void diffuser_disk_to_cpu(u32 *d, size_t n)
@@ -1092,7 +1059,6 @@ static struct crypt_iv_operations crypt_iv_random_ops = {
 };
 
 static struct crypt_iv_operations crypt_iv_eboiv_ops = {
-       .ctr       = crypt_iv_eboiv_ctr,
        .generator = crypt_iv_eboiv_gen
 };
 
@@ -2739,6 +2705,15 @@ static int crypt_ctr_cipher_new(struct dm_target *ti, 
char *cipher_in, char *key
                cipher_api = buf;
        }
 
+       if (*ivmode && (!strcmp(*ivmode, "eboiv") || !strcmp(*ivmode, 
"elephant"))) {
+               ret = snprintf(buf, CRYPTO_MAX_ALG_NAME, "eboiv(%s)", 
cipher_api);
+               if (ret < 0 || ret >= CRYPTO_MAX_ALG_NAME) {
+                       ti->error = "Cannot allocate cipher string";
+                       return -ENOMEM;
+               }
+               cipher_api = buf;
+       }
+
        cc->key_parts = cc->tfms_count;
 
        /* Allocate cipher */
@@ -2817,6 +2792,8 @@ static int crypt_ctr_cipher_old(struct dm_target *ti, 
char *cipher_in, char *key
                }
                ret = snprintf(cipher_api, CRYPTO_MAX_ALG_NAME,
                               "essiv(%s(%s),%s)", chainmode, cipher, *ivopts);
+       } else if (*ivmode && (!strcmp(*ivmode, "eboiv") || !strcmp(*ivmode, 
"elephant"))) {
+               ret = snprintf(cipher_api, CRYPTO_MAX_ALG_NAME, 
"eboiv(%s(%s))", chainmode, cipher);
        } else {
                ret = snprintf(cipher_api, CRYPTO_MAX_ALG_NAME,
                               "%s(%s)", chainmode, cipher);
-- 
2.28.0

Reply via email to