[dm-crypt] GEOM_ELI support in dm-crypt/cryptsetup

Carl-Daniel Hailfinger c-d.hailfinger.devel.2006 at gmx.net
Wed Dec 28 19:06:40 CET 2016


Hello everyone,

a short followup with a quick-and-dirty Linux kernel patch. Compile
tested only.

>From 97309be452816b634d19bc61ba95d27fe48ff366 Mon Sep 17 00:00:00 2001
From: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006 at gmx.net>
Date: Wed, 28 Dec 2016 18:52:49 +0100
Subject: [PATCH] Add FreeBSD GEOM::ELI (GELI) compatible IV mode.

Signed-off-by: Carl-Daniel Hailfinger <@>
---
 drivers/md/dm-crypt.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 49 insertions(+)

diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 7c6c572..feae131 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -111,6 +111,10 @@ struct iv_tcw_private {
 	u8 *whitening;
 };
 
+struct iv_byte64_private {
+	int sector_shift;
+};
+
 /*
  * Crypt: maps a linear range of a block device
  * and encrypts / decrypts at the same time.
@@ -151,6 +155,7 @@ struct crypt_config {
 		struct iv_benbi_private benbi;
 		struct iv_lmk_private lmk;
 		struct iv_tcw_private tcw;
+		struct iv_byte64_private byte64;
 	} iv_gen_private;
 	sector_t iv_offset;
 	unsigned int iv_size;
@@ -241,6 +246,10 @@ static struct crypto_skcipher *any_tfm(struct crypt_config *cc)
  *       Note that this encryption scheme is vulnerable to watermarking attacks
  *       and should be used for old compatible containers access only.
  *
+ * byte64: Compatible implementation of the IV scheme used by FreeBSD GEOM::ELI.
+ *       The initial vector is the 64-bit little-endian version of the byte
+ *       number, padded with zeros if necessary.
+ *
  * plumb: unimplemented, see:
  * http://article.gmane.org/gmane.linux.kernel.device-mapper.dm-crypt/454
  */
@@ -762,6 +771,37 @@ static int crypt_iv_tcw_post(struct crypt_config *cc, u8 *iv,
 	return r;
 }
 
+static int crypt_iv_byte64_ctr(struct crypt_config *cc, struct dm_target *ti,
+			       const char *opts)
+{
+	struct iv_byte64_private *byte64 = &cc->iv_gen_private.byte64;
+	int sector_shift = 9; //FIXME: Use the sector shift supplied by userspace
+
+	byte64->sector_shift = sector_shift;
+
+	return 0;
+}
+
+static void crypt_iv_byte64_dtr(struct crypt_config *cc)
+{
+}
+
+static int crypt_iv_byte64_gen(struct crypt_config *cc, u8 *iv,
+			       struct dm_crypt_request *dmreq)
+{
+	struct iv_byte64_private *byte64 = &cc->iv_gen_private.byte64;
+	int sector_shift = byte64->sector_shift;
+
+	memset(iv, 0, cc->iv_size);
+	/* FIXME: Make sure the sector number uses the right unit (512B vs. 4kiB sectors)
+	 * FIMXE: We want absolute byte numbers here, but those absolute byte numbers
+	 * are only calculated on boundaries specified by the GELI header.
+	 */
+	*(__le64 *)iv = cpu_to_le64(dmreq->iv_sector << sector_shift);
+
+	return 0;
+}
+
 static const struct crypt_iv_operations crypt_iv_plain_ops = {
 	.generator = crypt_iv_plain_gen
 };
@@ -806,6 +846,13 @@ static int crypt_iv_tcw_post(struct crypt_config *cc, u8 *iv,
 	.post	   = crypt_iv_tcw_post
 };
 
