dm crypt fixes and loop-aes mode support
Subsystems (2)
cover dm crypt fixes and loop-aes mode support
Patch 1 and 2 are fixes (maybe fold it in per cpu patch) others are preparation and changes for multikey support (compatibility mode for loop-aes mappings).
Note: the patchset is based on top of dm devel queue,
http://www.kernel.org/pub/linux/kernel/people/agk/patches/2.6/editing/series.html
it requires per-cpu dmcrypt change
Milan Broz (7):
dm crypt: fix per cpu struct dereference in destructor dm crypt: remove redundant setkey call
dm crypt: set key size early
dm crypt: remove unused compatible table output
dm crypt: redefine IV generator function and add post IV call [RFC]dm crypt: add multi-key capability
[RFC]dm crypt: add loop-aes LMK IV generator
Documentation/device-mapper/dm-crypt.txt | 7 +- drivers/md/dm-crypt.c | 382 ++++++++++++++++++++++++------ 2 files changed, 314 insertions(+), 75 deletions(-)
Signature · 1 line
1.7.2.3
PATCH 1/7 dm crypt: fix per cpu struct dereference in destructor
If destructor is called early (e.g. wrong cipher format) the destructor tries to access nonexistent per cpu struct and causes OOps.
Patch adds check for struct existence (and simplifies tfm destructor as well).
(introduced in per cpu patch)
--- drivers/md/dm-crypt.c | 30 ++++++++---------------------- 1 files changed, 8 insertions(+), 22 deletions(-)
drivers/md/dm-crypt.c +8 -22
@@ -1088,7 +1088,6 @@ static int crypt_setkey_allcpus(struct crypt_config *cc)return err; } -static int crypt_set_key (struct crypt_config *cc,char *key) {unsigned key_size =strlen (key) >>1 ;
@@ -1114,20 +1113,6 @@ static int crypt_wipe_key(struct crypt_config *cc)return crypt_setkey_allcpus (cc); } -static void crypt_dtr_cpus (struct crypt_config *cc) -{ -struct crypt_cpu *cs; -int cpu; - -for_each_possible_cpu (cpu) { - cs =per_cpu_ptr (cc->cpu, cpu); -if (cs->tfm) { -crypto_free_ablkcipher (cs->tfm); - cs->tfm =NULL ; - } - } -} -static void crypt_dtr (struct dm_target *ti) {struct crypt_config *cc = ti->private;
@@ -1144,11 +1129,14 @@ static void crypt_dtr(struct dm_target *ti)if (cc->crypt_queue)destroy_workqueue (cc->crypt_queue); -for_each_possible_cpu (cpu) { - cs =per_cpu_ptr (cc->cpu, cpu); -if (cs->req) -mempool_free (cs->req, cc->req_pool); - } +if (cc->cpu) +for_each_possible_cpu (cpu) { + cs =per_cpu_ptr (cc->cpu, cpu); +if (cs->req) +mempool_free (cs->req, cc->req_pool); +if (cs->tfm) +crypto_free_ablkcipher (cs->tfm); + }if (cc->bs)bioset_free (cc->bs);
@@ -1166,8 +1154,6 @@ static void crypt_dtr(struct dm_target *ti)if (cc->dev)dm_put_device (ti, cc->dev); -crypt_dtr_cpus (cc); -if (cc->cpu)free_percpu (cc->cpu);
Signature · 1 line
1.7.2.3
PATCH 2/7 dm crypt: remove redundant setkey call
In reply to Milan BrozAll keys are already set in crypt_ctr_cipher() call, no need set the key again later.
(introduced in per cpu patch)
--- drivers/md/dm-crypt.c | 11 +---------- 1 files changed, 1 insertions(+), 10 deletions(-)
drivers/md/dm-crypt.c +1 -10
@@ -1317,10 +1317,9 @@ bad_mem:static int crypt_ctr (struct dm_target *ti,unsigned int argc,char **argv) {struct crypt_config *cc; -struct crypt_cpu *cs;unsigned int key_size;unsigned long long tmpll; -int ret, cpu; +int ret;if (argc !=5 ) { ti->error ="Not enough arguments" ;
@@ -1372,14 +1371,6 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) goto bad; } -for_each_possible_cpu (cpu) { - cs =per_cpu_ptr (cc->cpu, cpu); -if (crypto_ablkcipher_setkey (cs->tfm, cc->key, key_size) <0 ) { - ti->error ="Error setting key" ; - goto bad; - } - } - ret = -EINVAL ;if (sscanf (argv[2 ],"%llu" , &tmpll) !=1 ) { ti->error ="Invalid iv_offset sector" ;
Signature · 1 line
1.7.2.3
PATCH 3/7 dm crypt: set key size early
In reply to Milan BrozSimplify key size verification (hexa string) and set key size early in constructor.
(The "-" string means no key - this is just for compatibility reasons. Because of shift it properly decodes to zero key size.)
(Patch required by later changes.)
--- drivers/md/dm-crypt.c | 11 +++++------ 1 files changed, 5 insertions(+), 6 deletions(-)
drivers/md/dm-crypt.c +5 -6
@@ -1090,15 +1090,13 @@ static int crypt_setkey_allcpus(struct crypt_config *cc)static int crypt_set_key (struct crypt_config *cc,char *key) { -unsigned key_size =strlen (key) >>1 ; - -if (cc->key_size && cc->key_size != key_size) +if (cc->key_size != (strlen (key) >>1 ))return -EINVAL ; - cc->key_size = key_size;/* initial settings */ +if (!cc->key_size &&strcmp (key,"-" )) +return -EINVAL ; -if ((!key_size &&strcmp (key,"-" )) || - (key_size &&crypt_decode_key (cc->key, key, key_size) <0 )) +if (cc->key_size &&crypt_decode_key (cc->key, key, cc->key_size) <0 )return -EINVAL ;set_bit (DM_CRYPT_KEY_VALID , &cc->flags);
@@ -1333,6 +1331,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) ti->error ="Cannot allocate encryption context" ;return -ENOMEM ; } + cc->key_size = key_size; ti->private = cc; ret =crypt_ctr_cipher (ti, argv[0 ], argv[1 ]);
Signature · 1 line
1.7.2.3
PATCH 4/7 dm crypt: remove unused compatible table output
In reply to Milan Brozcc->cipher_mode is always set in constructor
dm-crypt still can use compatible mode without IV or blockmode set but it is already internaly converted to "cbc-plain" so we can remove unused table output.
(Also simplify tfm variable which will be removed later.)
--- drivers/md/dm-crypt.c | 8 ++------ 1 files changed, 2 insertions(+), 6 deletions(-)
drivers/md/dm-crypt.c +2 -6
@@ -1241,7 +1241,6 @@ static int crypt_ctr_cipher(struct dm_target *ti, }per_cpu_ptr (cc->cpu, cpu)->tfm = tfm; } - tfm =any_tfm (cc);/* Initialize and set key */ ret =crypt_set_key (cc, key);
@@ -1251,7 +1250,7 @@ static int crypt_ctr_cipher(struct dm_target *ti, }/* Initialize IV */ - cc->iv_size =crypto_ablkcipher_ivsize (tfm); + cc->iv_size =crypto_ablkcipher_ivsize (any_tfm (cc));if (cc->iv_size)/* at least a 64 bit sector number should fit in our buffer */ cc->iv_size = max(cc->iv_size,
@@ -1451,10 +1450,7 @@ static int crypt_status(struct dm_target *ti, status_type_t type,break ;case STATUSTYPE_TABLE : -if (cc->cipher_mode) -DMEMIT ("%s-%s " , cc->cipher, cc->cipher_mode); -else -DMEMIT ("%s " , cc->cipher); +DMEMIT ("%s-%s " , cc->cipher, cc->cipher_mode);if (cc->key_size >0 ) {if ((maxlen - sz) < ((cc->key_size <<1 ) +1 ))
Signature · 1 line
1.7.2.3
PATCH 5/7 dm crypt: redefine IV generator function and add post IV call
In reply to Milan BrozIV (initialisation vector) can in principle depend not only on sector but also on plaintext data (or other attributes).
Change IV generator interface to work directly with dmreq structure to allow such dependence in generator.
Also add post() function which is called after the crypto operation.
This allows tricky modification of decrypted data or IV internals. (If not suitable directly in crypto API.)
In asynchronous mode the post() can be called after ctx->sector count was increased so it is needed
to add iv_sector copy directly to dmreq structure. (N.B. dmreq always include only one sector in scatterlists)
--- drivers/md/dm-crypt.c | 48 +++++++++++++++++++++++++++++++++++------------- 1 files changed, 35 insertions(+), 13 deletions(-)
drivers/md/dm-crypt.c +35 -13
@@ -64,6 +64,7 @@ struct dm_crypt_request {struct convert_context *ctx;struct scatterlist sg_in;struct scatterlist sg_out; +sector_t iv_sector; };struct crypt_config ;
@@ -74,7 +75,10 @@ struct crypt_iv_operations {void (*dtr)(struct crypt_config *cc);int (*init)(struct crypt_config *cc);int (*wipe)(struct crypt_config *cc); -int (*generator)(struct crypt_config *cc,u8 *iv,sector_t sector); +int (*generator)(struct crypt_config *cc,u8 *iv, +struct dm_crypt_request *dmreq); +int (*post)(struct crypt_config *cc,u8 *iv, +struct dm_crypt_request *dmreq); };struct iv_essiv_private {
@@ -166,6 +170,7 @@ static struct kmem_cache *_crypt_io_pool;static void clone_init (struct dm_crypt_io *,struct bio *);static void kcryptd_queue_crypt (struct dm_crypt_io *io); +static u8 *iv_of_dmreq (struct crypt_config *cc,struct dm_crypt_request *dmreq);static struct crypt_cpu *crypt_me (struct crypt_config *cc) {
@@ -204,19 +209,20 @@ static struct crypto_ablkcipher *any_tfm(struct crypt_config *cc)* http://article.gmane.org/gmane.linux.kernel.device-mapper.dm-crypt/454 */ -static int crypt_iv_plain_gen (struct crypt_config *cc,u8 *iv,sector_t sector) +static int crypt_iv_plain_gen (struct crypt_config *cc,u8 *iv, +struct dm_crypt_request *dmreq) {memset (iv,0 , cc->iv_size); - *(u32 *)iv =cpu_to_le32 (sector &0xffffffff ); + *(u32 *)iv =cpu_to_le32 (dmreq->iv_sector &0xffffffff );return 0 ; }static int crypt_iv_plain64_gen (struct crypt_config *cc,u8 *iv, -sector_t sector) +struct dm_crypt_request *dmreq) {memset (iv,0 , cc->iv_size); - *(u64 *)iv =cpu_to_le64 (sector); + *(u64 *)iv =cpu_to_le64 (dmreq->iv_sector);return 0 ; }
@@ -379,12 +385,13 @@ bad:return err; } -static int crypt_iv_essiv_gen (struct crypt_config *cc,u8 *iv,sector_t sector) +static int crypt_iv_essiv_gen (struct crypt_config *cc,u8 *iv, +struct dm_crypt_request *dmreq) {struct crypto_cipher *essiv_tfm =crypt_me (cc)->iv_private;memset (iv,0 , cc->iv_size); - *(u64 *)iv =cpu_to_le64 (sector); + *(u64 *)iv =cpu_to_le64 (dmreq->iv_sector);crypto_cipher_encrypt_one (essiv_tfm, iv, iv);return 0 ; }
@@ -417,19 +424,21 @@ static void crypt_iv_benbi_dtr(struct crypt_config *cc) { } -static int crypt_iv_benbi_gen (struct crypt_config *cc,u8 *iv,sector_t sector) +static int crypt_iv_benbi_gen (struct crypt_config *cc,u8 *iv, +struct dm_crypt_request *dmreq) {__be64 val;memset (iv,0 , cc->iv_size -sizeof (u64));/* rest is cleared below */ - val =cpu_to_be64 (((u64 )sector << cc->iv_gen_private.benbi.shift) +1 ); + val =cpu_to_be64 (((u64 )dmreq->iv_sector << cc->iv_gen_private.benbi.shift) +1 );put_unaligned (val, (__be64 *)(iv + cc->iv_size -sizeof (u64)));return 0 ; } -static int crypt_iv_null_gen (struct crypt_config *cc,u8 *iv,sector_t sector) +static int crypt_iv_null_gen (struct crypt_config *cc,u8 *iv, +struct dm_crypt_request *dmreq) {memset (iv,0 , cc->iv_size);
@@ -489,6 +498,13 @@ static struct ablkcipher_request *req_of_dmreq(struct crypt_config *cc,return (struct ablkcipher_request *)((char *)dmreq - cc->dmreq_start); } +static u8 *iv_of_dmreq (struct crypt_config *cc, +struct dm_crypt_request *dmreq) +{ +return (u8 *)ALIGN ((unsigned long )(dmreq +1 ), +crypto_ablkcipher_alignmask (any_tfm (cc)) +1 ); +} +static int crypt_convert_block (struct crypt_config *cc,struct convert_context *ctx,struct ablkcipher_request *req)
@@ -500,9 +516,9 @@ static int crypt_convert_block(struct crypt_config *cc,int r =0 ; dmreq =dmreq_of_req (cc, req); - iv = (u8 *)ALIGN ((unsigned long )(dmreq +1 ), -crypto_ablkcipher_alignmask (any_tfm (cc)) +1 ); + iv =iv_of_dmreq (cc, dmreq); + dmreq->iv_sector = ctx->sector; dmreq->ctx = ctx;sg_init_table (&dmreq->sg_in,1 ); sg_set_page(&dmreq->sg_in, bv_in->bv_page, 1 << SECTOR_SHIFT,
@@ -525,7 +541,7 @@ static int crypt_convert_block(struct crypt_config *cc, }if (cc->iv_gen_ops) { - r = cc->iv_gen_ops->generator (cc, iv, ctx->sector); + r = cc->iv_gen_ops->generator (cc, iv, dmreq);if (r <0 )return r; }
@@ -538,6 +554,9 @@ static int crypt_convert_block(struct crypt_config *cc,else r =crypto_ablkcipher_decrypt (req); +if (!r && cc->iv_gen_ops && cc->iv_gen_ops->post) + r = cc->iv_gen_ops->post (cc, iv, dmreq); +return r; }
@@ -1003,6 +1022,9 @@ static void kcryptd_async_done(struct crypto_async_request *async_req,return ; } +if (!error && cc->iv_gen_ops && cc->iv_gen_ops->post) + error = cc->iv_gen_ops->post (cc,iv_of_dmreq (cc, dmreq), dmreq); +mempool_free (req_of_dmreq (cc, dmreq), cc->req_pool);if (!atomic_dec_and_test (&ctx->pending))
Signature · 1 line
1.7.2.3
RFC PATCH 6/7 dm crypt: add multi-key capability
In reply to Milan BrozFor supporting multikey mapping we need some way
how to setup more keys in mapping table.
This patch extends mapping table to optional keycount and implements generic multi-key capability.
With more keys defined the <key> string is divided into several <keycount> sections and these are used for the tfms.
The tfm is used according to sector offset
(sector 0->tfm[0], sector 1->tfm[1], sector N->tfm[N modulo keycount]) (only power of two values supported for keycount here).
(N.B. This capability is there only to allow legacy support of loop-aes encryption scheme designed by Jari Ruusu.
There is no third party analysis that multikey scheme increases security of system in comparison to using just one key and secure block mode and appropriate IV generator.)
Because of tfms per-cpu allocation, this mode can be take a lot of memory on large smp systems.
--- Documentation/device-mapper/dm-crypt.txt | 7 ++- drivers/md/dm-crypt.c | 100 +++++++++++++++++++++++------ 2 files changed, 85 insertions(+), 22 deletions(-)
Documentation/device-mapper/dm-crypt.txt +6 -1
@@ -8,7 +8,7 @@ Parameters: <cipher> <key> <iv_offset> <device path> <offset> <cipher> Encryption cipher and an optional IV generation mode. - (In format cipher-chainmode-ivopts:ivmode). + (In format cipher[:keycount]-chainmode-ivopts:ivmode). Examples: des aes-cbc-essiv:sha256
@@ -20,6 +20,11 @@ Parameters: <cipher> <key> <iv_offset> <device path> <offset> Key used for encryption. It is encoded as a hexadecimal number. You can only use key sizes that are valid for the selected cipher. +<keycount> + Multi-key compatibility mode - you can define different keys and + the sectors are according its offset (sector 0 -> key0, 1 -> key1 etc). + Keycount must power of two. + <iv_offset> The IV offset is a sector count that is added to the sector number before creating the IV.
drivers/md/dm-crypt.c +79 -21
200 lines not on this page · raw message
Signature · 1 line
1.7.2.3
RFC PATCH 7/7 dm crypt: add loop-aes LMK IV generator
In reply to Milan BrozThis IV is designed by Jari Ruusu and is used
in loop-aes package.
This patch just adds compatibility mode to dmcrypt for this IV scheme.
(N.B it is not meant as loop-aes replacement which here provides better perfomance but just to provide compatible mappings for people which are unable to patch kernel and userspace to access loop-aes devices.)
loop-aes can use three encryption schemes:
version 1: is plain aes-cbc mode (already compatible) version 2: uses 64 multikey scheme with LMK IV version 3: the same as version 2 with additional IV seed (so v3 uses 65 keys, last key is used as IV seed)
For v2/3 the cipher specification looks like: aes:64-cbc-lmk
In fact, LMK is not only IV generator but also slight modification to CBC encryption mode - the first block of CBC mode depends not only on sector and optional IV seed, but also on plainext data of this sector.
This means that after decryption the first block of sector must be tweaked according to decrypted data.
The format of key is just hexa encoded "raw key" used in loop-aes ioctl.
There is needed small userspace utility which gpg decrypts the file with key and performs simple hash operation to generate raw keys.
(It will be added to cryptsetup once if this patch is accepted.)
Code is inspired by Max Vozeler cryptoAPI implementation (which was not accepted some time ago.)
--- drivers/md/dm-crypt.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 183 insertions(+), 1 deletions(-)
drivers/md/dm-crypt.c +183 -1
@@ -23,6 +23,9 @@#include <linux/scatterlist.h> #include <asm/page.h> #include <asm/unaligned.h> +#include <crypto/hash.h> +#include <crypto/md5.h> +#include <crypto/algapi.h> #include <linux/device-mapper.h>
@@ -90,6 +93,12 @@ struct iv_benbi_private {int shift; }; +#define LMK_SEED_SIZE 64/* hash + 0 */ +struct iv_lmk_private { +struct crypto_shash *hash_tfm; +u8 *seed; +}; +/* * Crypt: maps a linear range of a block device * and encrypts / decrypts at the same time.
@@ -131,6 +140,7 @@ struct crypt_config {union {struct iv_essiv_private essiv;struct iv_benbi_private benbi; +struct iv_lmk_private lmk; } iv_gen_private;sector_t iv_offset;unsigned int iv_size;
@@ -446,6 +456,164 @@ static int crypt_iv_null_gen(struct crypt_config *cc, u8 *iv,return 0 ; } +static void crypt_iv_lmk_dtr (struct crypt_config *cc) +{ +struct iv_lmk_private *lmk = &cc->iv_gen_private.lmk; + +if (lmk->hash_tfm && !IS_ERR (lmk->hash_tfm)) +crypto_free_shash (lmk->hash_tfm); + lmk->hash_tfm =NULL ; + +kzfree (lmk->seed); + lmk->seed =NULL ; +} + +static int crypt_iv_lmk_ctr (struct crypt_config *cc,struct dm_target *ti, +const char *opts) +{ +struct iv_lmk_private *lmk = &cc->iv_gen_private.lmk; + + lmk->hash_tfm =crypto_alloc_shash ("md5" ,0 ,0 ); +if (IS_ERR (lmk->hash_tfm)) { + ti->error ="Error initializing LMK hash" ; +return PTR_ERR (lmk->hash_tfm); + } + +/* No seed in LMK version 2 */ +if (cc->key_parts == cc->tfms_count) { + lmk->seed =NULL ; +return 0 ; + } + + lmk->seed =kzalloc (LMK_SEED_SIZE ,GFP_KERNEL ); +if (!lmk->seed) { +crypt_iv_lmk_dtr (cc); + ti->error ="Error kmallocing seed storage in LMK" ; +return -ENOMEM ; + } + +return 0 ; +} + +static int crypt_iv_lmk_init (struct crypt_config *cc) +{ +struct iv_lmk_private *lmk = &cc->iv_gen_private.lmk; +int subkey_size = cc->key_size / cc->key_parts; + +/* LMK seed is on the position of LMK_KEYS + 1 key */ +if (lmk->seed) +memcpy (lmk->seed, cc->key + (cc->tfms_count * subkey_size), +crypto_shash_digestsize (lmk->hash_tfm)); + +return 0 ; +} + +static int crypt_iv_lmk_wipe (struct crypt_config *cc) +{ +struct iv_lmk_private *lmk = &cc->iv_gen_private.lmk; + +if (lmk->seed) +memset (lmk->seed,0 ,LMK_SEED_SIZE ); + +return 0 ; +} + +static inline void cpu_to_le32_array (u32 *buf,unsigned int words) +{ +while (words--) { +__cpu_to_le32s (buf); + buf++; + } +} + +static int crypt_iv_lmk_one (struct crypt_config *cc,u8 *iv, +struct dm_crypt_request *dmreq, +u8 *data) +{ +struct iv_lmk_private *lmk = &cc->iv_gen_private.lmk; +struct { +struct shash_desc desc; +char ctx[crypto_shash_descsize (lmk->hash_tfm)]; + } sdesc; +struct md5_state md5state; +u32 buf[4 ]; +int r; + + sdesc.desc.tfm = lmk->hash_tfm; + sdesc.desc.flags =CRYPTO_TFM_REQ_MAY_SLEEP ; + + r =crypto_shash_init (&sdesc.desc); +if (r) +return r; + +if (lmk->seed) { + r =crypto_shash_update (&sdesc.desc, lmk->seed,LMK_SEED_SIZE ); +if (r) +return r; + } + +/* Sector is always 512B, block size 16, add data of blocks 1-31 */ + r =crypto_shash_update (&sdesc.desc, data +16 ,16 *31 ); +if (r) +return r; + +/* Sector is cropped to 56 bits here */ + buf[0 ] = dmreq->iv_sector &0xFFFFFFFF ; + buf[1 ] = ((dmreq->iv_sector >>32 ) &0x00FFFFFF ) |0x80000000 ; + buf[2 ] =4024 ; + buf[3 ] =0 ; +cpu_to_le32_array (buf,4 ); + + r =crypto_shash_update (&sdesc.desc, (u8 *)buf,sizeof (buf)); +if (r) +return r; + +/* No MD5 padding here */ + r =crypto_shash_export (&sdesc.desc, &md5state); +if (r) +return r; + +cpu_to_le32_array (md5state.hash,4 ); +memcpy (iv, &md5state.hash, cc->iv_size); +return 0 ; +} + +static int crypt_iv_lmk_gen (struct crypt_config *cc,u8 *iv, +struct dm_crypt_request *dmreq) +{ +u8 *src; +int r =0 ; + +if (bio_data_dir (dmreq->ctx->bio_in) ==WRITE ) { + src =kmap_atomic (sg_page (&dmreq->sg_in),KM_USER0 ); + r =crypt_iv_lmk_one (cc, iv, dmreq, src + dmreq->sg_in.offset); +kunmap_atomic (src,KM_USER0 ); + }else +memset (iv,0 , cc->iv_size); + +return r; +} + +static int crypt_iv_lmk_post (struct crypt_config *cc,u8 *iv, +struct dm_crypt_request *dmreq) +{ +u8 *dst; +int r; + +if (bio_data_dir (dmreq->ctx->bio_in) ==WRITE ) +return 0 ; + + dst =kmap_atomic (sg_page (&dmreq->sg_out),KM_USER0 ); + r =crypt_iv_lmk_one (cc, iv, dmreq, dst + dmreq->sg_out.offset); + +/* Code must fix the first block of plaintext sector */ +if (!r) +crypto_xor (dst + dmreq->sg_out.offset, iv, cc->iv_size); + +kunmap_atomic (dst,KM_USER0 ); +return r; +} +static struct crypt_iv_operations crypt_iv_plain_ops = { .generator = crypt_iv_plain_gen };
@@ -472,6 +640,15 @@ static struct crypt_iv_operations crypt_iv_null_ops = { .generator = crypt_iv_null_gen }; +static struct crypt_iv_operations crypt_iv_lmk_ops = { + .ctr = crypt_iv_lmk_ctr, + .dtr = crypt_iv_lmk_dtr, + .init = crypt_iv_lmk_init, + .wipe = crypt_iv_lmk_wipe, + .generator = crypt_iv_lmk_gen, + .post = crypt_iv_lmk_post +}; + static void crypt_convert_init(struct crypt_config *cc, struct convert_context *ctx, struct bio *bio_out, struct bio *bio_in,
@@ -1349,7 +1526,12 @@ static int crypt_ctr_cipher(struct dm_target *ti, cc->iv_gen_ops = &crypt_iv_benbi_ops; else if (strcmp(ivmode, "null") == 0) cc->iv_gen_ops = &crypt_iv_null_ops; - else { + else if (strcmp(ivmode, "lmk") == 0) { + cc->iv_gen_ops = &crypt_iv_lmk_ops; + /* loop-aes multikey version 3 - last key used for IV seed */ + if (cc->key_size % cc->key_parts) + cc->key_parts++; + } else { ret = -EINVAL; ti->error = "Invalid IV mode"; goto bad;
Signature · 1 line
1.7.2.3