Skip to content

Commit b9411d7

Browse files
mbrozsnitm
authored andcommitted
dm crypt: implement eboiv - encrypted byte-offset initialization vector
This IV is used in some BitLocker devices with CBC encryption mode. IV is encrypted little-endian byte-offset (with the same key and cipher as the volume). Signed-off-by: Milan Broz <[email protected]> Signed-off-by: Mike Snitzer <[email protected]>
1 parent 6028a7a commit b9411d7

File tree

1 file changed

+81
-1
lines changed

1 file changed

+81
-1
lines changed

drivers/md/dm-crypt.c

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,10 @@ struct iv_tcw_private {
120120
u8 *whitening;
121121
};
122122

123+
struct iv_eboiv_private {
124+
struct crypto_cipher *tfm;
125+
};
126+
123127
/*
124128
* Crypt: maps a linear range of a block device
125129
* and encrypts / decrypts at the same time.
@@ -159,6 +163,7 @@ struct crypt_config {
159163
struct iv_benbi_private benbi;
160164
struct iv_lmk_private lmk;
161165
struct iv_tcw_private tcw;
166+
struct iv_eboiv_private eboiv;
162167
} iv_gen_private;
163168
u64 iv_offset;
164169
unsigned int iv_size;
@@ -290,6 +295,10 @@ static struct crypto_aead *any_tfm_aead(struct crypt_config *cc)
290295
* is calculated from initial key, sector number and mixed using CRC32.
291296
* Note that this encryption scheme is vulnerable to watermarking attacks
292297
* and should be used for old compatible containers access only.
298+
*
299+
* eboiv: Encrypted byte-offset IV (used in Bitlocker in CBC mode)
300+
* The IV is encrypted little-endian byte-offset (with the same key
301+
* and cipher as the volume).
293302
*/
294303

295304
static int crypt_iv_plain_gen(struct crypt_config *cc, u8 *iv,
@@ -838,6 +847,67 @@ static int crypt_iv_random_gen(struct crypt_config *cc, u8 *iv,
838847
return 0;
839848
}
840849

850+
static void crypt_iv_eboiv_dtr(struct crypt_config *cc)
851+
{
852+
struct iv_eboiv_private *eboiv = &cc->iv_gen_private.eboiv;
853+
854+
crypto_free_cipher(eboiv->tfm);
855+
eboiv->tfm = NULL;
856+
}
857+
858+
static int crypt_iv_eboiv_ctr(struct crypt_config *cc, struct dm_target *ti,
859+
const char *opts)
860+
{
861+
struct iv_eboiv_private *eboiv = &cc->iv_gen_private.eboiv;
862+
struct crypto_cipher *tfm;
863+
864+
tfm = crypto_alloc_cipher(cc->cipher, 0, 0);
865+
if (IS_ERR(tfm)) {
866+
ti->error = "Error allocating crypto tfm for EBOIV";
867+
return PTR_ERR(tfm);
868+
}
869+
870+
if (crypto_cipher_blocksize(tfm) != cc->iv_size) {
871+
ti->error = "Block size of EBOIV cipher does "
872+
"not match IV size of block cipher";
873+
crypto_free_cipher(tfm);
874+
return -EINVAL;
875+
}
876+
877+
eboiv->tfm = tfm;
878+
return 0;
879+
}
880+
881+
static int crypt_iv_eboiv_init(struct crypt_config *cc)
882+
{
883+
struct iv_eboiv_private *eboiv = &cc->iv_gen_private.eboiv;
884+
int err;
885+
886+
err = crypto_cipher_setkey(eboiv->tfm, cc->key, cc->key_size);
887+
if (err)
888+
return err;
889+
890+
return 0;
891+
}
892+
893+
static int crypt_iv_eboiv_wipe(struct crypt_config *cc)
894+
{
895+
/* Called after cc->key is set to random key in crypt_wipe() */
896+
return crypt_iv_eboiv_init(cc);
897+
}
898+
899+
static int crypt_iv_eboiv_gen(struct crypt_config *cc, u8 *iv,
900+
struct dm_crypt_request *dmreq)
901+
{
902+
struct iv_eboiv_private *eboiv = &cc->iv_gen_private.eboiv;
903+
904+
memset(iv, 0, cc->iv_size);
905+
*(__le64 *)iv = cpu_to_le64(dmreq->iv_sector * cc->sector_size);
906+
crypto_cipher_encrypt_one(eboiv->tfm, iv, iv);
907+
908+
return 0;
909+
}
910+
841911
static const struct crypt_iv_operations crypt_iv_plain_ops = {
842912
.generator = crypt_iv_plain_gen
843913
};
@@ -890,6 +960,14 @@ static struct crypt_iv_operations crypt_iv_random_ops = {
890960
.generator = crypt_iv_random_gen
891961
};
892962

963+
static struct crypt_iv_operations crypt_iv_eboiv_ops = {
964+
.ctr = crypt_iv_eboiv_ctr,
965+
.dtr = crypt_iv_eboiv_dtr,
966+
.init = crypt_iv_eboiv_init,
967+
.wipe = crypt_iv_eboiv_wipe,
968+
.generator = crypt_iv_eboiv_gen
969+
};
970+
893971
/*
894972
* Integrity extensions
895973
*/
@@ -2293,6 +2371,8 @@ static int crypt_ctr_ivmode(struct dm_target *ti, const char *ivmode)
22932371
cc->iv_gen_ops = &crypt_iv_benbi_ops;
22942372
else if (strcmp(ivmode, "null") == 0)
22952373
cc->iv_gen_ops = &crypt_iv_null_ops;
2374+
else if (strcmp(ivmode, "eboiv") == 0)
2375+
cc->iv_gen_ops = &crypt_iv_eboiv_ops;
22962376
else if (strcmp(ivmode, "lmk") == 0) {
22972377
cc->iv_gen_ops = &crypt_iv_lmk_ops;
22982378
/*
@@ -3093,7 +3173,7 @@ static void crypt_io_hints(struct dm_target *ti, struct queue_limits *limits)
30933173

30943174
static struct target_type crypt_target = {
30953175
.name = "crypt",
3096-
.version = {1, 18, 1},
3176+
.version = {1, 19, 0},
30973177
.module = THIS_MODULE,
30983178
.ctr = crypt_ctr,
30993179
.dtr = crypt_dtr,

0 commit comments

Comments
 (0)