+static const struct crypt_iv_operations crypt_iv_byte64_ops = {
+	//FIXME: Use .init instead?
+	.ctr      = crypt_iv_byte64_ctr,
+	.dtr      = crypt_iv_byte64_dtr,
+	.generator = crypt_iv_byte64_gen
+};
+
 static void crypt_convert_init(struct crypt_config *cc,
 			       struct convert_context *ctx,
 			       struct bio *bio_out, struct bio *bio_in,
@@ -1816,6 +1863,8 @@ static int crypt_ctr_cipher(struct dm_target *ti,
 		cc->iv_gen_ops = &crypt_iv_tcw_ops;
 		cc->key_parts += 2; /* IV + whitening */
 		cc->key_extra_size = cc->iv_size + TCW_WHITENING_SIZE;
+	} else if (strcmp(ivmode, "byte64") == 0) {
+		cc->iv_gen_ops = &crypt_iv_byte64_ops;
 	} else {
 		ret = -EINVAL;
 		ti->error = "Invalid IV mode";
-- 
1.9.1


Really untested. Taking the sector_shift value from userspace cryptsetup
is not yet implemented.


On 28.12.2016 16:46, Carl-Daniel Hailfinger wrote:
> Hello everyone,
>
> I was looking for a way to access a GELI encrypted disk from within
> Linux (for forensics of disks used in FreeBSD, but people wanting to
> access encrypted FreeNAS data from OpenMediaVault could benefit as well)
> and found this email. Did the code for GEOM_ELI encryption support in
> cryptsetup/dm-crypt ever get written? If not, I might have a go at it.
>
> Admittedly the only part I'm interested right now is the unauthenticated
> aes-xts with the bytecount64 IV because that is apparently the most
> commonly used variant.
>
>
> On Fri Dec 13 07:42:52 CET 2013, f000m at z1p.biz wrote:
>> --- Ursprüngliche Nachricht ---
>> Von: Milan Broz <gmazyland at gmail.com>
>> Datum: 30.11.2013 18:33:02
>> An: f000m at z1p.biz
>> Betreff: Re: [dm-crypt] GEOM_ELI support in dm-crypt/cryptsetup
>>
>>> On 11/30/2013 04:25 PM, f000m at z1p.biz wrote:
>>>> I am planing to make dm-crypt and cryptsetup able to
>>>> handle FreeBSD's GEOM_ELI crypted devices (without its
>>>> integrity stuff).
>>> I think that even integrity stuff would be interesting
>>> but that's a lot of kernel work.
>>> (But I am quite interested how FreeBSD approach looks like anyway.)
>>>
>> The first comment in the header file explains how it works.
>> http://svnweb.freebsd.org/base/head/sys/geom/eli/g_eli_integrity.c?view=co
>>
>>>> In the kernel modul there would be minor changes
>>>> concerning two more IV generators needed to add:
>>>> First, because of a slightly different handling of plain type
>>>> (it uses offsets instead of sectors).
>>>> Second, GEOM_ELI uses CBC with unpredictable IV instead of
>>>> ESSIV Mode.
>>> Not sure I understand offset/sectors problem.
>>> Can you elaborate more here? Is it just multiplication
>>> of sector number by sector size or something else?
>>> (Or just point me to the docs :)
>>>
>> Yes it is for plain mode. You can see it in g_eli_crypto_ivgen().
>> http://svnweb.freebsd.org/base/head/sys/geom/eli/g_eli.c?view=co
>>
>> The unpredicable IV generation creates a SHA256 digest. It uses a IV seed
>> and the offset number (sector number by sector size).
>>
>> Also it would need to add a routine to calculate (HMAC-SHA-512) the
>> encryption key on the fly because GEOM_ELI uses multiple encryption keys
>> since version 5. It uses a different key for every 2^20 sectors.
>> So I would put it in the IV generators, too.
>>
>>> Anyway, adding new IV generators to dmcrypt should not be big problem
>>> (in principle).
>>>
>>>> Additionally cryptsetup must be patched to be able
>>>> to deal with the metadata structure of GEOM_ELI devices.
>>>>
>>>> Would there be any interests in committing me this code
>>>> to the upstream?
>>> Well, I am not sure how broadly this format is used and if
>>> there are potential users in Linux world, so if you can
>>> post more description here it would be nice.
>>>
>> It is a common tool in FreeBSD for cryptography. So it would be
>> nice one could access these FreeBSD devices with Linux, too (I think =).
>>
>>> (And if anyone on list is interested, plesase say so... now :)
>>>
>>> But in general, yes, I think it is good idea.
>>>
>>> I would suggest you to do these steps:
>>>
>>> 1) provide links to documentation of format, limitation
>>> of your approach etc (also should be included in patch later)
>>>
>>> 2) first, implement needed changes in Linux kernel (dmcrypt IVs)
>>> (if it is only new IV, it should be straightforward)
>>> Please post patches to DM devel list (dm-devel at redhat.com)
>>>
>>> This should be done in advance - for testing, you can use
>>> dmsetup to configure dmcrypt device and test it works for your
>>> images.
>>>
>>> Cryptsetup support can come later (we need patch in stable kernel
>>> first to release build supporting it).
>>>
>>> 3) second, post patches for cryptsetup to this list.
>>>
>>> Please keep format specific code in separate directory,
>>> lib/geli/* or so.
>>> (I am planning some unified interface for formats in future (1.7),
>>> so see how is e.g. TCRYPT done - it should be very similar).
>>>
>>> Please post at least simple regression tests together with patches
>>> (see tests/ dir).
>>>
>>> License of new code must be compatible with released code,
>>> basically GPL2+/LGPL2.1+ for cryptsetup.
>>>
>>> (And be prepared it will take some time and perhaps reiterated
>>> patch posts - mainly for kernel part :)
>>>
>>> Thanks,
>>> Milan
>>>
>> Thanks for your suggestions.
>>
>> Best regards.
> Regards,
> Carl-Daniel

I haven't yet looked at how cryptsetup feeds the setup data to the
kernel. AFAICS the only data the kernel needs to know is the key and the
sector shift value. Is there any quick howto for adding support for new
on-disk formats to cryptsetup? The GELI on-disk format I care about is
just one metadata sector at the end of the device, and sector 0 to n-2
store encrypted data.

Any help would be appreciated.

Regards,
Carl-Daniel


More information about the dm-crypt mailing list