[dm-devel] [PATCH] dm-crypt: add support for very wide (>512 bytes) block modes
Rik Snel
rsnel at cube.dyndns.org
Sun Dec 3 12:48:22 UTC 2006
From: Rik Snel <rsnel at cube.dyndns.org>
By default dm-crypt sends and receives chunks of 512 bytes to and from
the crypto layer. For implementing deniable harddisk encryption it is
useful to make these chunks larger; i.e. equal to the filesystem block
size. If a wide block cipher mode (like ABL) is used, then a single bit
modification of the filesystem block will result in a total change of the
corresponding cipher block.
This patch adds an optional argument to dm-crypt, the 'extra sector size
shift'. The blocksize for communicating with the crypto layer will be
512<<'extra sector size shift'. The resulting size may not be larger
than PAGE_SIZE. Care is taken to also enlarge the hardsector_size as needed.
Signed-off-by: Rik Snel <rsnel at cube.dyndns.org>
---
drivers/md/dm-crypt.c | 50 ++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 45 insertions(+), 5 deletions(-)
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index a88dc95..28a9729 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -95,6 +95,7 @@ struct crypt_config {
struct crypto_blkcipher *tfm;
unsigned long flags;
unsigned int key_size;
+ int extra_shift;
u8 key[0];
};
@@ -257,7 +258,8 @@ static int crypt_iv_benbi_gen(struct crypt_config *cc, u8 *iv, sector_t sector)
static int crypt_iv_bewbi_gen(struct crypt_config *cc, u8 *iv, sector_t sector)
{
memset(iv, 0, cc->iv_size - sizeof(u32));
- *((u32*)iv + 3) = cpu_to_be32((sector & 0xffffffff) + 1);
+ *((u32*)iv + 3) =
+ cpu_to_be32((sector >> cc->extra_shift & 0xffffffff) + 1);
return 0;
}
@@ -344,12 +346,12 @@ static int crypt_convert(struct crypt_config *cc,
struct scatterlist sg_in = {
.page = bv_in->bv_page,
.offset = bv_in->bv_offset + ctx->offset_in,
- .length = 1 << SECTOR_SHIFT
+ .length = (1 << SECTOR_SHIFT) << cc->extra_shift
};
struct scatterlist sg_out = {
.page = bv_out->bv_page,
.offset = bv_out->bv_offset + ctx->offset_out,
- .length = 1 << SECTOR_SHIFT
+ .length = (1 << SECTOR_SHIFT) << cc->extra_shift
};
ctx->offset_in += sg_in.length;
@@ -760,7 +762,7 @@ static int crypt_wipe_key(struct crypt_config *cc)
/*
* Construct an encryption mapping:
- * <cipher> <key> <iv_offset> <dev_path> <start>
+ * <cipher> <key> <iv_offset> <dev_path> <start> [<extra_shift>]
*/
static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
{
@@ -774,11 +776,16 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
unsigned int key_size;
unsigned long long tmpll;
- if (argc != 5) {
+ if (argc < 5) {
ti->error = "Not enough arguments";
return -EINVAL;
}
+ if (argc > 6) {
+ ti->error = "Too many arguments";
+ return -EINVAL;
+ }
+
tmp = argv[0];
cipher = strsep(&tmp, "-");
chainmode = strsep(&tmp, "-");
@@ -903,12 +910,42 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
}
cc->start = tmpll;
+ if (argc > 5) {
+ if (sscanf(argv[5], "%llu", &tmpll) != 1) {
+ ti->error = "Invalid extra sector size shift";
+ goto bad5;
+ }
+ if (tmpll < 1) {
+ ti->error = "Invalid extra sector size shift, "
+ "must be positive";
+ goto bad5;
+ }
+ if (tmpll > PAGE_SHIFT - SECTOR_SHIFT) {
+ ti->error = "Invalid extra sector size shift, "
+ "must be <= PAGE_SHIFT - SECTOR_SHIFT";
+ goto bad5;
+ }
+ cc->extra_shift = tmpll;
+ } else cc->extra_shift = 0;
+
if (dm_get_device(ti, argv[3], cc->start, ti->len,
dm_table_get_mode(ti->table), &cc->dev)) {
ti->error = "Device lookup failed";
goto bad5;
}
+ if (cc->extra_shift) {
+ /* update hardsector_size */
+ if (ti->limits.hardsect_size%(1 << SECTOR_SHIFT)) {
+ ti->error = "Weird sector size, too small or "
+ "not a power of 2";
+ goto bad5;
+ }
+ while (ti->limits.hardsect_size <
+ (1 << SECTOR_SHIFT) << cc->extra_shift)
+ ti->limits.hardsect_size <<= 1;
+ }
+
if (ivmode && cc->iv_gen_ops) {
if (ivopts)
*(ivopts - 1) = ':';
@@ -1010,6 +1047,9 @@ static int crypt_status(struct dm_target *ti, status_type_t type,
DMEMIT(" %llu %s %llu", (unsigned long long)cc->iv_offset,
cc->dev->name, (unsigned long long)cc->start);
+ if (cc->extra_shift)
+ DMEMIT(" %llu", (unsigned long long)cc->extra_shift);
+
break;
}
return 0;
--
1.4.4.1
More information about the dm-devel
mailing list