[PATCH v2 3/4] dm crypt: switch to EBOIV crypto API template

From: Gilad Ben-Yossef
Date: Wed Oct 28 2020 - 18:03:09 EST


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 <gilad@xxxxxxxxxxxxx>

---
drivers/md/dm-crypt.c | 61 ++++++++++++++-----------------------------
1 file changed, 19 insertions(+), 42 deletions(-)

diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 148960721254..86b7c7ee3225 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)
@@ -771,18 +742,14 @@ static int crypt_iv_elephant_ctr(struct crypt_config *cc, struct dm_target *ti,
const char *opts)
{
struct iv_elephant_private *elephant = &cc->iv_gen_private.elephant;
- int r;
+ int r = 0;

elephant->tfm = crypto_alloc_skcipher("ecb(aes)", 0, 0);
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;
}

@@ -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