diff mbox series

[v2,1/3] dm-inlinecrypt: Add inline encryption support

Message ID 20240916085741.1636554-2-quic_mdalam@quicinc.com (mailing list archive)
State New
Headers show
Series Add inline encryption support | expand

Commit Message

Md Sadre Alam Sept. 16, 2024, 8:57 a.m. UTC
QCOM SDCC controller supports Inline Crypto Engine
This driver will enables inline encryption/decryption
for ICE. The algorithm supported by ICE are XTS(AES)
and CBC(AES).

Signed-off-by: Md Sadre Alam <quic_mdalam@quicinc.com>
---

Change in [v2]

* Added dm-inlinecrypt driver support

* squash the patch blk-crypto: Add additional algo modes for Inline
  encryption and md: dm-crypt: Add additional algo modes for inline
  encryption and added in this

Change in [v1]

* This patch was not included in [v1]

 block/blk-crypto.c           |  21 +++
 drivers/md/Kconfig           |   8 +
 drivers/md/Makefile          |   1 +
 drivers/md/dm-inline-crypt.c | 316 +++++++++++++++++++++++++++++++++++
 include/linux/blk-crypto.h   |   3 +
 5 files changed, 349 insertions(+)
 create mode 100644 drivers/md/dm-inline-crypt.c

Comments

kernel test robot Sept. 17, 2024, 5:05 a.m. UTC | #1
Hi Md,

kernel test robot noticed the following build errors:

[auto build test ERROR on device-mapper-dm/for-next]
[also build test ERROR on axboe-block/for-next linus/master song-md/md-next v6.11 next-20240916]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Md-Sadre-Alam/dm-inlinecrypt-Add-inline-encryption-support/20240916-170452
base:   https://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm.git for-next
patch link:    https://lore.kernel.org/r/20240916085741.1636554-2-quic_mdalam%40quicinc.com
patch subject: [PATCH v2 1/3] dm-inlinecrypt: Add inline encryption support
config: openrisc-randconfig-r062-20240917 (https://download.01.org/0day-ci/archive/20240917/202409171209.aEtxsPez-lkp@intel.com/config)
compiler: or1k-linux-gcc (GCC) 14.1.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240917/202409171209.aEtxsPez-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202409171209.aEtxsPez-lkp@intel.com/

All errors (new ones prefixed by >>):

   drivers/md/dm-inline-crypt.c: In function 'crypt_prepare_inline_crypt_key':
>> drivers/md/dm-inline-crypt.c:81:15: error: implicit declaration of function 'blk_crypto_init_key' [-Wimplicit-function-declaration]
      81 |         ret = blk_crypto_init_key(cc->blk_key, cc->key, cc->crypto_mode,
         |               ^~~~~~~~~~~~~~~~~~~
>> drivers/md/dm-inline-crypt.c:88:15: error: implicit declaration of function 'blk_crypto_start_using_key' [-Wimplicit-function-declaration]
      88 |         ret = blk_crypto_start_using_key(cc->dev->bdev, cc->blk_key);
         |               ^~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/md/dm-inline-crypt.c: In function 'crypt_destroy_inline_crypt_key':
>> drivers/md/dm-inline-crypt.c:104:17: error: implicit declaration of function 'blk_crypto_evict_key'; did you mean 'blk_crypto_register'? [-Wimplicit-function-declaration]
     104 |                 blk_crypto_evict_key(cc->dev->bdev, cc->blk_key);
         |                 ^~~~~~~~~~~~~~~~~~~~
         |                 blk_crypto_register
   drivers/md/dm-inline-crypt.c: In function 'crypt_inline_encrypt_submit':
>> drivers/md/dm-inline-crypt.c:121:17: error: implicit declaration of function 'bio_crypt_set_ctx' [-Wimplicit-function-declaration]
     121 |                 bio_crypt_set_ctx(bio, cc->blk_key, dun, GFP_KERNEL);
         |                 ^~~~~~~~~~~~~~~~~


vim +/blk_crypto_init_key +81 drivers/md/dm-inline-crypt.c

    72	
    73	static int crypt_prepare_inline_crypt_key(struct inlinecrypt_config *cc)
    74	{
    75		int ret;
    76	
    77		cc->blk_key = kzalloc(sizeof(*cc->blk_key), GFP_KERNEL);
    78		if (!cc->blk_key)
    79			return -ENOMEM;
    80	
  > 81		ret = blk_crypto_init_key(cc->blk_key, cc->key, cc->crypto_mode,
    82					  cc->iv_size, cc->sector_size);
    83		if (ret) {
    84			DMERR("Failed to init inline encryption key");
    85			goto bad_key;
    86		}
    87	
  > 88		ret = blk_crypto_start_using_key(cc->dev->bdev, cc->blk_key);
    89		if (ret) {
    90			DMERR("Failed to use inline encryption key");
    91			goto bad_key;
    92		}
    93	
    94		return 0;
    95	bad_key:
    96		kfree_sensitive(cc->blk_key);
    97		cc->blk_key = NULL;
    98		return ret;
    99	}
   100	
   101	static void crypt_destroy_inline_crypt_key(struct inlinecrypt_config *cc)
   102	{
   103		if (cc->blk_key) {
 > 104			blk_crypto_evict_key(cc->dev->bdev, cc->blk_key);
   105			kfree_sensitive(cc->blk_key);
   106			cc->blk_key = NULL;
   107		}
   108	}
   109	
   110	static void crypt_inline_encrypt_submit(struct dm_target *ti, struct bio *bio)
   111	{
   112		struct inlinecrypt_config *cc = ti->private;
   113		u64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE];
   114	
   115		bio_set_dev(bio, cc->dev->bdev);
   116		if (bio_sectors(bio)) {
   117			memset(dun, 0, BLK_CRYPTO_MAX_IV_SIZE);
   118			bio->bi_iter.bi_sector = cc->start +
   119				dm_target_offset(ti, bio->bi_iter.bi_sector);
   120			dun[0] = le64_to_cpu(bio->bi_iter.bi_sector + cc->iv_offset);
 > 121			bio_crypt_set_ctx(bio, cc->blk_key, dun, GFP_KERNEL);
   122		}
   123	
   124		submit_bio_noacct(bio);
   125	}
   126
kernel test robot Sept. 17, 2024, 6:38 a.m. UTC | #2
Hi Md,

kernel test robot noticed the following build warnings:

[auto build test WARNING on device-mapper-dm/for-next]
[also build test WARNING on axboe-block/for-next linus/master song-md/md-next v6.11 next-20240916]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Md-Sadre-Alam/dm-inlinecrypt-Add-inline-encryption-support/20240916-170452
base:   https://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm.git for-next
patch link:    https://lore.kernel.org/r/20240916085741.1636554-2-quic_mdalam%40quicinc.com
patch subject: [PATCH v2 1/3] dm-inlinecrypt: Add inline encryption support
config: x86_64-allyesconfig (https://download.01.org/0day-ci/archive/20240917/202409171440.qx2iOkY3-lkp@intel.com/config)
compiler: clang version 18.1.8 (https://github.com/llvm/llvm-project 3b5b5c1ec4a3095ab096dd780e84d7ab81f3d7ff)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240917/202409171440.qx2iOkY3-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202409171440.qx2iOkY3-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> drivers/md/dm-inline-crypt.c:198:6: warning: variable 'ret' is used uninitialized whenever 'if' condition is true [-Wsometimes-uninitialized]
     198 |         if ((sscanf(argv[2], "%llu%c", &tmpll, &dummy) != 1) ||
         |             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     199 |             (tmpll & ((cc->sector_size >> SECTOR_SHIFT) - 1))) {
         |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/md/dm-inline-crypt.c:250:9: note: uninitialized use occurs here
     250 |         return ret;
         |                ^~~
   drivers/md/dm-inline-crypt.c:198:2: note: remove the 'if' if its condition is always false
     198 |         if ((sscanf(argv[2], "%llu%c", &tmpll, &dummy) != 1) ||
         |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     199 |             (tmpll & ((cc->sector_size >> SECTOR_SHIFT) - 1))) {
         |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     200 |                 ti->error = "Invalid iv_offset sector";
         |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     201 |                 goto bad;
         |                 ~~~~~~~~~
     202 |         }
         |         ~
>> drivers/md/dm-inline-crypt.c:198:6: warning: variable 'ret' is used uninitialized whenever '||' condition is true [-Wsometimes-uninitialized]
     198 |         if ((sscanf(argv[2], "%llu%c", &tmpll, &dummy) != 1) ||
         |             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/md/dm-inline-crypt.c:250:9: note: uninitialized use occurs here
     250 |         return ret;
         |                ^~~
   drivers/md/dm-inline-crypt.c:198:6: note: remove the '||' if its condition is always false
     198 |         if ((sscanf(argv[2], "%llu%c", &tmpll, &dummy) != 1) ||
         |             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/md/dm-inline-crypt.c:178:9: note: initialize the variable 'ret' to silence this warning
     178 |         int ret;
         |                ^
         |                 = 0
   2 warnings generated.


vim +198 drivers/md/dm-inline-crypt.c

   168	
   169	static int inlinecrypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
   170	{
   171		struct inlinecrypt_config *cc;
   172		char *cipher_api = NULL;
   173		char *cipher, *chainmode;
   174		unsigned long long tmpll;
   175		char *ivmode;
   176		int key_size;
   177		char dummy;
   178		int ret;
   179	
   180		if (argc < 5) {
   181			ti->error = "Not enough arguments";
   182			return -EINVAL;
   183		}
   184	
   185		key_size = strlen(argv[1]) >> 1;
   186	
   187		cc = kzalloc(struct_size(cc, key, key_size), GFP_KERNEL);
   188		if (!cc) {
   189			ti->error = "Cannot allocate encryption context";
   190			return -ENOMEM;
   191		}
   192		cc->key_size = key_size;
   193		cc->sector_size = (1 << SECTOR_SHIFT);
   194		cc->sector_shift = 0;
   195	
   196		ti->private = cc;
   197	
 > 198		if ((sscanf(argv[2], "%llu%c", &tmpll, &dummy) != 1) ||
   199		    (tmpll & ((cc->sector_size >> SECTOR_SHIFT) - 1))) {
   200			ti->error = "Invalid iv_offset sector";
   201			goto bad;
   202		}
   203		cc->iv_offset = tmpll;
   204	
   205		ret = dm_get_device(ti, argv[3], dm_table_get_mode(ti->table),
   206				    &cc->dev);
   207		if (ret) {
   208			ti->error = "Device lookup failed";
   209			goto bad;
   210		}
   211	
   212		ret = -EINVAL;
   213		if (sscanf(argv[4], "%llu%c", &tmpll, &dummy) != 1 ||
   214		    tmpll != (sector_t)tmpll) {
   215			ti->error = "Invalid device sector";
   216			goto bad;
   217		}
   218	
   219		cc->start = tmpll;
   220	
   221		cipher = strsep(&argv[0], "-");
   222		chainmode = strsep(&argv[0], "-");
   223		ivmode = strsep(&argv[0], "-");
   224	
   225		cipher_api = kmalloc(CRYPTO_MAX_ALG_NAME, GFP_KERNEL);
   226		if (!cipher_api)
   227			goto bad;
   228	
   229		ret = snprintf(cipher_api, CRYPTO_MAX_ALG_NAME,
   230			       "%s(%s)", chainmode, cipher);
   231		if (ret < 0 || ret >= CRYPTO_MAX_ALG_NAME) {
   232			kfree(cipher_api);
   233			ret = -ENOMEM;
   234			goto bad;
   235		}
   236	
   237		ret = crypt_select_inline_crypt_mode(ti, cipher_api, ivmode);
   238	
   239		/* Initialize and set key */
   240		ret = inlinecrypt_set_key(cc, argv[1]);
   241		if (ret < 0) {
   242			ti->error = "Error decoding and setting key";
   243			return ret;
   244		}
   245	
   246		return 0;
   247	bad:
   248		ti->error = "Error in inlinecrypt mapping";
   249		inlinecrypt_dtr(ti);
   250		return ret;
   251	}
   252
kernel test robot Sept. 18, 2024, 5:08 a.m. UTC | #3
Hi Md,

kernel test robot noticed the following build warnings:

[auto build test WARNING on device-mapper-dm/for-next]
[also build test WARNING on axboe-block/for-next linus/master song-md/md-next v6.11 next-20240917]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Md-Sadre-Alam/dm-inlinecrypt-Add-inline-encryption-support/20240916-170452
base:   https://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm.git for-next
patch link:    https://lore.kernel.org/r/20240916085741.1636554-2-quic_mdalam%40quicinc.com
patch subject: [PATCH v2 1/3] dm-inlinecrypt: Add inline encryption support
config: csky-randconfig-r111-20240918 (https://download.01.org/0day-ci/archive/20240918/202409181233.1FrQNVtU-lkp@intel.com/config)
compiler: csky-linux-gcc (GCC) 14.1.0
reproduce: (https://download.01.org/0day-ci/archive/20240918/202409181233.1FrQNVtU-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202409181233.1FrQNVtU-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
>> drivers/md/dm-inline-crypt.c:120:26: sparse: sparse: cast to restricted __le64
   drivers/md/dm-inline-crypt.c:214:32: sparse: sparse: self-comparison always evaluates to false

vim +120 drivers/md/dm-inline-crypt.c

   109	
   110	static void crypt_inline_encrypt_submit(struct dm_target *ti, struct bio *bio)
   111	{
   112		struct inlinecrypt_config *cc = ti->private;
   113		u64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE];
   114	
   115		bio_set_dev(bio, cc->dev->bdev);
   116		if (bio_sectors(bio)) {
   117			memset(dun, 0, BLK_CRYPTO_MAX_IV_SIZE);
   118			bio->bi_iter.bi_sector = cc->start +
   119				dm_target_offset(ti, bio->bi_iter.bi_sector);
 > 120			dun[0] = le64_to_cpu(bio->bi_iter.bi_sector + cc->iv_offset);
   121			bio_crypt_set_ctx(bio, cc->blk_key, dun, GFP_KERNEL);
   122		}
   123	
   124		submit_bio_noacct(bio);
   125	}
   126
diff mbox series

Patch

diff --git a/block/blk-crypto.c b/block/blk-crypto.c
index 4d760b092deb..e5bc3c7a405b 100644
--- a/block/blk-crypto.c
+++ b/block/blk-crypto.c
@@ -19,6 +19,12 @@ 
 #include "blk-crypto-internal.h"
 
 const struct blk_crypto_mode blk_crypto_modes[] = {
+	[BLK_ENCRYPTION_MODE_AES_128_XTS] = {
+		.name = "AES-128-XTS",
+		.cipher_str = "xts(aes)",
+		.keysize = 32,
+		.ivsize = 16,
+	},
 	[BLK_ENCRYPTION_MODE_AES_256_XTS] = {
 		.name = "AES-256-XTS",
 		.cipher_str = "xts(aes)",
@@ -43,6 +49,18 @@  const struct blk_crypto_mode blk_crypto_modes[] = {
 		.keysize = 32,
 		.ivsize = 16,
 	},
+	[BLK_ENCRYPTION_MODE_AES_128_CBC] = {
+		.name = "AES-128-CBC",
+		.cipher_str = "cbc(aes)",
+		.keysize = 16,
+		.ivsize = 16,
+	},
+	[BLK_ENCRYPTION_MODE_AES_256_CBC] = {
+		.name = "AES-256-CBC",
+		.cipher_str = "cbc(aes)",
+		.keysize = 32,
+		.ivsize = 16,
+	},
 };
 
 /*
@@ -106,6 +124,7 @@  void bio_crypt_set_ctx(struct bio *bio, const struct blk_crypto_key *key,
 
 	bio->bi_crypt_context = bc;
 }
+EXPORT_SYMBOL_GPL(bio_crypt_set_ctx);
 
 void __bio_crypt_free_ctx(struct bio *bio)
 {
@@ -356,6 +375,7 @@  int blk_crypto_init_key(struct blk_crypto_key *blk_key, const u8 *raw_key,
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(blk_crypto_init_key);
 
 bool blk_crypto_config_supported_natively(struct block_device *bdev,
 					  const struct blk_crypto_config *cfg)
@@ -398,6 +418,7 @@  int blk_crypto_start_using_key(struct block_device *bdev,
 		return 0;
 	return blk_crypto_fallback_start_using_mode(key->crypto_cfg.crypto_mode);
 }
+EXPORT_SYMBOL_GPL(blk_crypto_start_using_key);
 
 /**
  * blk_crypto_evict_key() - Evict a blk_crypto_key from a block_device
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig
index 1e9db8e4acdf..272a6a3274bb 100644
--- a/drivers/md/Kconfig
+++ b/drivers/md/Kconfig
@@ -270,6 +270,14 @@  config DM_CRYPT
 
 	  If unsure, say N.
 
+config DM_INLINE_CRYPT
+	tristate "Inline crypt target support"
+	depends on BLK_DEV_DM || COMPILE_TEST
+	help
+	  This inline crypt device-mapper target allows to create a device
+	  that transparently encrypts the data on it using inline crypto HW
+	  engine.
+
 config DM_SNAPSHOT
        tristate "Snapshot target"
        depends on BLK_DEV_DM
diff --git a/drivers/md/Makefile b/drivers/md/Makefile
index 476a214e4bdc..0e09b7665803 100644
--- a/drivers/md/Makefile
+++ b/drivers/md/Makefile
@@ -51,6 +51,7 @@  obj-$(CONFIG_DM_UNSTRIPED)	+= dm-unstripe.o
 obj-$(CONFIG_DM_BUFIO)		+= dm-bufio.o
 obj-$(CONFIG_DM_BIO_PRISON)	+= dm-bio-prison.o
 obj-$(CONFIG_DM_CRYPT)		+= dm-crypt.o
+obj-$(CONFIG_DM_INLINE_CRYPT)  += dm-inline-crypt.o
 obj-$(CONFIG_DM_DELAY)		+= dm-delay.o
 obj-$(CONFIG_DM_DUST)		+= dm-dust.o
 obj-$(CONFIG_DM_FLAKEY)		+= dm-flakey.o
diff --git a/drivers/md/dm-inline-crypt.c b/drivers/md/dm-inline-crypt.c
new file mode 100644
index 000000000000..e94f86a3a5e0
--- /dev/null
+++ b/drivers/md/dm-inline-crypt.c
@@ -0,0 +1,316 @@ 
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2024, Qualcomm Innovation Center, Inc. All rights reserved
+ *
+ * Based on work by Israel Rukshin file: dm-crypt.c
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/bio.h>
+#include <linux/blkdev.h>
+#include <linux/crypto.h>
+#include <linux/blk-crypto.h>
+#include <linux/device-mapper.h>
+
+#define DM_MSG_PREFIX "inline-crypt"
+
+struct inlinecrypt_config {
+	struct dm_dev *dev;
+	sector_t start;
+	u64 iv_offset;
+	unsigned int iv_size;
+	unsigned short sector_size;
+	unsigned char sector_shift;
+	unsigned int key_size;
+	enum blk_crypto_mode_num crypto_mode;
+	struct blk_crypto_key *blk_key;
+	u8 key[] __counted_by(key_size);
+};
+
+#define DM_CRYPT_DEFAULT_MAX_READ_SIZE		131072
+#define DM_CRYPT_DEFAULT_MAX_WRITE_SIZE		131072
+
+static unsigned int get_max_request_size(struct inlinecrypt_config *cc, bool wrt)
+{
+	unsigned int val, sector_align;
+
+	val = !wrt ? DM_CRYPT_DEFAULT_MAX_READ_SIZE : DM_CRYPT_DEFAULT_MAX_WRITE_SIZE;
+	if (wrt) {
+		if (unlikely(val > BIO_MAX_VECS << PAGE_SHIFT))
+			val = BIO_MAX_VECS << PAGE_SHIFT;
+	}
+	sector_align = max(bdev_logical_block_size(cc->dev->bdev), (unsigned int)cc->sector_size);
+	val = round_down(val, sector_align);
+	if (unlikely(!val))
+		val = sector_align;
+	return val >> SECTOR_SHIFT;
+}
+
+static int crypt_select_inline_crypt_mode(struct dm_target *ti, char *cipher,
+					  char *ivmode)
+{
+	struct inlinecrypt_config *cc = ti->private;
+
+	if (strcmp(cipher, "xts(aes128)") == 0) {
+		cc->crypto_mode = BLK_ENCRYPTION_MODE_AES_128_XTS;
+	} else if (strcmp(cipher, "xts(aes256)") == 0) {
+		cc->crypto_mode = BLK_ENCRYPTION_MODE_AES_256_XTS;
+	} else if (strcmp(cipher, "cbc(aes128)") == 0) {
+		cc->crypto_mode = BLK_ENCRYPTION_MODE_AES_128_CBC;
+	} else if (strcmp(cipher, "cbc(aes256)") == 0) {
+		cc->crypto_mode = BLK_ENCRYPTION_MODE_AES_256_CBC;
+	} else {
+		ti->error = "Invalid cipher for inline_crypt";
+		return -EINVAL;
+	}
+
+	cc->iv_size = 4;
+
+	return 0;
+}
+
+static int crypt_prepare_inline_crypt_key(struct inlinecrypt_config *cc)
+{
+	int ret;
+
+	cc->blk_key = kzalloc(sizeof(*cc->blk_key), GFP_KERNEL);
+	if (!cc->blk_key)
+		return -ENOMEM;
+
+	ret = blk_crypto_init_key(cc->blk_key, cc->key, cc->crypto_mode,
+				  cc->iv_size, cc->sector_size);
+	if (ret) {
+		DMERR("Failed to init inline encryption key");
+		goto bad_key;
+	}
+
+	ret = blk_crypto_start_using_key(cc->dev->bdev, cc->blk_key);
+	if (ret) {
+		DMERR("Failed to use inline encryption key");
+		goto bad_key;
+	}
+
+	return 0;
+bad_key:
+	kfree_sensitive(cc->blk_key);
+	cc->blk_key = NULL;
+	return ret;
+}
+
+static void crypt_destroy_inline_crypt_key(struct inlinecrypt_config *cc)
+{
+	if (cc->blk_key) {
+		blk_crypto_evict_key(cc->dev->bdev, cc->blk_key);
+		kfree_sensitive(cc->blk_key);
+		cc->blk_key = NULL;
+	}
+}
+
+static void crypt_inline_encrypt_submit(struct dm_target *ti, struct bio *bio)
+{
+	struct inlinecrypt_config *cc = ti->private;
+	u64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE];
+
+	bio_set_dev(bio, cc->dev->bdev);
+	if (bio_sectors(bio)) {
+		memset(dun, 0, BLK_CRYPTO_MAX_IV_SIZE);
+		bio->bi_iter.bi_sector = cc->start +
+			dm_target_offset(ti, bio->bi_iter.bi_sector);
+		dun[0] = le64_to_cpu(bio->bi_iter.bi_sector + cc->iv_offset);
+		bio_crypt_set_ctx(bio, cc->blk_key, dun, GFP_KERNEL);
+	}
+
+	submit_bio_noacct(bio);
+}
+
+static int inlinecrypt_setkey(struct inlinecrypt_config *cc)
+{
+	crypt_destroy_inline_crypt_key(cc);
+
+	return crypt_prepare_inline_crypt_key(cc);
+
+	return 0;
+}
+
+static int inlinecrypt_set_key(struct inlinecrypt_config *cc, char *key)
+{
+	int r = -EINVAL;
+	int key_string_len = strlen(key);
+
+	/* Decode key from its hex representation. */
+	if (cc->key_size && hex2bin(cc->key, key, cc->key_size) < 0)
+		goto out;
+
+	r = inlinecrypt_setkey(cc);
+out:
+	memset(key, '0', key_string_len);
+
+	return r;
+}
+
+static void inlinecrypt_dtr(struct dm_target *ti)
+{
+	struct inlinecrypt_config *cc = ti->private;
+
+	ti->private = NULL;
+
+	if (!cc)
+		return;
+
+	crypt_destroy_inline_crypt_key(cc);
+
+	if (cc->dev)
+		dm_put_device(ti, cc->dev);
+
+	kfree_sensitive(cc);
+}
+
+static int inlinecrypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+{
+	struct inlinecrypt_config *cc;
+	char *cipher_api = NULL;
+	char *cipher, *chainmode;
+	unsigned long long tmpll;
+	char *ivmode;
+	int key_size;
+	char dummy;
+	int ret;
+
+	if (argc < 5) {
+		ti->error = "Not enough arguments";
+		return -EINVAL;
+	}
+
+	key_size = strlen(argv[1]) >> 1;
+
+	cc = kzalloc(struct_size(cc, key, key_size), GFP_KERNEL);
+	if (!cc) {
+		ti->error = "Cannot allocate encryption context";
+		return -ENOMEM;
+	}
+	cc->key_size = key_size;
+	cc->sector_size = (1 << SECTOR_SHIFT);
+	cc->sector_shift = 0;
+
+	ti->private = cc;
+
+	if ((sscanf(argv[2], "%llu%c", &tmpll, &dummy) != 1) ||
+	    (tmpll & ((cc->sector_size >> SECTOR_SHIFT) - 1))) {
+		ti->error = "Invalid iv_offset sector";
+		goto bad;
+	}
+	cc->iv_offset = tmpll;
+
+	ret = dm_get_device(ti, argv[3], dm_table_get_mode(ti->table),
+			    &cc->dev);
+	if (ret) {
+		ti->error = "Device lookup failed";
+		goto bad;
+	}
+
+	ret = -EINVAL;
+	if (sscanf(argv[4], "%llu%c", &tmpll, &dummy) != 1 ||
+	    tmpll != (sector_t)tmpll) {
+		ti->error = "Invalid device sector";
+		goto bad;
+	}
+
+	cc->start = tmpll;
+
+	cipher = strsep(&argv[0], "-");
+	chainmode = strsep(&argv[0], "-");
+	ivmode = strsep(&argv[0], "-");
+
+	cipher_api = kmalloc(CRYPTO_MAX_ALG_NAME, GFP_KERNEL);
+	if (!cipher_api)
+		goto bad;
+
+	ret = snprintf(cipher_api, CRYPTO_MAX_ALG_NAME,
+		       "%s(%s)", chainmode, cipher);
+	if (ret < 0 || ret >= CRYPTO_MAX_ALG_NAME) {
+		kfree(cipher_api);
+		ret = -ENOMEM;
+		goto bad;
+	}
+
+	ret = crypt_select_inline_crypt_mode(ti, cipher_api, ivmode);
+
+	/* Initialize and set key */
+	ret = inlinecrypt_set_key(cc, argv[1]);
+	if (ret < 0) {
+		ti->error = "Error decoding and setting key";
+		return ret;
+	}
+
+	return 0;
+bad:
+	ti->error = "Error in inlinecrypt mapping";
+	inlinecrypt_dtr(ti);
+	return ret;
+}
+
+static int inlinecrypt_map(struct dm_target *ti, struct bio *bio)
+{
+	struct inlinecrypt_config *cc = ti->private;
+	unsigned int max_sectors;
+
+	/*
+	 * If bio is REQ_PREFLUSH or REQ_OP_DISCARD, just bypass crypt queues.
+	 * - for REQ_PREFLUSH device-mapper core ensures that no IO is in-flight
+	 * - for REQ_OP_DISCARD caller must use flush if IO ordering matters
+	 */
+	if (unlikely(bio->bi_opf & REQ_PREFLUSH ||
+		     bio_op(bio) == REQ_OP_DISCARD)) {
+		bio_set_dev(bio, cc->dev->bdev);
+		if (bio_sectors(bio))
+			bio->bi_iter.bi_sector = cc->start +
+				dm_target_offset(ti, bio->bi_iter.bi_sector);
+		return DM_MAPIO_REMAPPED;
+	}
+
+	/*
+	 * Check if bio is too large, split as needed.
+	 */
+	max_sectors = get_max_request_size(cc, bio_data_dir(bio) == WRITE);
+	if (unlikely(bio_sectors(bio) > max_sectors))
+		dm_accept_partial_bio(bio, max_sectors);
+
+	/*
+	 * Ensure that bio is a multiple of internal sector eninlinecryption size
+	 * and is aligned to this size as defined in IO hints.
+	 */
+	if (unlikely((bio->bi_iter.bi_sector & ((cc->sector_size >> SECTOR_SHIFT) - 1)) != 0))
+		return DM_MAPIO_KILL;
+
+	if (unlikely(bio->bi_iter.bi_size & (cc->sector_size - 1)))
+		return DM_MAPIO_KILL;
+
+	crypt_inline_encrypt_submit(ti, bio);
+		return DM_MAPIO_SUBMITTED;
+
+	return 0;
+}
+
+static int inlinecrypt_iterate_devices(struct dm_target *ti,
+				       iterate_devices_callout_fn fn, void *data)
+{
+	struct inlinecrypt_config *cc = ti->private;
+
+	return fn(ti, cc->dev, cc->start, ti->len, data);
+}
+
+static struct target_type inlinecrypt_target = {
+	.name   = "inline-crypt",
+	.version = {1, 0, 0},
+	.module = THIS_MODULE,
+	.ctr    = inlinecrypt_ctr,
+	.dtr    = inlinecrypt_dtr,
+	.map    = inlinecrypt_map,
+	.iterate_devices = inlinecrypt_iterate_devices,
+};
+module_dm(inlinecrypt);
+
+MODULE_AUTHOR("Md Sadre Alam <quic_mdalam@quicinc.com>");
+MODULE_DESCRIPTION(DM_NAME " target for inline encryption / decryption");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/blk-crypto.h b/include/linux/blk-crypto.h
index 5e5822c18ee4..da503a05c5f6 100644
--- a/include/linux/blk-crypto.h
+++ b/include/linux/blk-crypto.h
@@ -10,10 +10,13 @@ 
 
 enum blk_crypto_mode_num {
 	BLK_ENCRYPTION_MODE_INVALID,
+	BLK_ENCRYPTION_MODE_AES_128_XTS,
 	BLK_ENCRYPTION_MODE_AES_256_XTS,
 	BLK_ENCRYPTION_MODE_AES_128_CBC_ESSIV,
 	BLK_ENCRYPTION_MODE_ADIANTUM,
 	BLK_ENCRYPTION_MODE_SM4_XTS,
+	BLK_ENCRYPTION_MODE_AES_128_CBC,
+	BLK_ENCRYPTION_MODE_AES_256_CBC,
 	BLK_ENCRYPTION_MODE_MAX,
 };