* [dm-crypt] Reencrypt process questions
@ 2019-09-30 20:51 Yexie2Fe
2019-10-01 7:18 ` Milan Broz
2019-10-01 12:25 ` Ondrej Kozina
0 siblings, 2 replies; 4+ messages in thread
From: Yexie2Fe @ 2019-09-30 20:51 UTC (permalink / raw)
To: dm-crypt@saout.de
Hi,
After going through the process of reencrypting a non-encrypted disk and
an old LUKS1 volume, I have a couple of questions.
I noticed that the digest iteration count is set to the fixed value of
1000 (cryptsetup 2.2.1 / LUKS2). With a regular luksFormat (or even a
first reencrypt of a non-encrypted disk), it is properly computed from
the key-derivation "benchmark". The FAQ mentions that the "MK iterations
are not very security relevant".
- What is the purpose of these iterations?
- Why are they defined in this fashion (computed vs fixed value when
reencrypting)?
- Is there an option similar to `--pbkdf-force-iterations` to define
this value manually?
I also noticed that `cryptesetup` doesn't have the legacy
`cryptsetup-reencrypt` option `--keep-key` which is useful to change the
parameters like the hash function without actually reencrypting the
data.
Finally, the man page indicates that for `reencrypt
--reduce-device-size`, "only --encrypt variant is supported". I used
this option without `--encrypt` and it seemed to work, although the
behavior was a little bit different compared to the reencryption of a
non-encrypted device.
Using `reencrypt --reduce-device-size 32M` as advised, in the case a
non-encrypted device, the final data offset is 16777216 bytes, whereas
in case of a reencryption of an already encrypted device (with the LUKS1
header size), the final offset is 35618816 bytes. I expected the header
size to match the `--reduce-device-size` option value in the first case.
Best regards,
--
yexie
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [dm-crypt] Reencrypt process questions
2019-09-30 20:51 [dm-crypt] Reencrypt process questions Yexie2Fe
@ 2019-10-01 7:18 ` Milan Broz
2019-10-01 12:25 ` Ondrej Kozina
1 sibling, 0 replies; 4+ messages in thread
From: Milan Broz @ 2019-10-01 7:18 UTC (permalink / raw)
To: Yexie2Fe, dm-crypt@saout.de
Hi,
I let Ondra reply to the reencrypt questions, but few notes below
On 30/09/2019 22:51, Yexie2Fe wrote:
> Hi,
>
> After going through the process of reencrypting a non-encrypted disk and
> an old LUKS1 volume, I have a couple of questions.
>
> I noticed that the digest iteration count is set to the fixed value of
> 1000 (cryptsetup 2.2.1 / LUKS2). With a regular luksFormat (or even a
> first reencrypt of a non-encrypted disk), it is properly computed from
> the key-derivation "benchmark". The FAQ mentions that the "MK iterations
> are not very security relevant".>
> - What is the purpose of these iterations?
It is just additional countermeasure if some issue with RNG is found
later.
Attacking volume key directly should be infeasible through brute force,
so attacking salted digest of it is even worse.
Moreover, an attacker will perhaps use some known plaintext (fs signature),
not attacking digest.
IOW you can run one block cipher decryption of one particular sector with
the known signature and check for validity of decrypted plaintext instead
of running full volume key digest check.
Anyway, I kept the digest the same as in LUKS1.
> - Why are they defined in this fashion (computed vs fixed value when
> reencrypting)?
It should not be fixed value, digest iterations should be benchmarked (the same as in LUKS1).
Onlyy if you require too low iteration time, the minimum (1000) is used.
What parameters were used for the reencryption command?
There is one exception - if you use --pbkdf-force-iterations for the keyslot iterations,
the minimum iteration for digest is used (to avoid benchmark run in automated setups).
> - Is there an option similar to `--pbkdf-force-iterations` to define
> this value manually?
No, I am not sure we really need it. Maybe we need to always just run PBKDF2 benchmark
for a new digest (and possible add generic "disable benchmark" switch). Dunno.
>
> I also noticed that `cryptesetup` doesn't have the legacy
> `cryptsetup-reencrypt` option `--keep-key` which is useful to change the
> parameters like the hash function without actually reencrypting the
> data.
We can do it with luksConvertKey already.
(Ondra can provide details here.)
Milan
> Finally, the man page indicates that for `reencrypt
> --reduce-device-size`, "only --encrypt variant is supported". I used
> this option without `--encrypt` and it seemed to work, although the
> behavior was a little bit different compared to the reencryption of a
> non-encrypted device.
>
> Using `reencrypt --reduce-device-size 32M` as advised, in the case a
> non-encrypted device, the final data offset is 16777216 bytes, whereas
> in case of a reencryption of an already encrypted device (with the LUKS1
> header size), the final offset is 35618816 bytes. I expected the header
> size to match the `--reduce-device-size` option value in the first case.
>
> Best regards,
>
> --
> yexie
> _______________________________________________
> dm-crypt mailing list
> dm-crypt@saout.de
> https://www.saout.de/mailman/listinfo/dm-crypt
>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [dm-crypt] Reencrypt process questions
2019-09-30 20:51 [dm-crypt] Reencrypt process questions Yexie2Fe
2019-10-01 7:18 ` Milan Broz
@ 2019-10-01 12:25 ` Ondrej Kozina
2019-10-01 15:03 ` Yexie2Fe
1 sibling, 1 reply; 4+ messages in thread
From: Ondrej Kozina @ 2019-10-01 12:25 UTC (permalink / raw)
To: dm-crypt@saout.de; +Cc: Yexie2Fe
On 9/30/19 10:51 PM, Yexie2Fe wrote:
> (...)
>
> I also noticed that `cryptesetup` doesn't have the legacy
> `cryptsetup-reencrypt` option `--keep-key` which is useful to change the
> parameters like the hash function without actually reencrypting the
> data.
With LUKS2 you can have each keyslot with different parameters (hash
included, with pbkdf2 function) so it did not make sense to do
'reencryption' just to alter those parameters. As Milan pointed out we
have luksConvertKey action for this. There's no need to replace whole
LUKS2 header for it (that's what legacy cryptsetup-reencrypt utility did
in fact with LUKS1 header).
>
> Finally, the man page indicates that for `reencrypt
> --reduce-device-size`, "only --encrypt variant is supported". I used
> this option without `--encrypt` and it seemed to work, although the
> behavior was a little bit different compared to the reencryption of a
> non-encrypted device. >
> Using `reencrypt --reduce-device-size 32M` as advised, in the case a
> non-encrypted device, the final data offset is 16777216 bytes, whereas
> in case of a reencryption of an already encrypted device (with the LUKS1
> header size), the final offset is 35618816 bytes. I expected the header
> size to match the `--reduce-device-size` option value in the first case
It works as you describe I can only add more clarification. We advertise
(currently) only the use case with device encryption because the
reencryption seemed to us less significant, but it should work in both
cases (at least on API level we have basic tests coverage).
Let's explain your examples with --reduce-device-size 32M. When you do
encryption of plaintext device (placing LUKS2 header in the head of data
device variant) we need spare storage to solve two problems:
1) We need to place LUKS2 header in head of the device (blkid scans for
LUKS2 headers only at offset 0). But there's data there already. So we
take 16MiBs of data in head of device and place it in the tail section
of data device (--reduce-device-size parameter says there's 32MiBs free
space at the end). After it, we place LUKS2 header in the head of device
with proper mapping of data originally placed in head of the data device
at offset 0. If you call "cryptsetup reencrypt --encrypt --init-only
--reduce-device-size 32M" and "cryptsetup luksDump" afterwards you'll
see the mapping of linear segment with id 0. The new LUKS2 header will
have data offset 16MiB (as you've noticed).
2) We need to shift rest of data backwards (towards device tail, while
performing encryption) so that we can reinstate segment with id 0 at
offset 16MiB in the end. For the encryption with data shift we use
second half of area at the tail of the data device (free of real data).
After encryption is completed you have regular LUKS2 device with data
offset 16MiB and free 16 MiB at the tail of the device (you can extend
fs to take the remining 16MiBs at the end). That's where my
documentation fails (I'm going to add note about it).
On the other hand, when you perform reencryption with data shift you
already have LUKS2 header with some data offset in the beginning of the
operation. When you call "cryptsetup reencrypt --reduce-device-size 32M"
we perform device reencryption with data shift and in the end (after
reencryption is finished) we move the data offset 32MiB further (we
don't need to consume half the value for LUKS2 header placement).
So only thing that seems odd to me is your offset 35618816 bytes. This
is strange value. Could provide me with steps how you got that value?
I've run following steps, but failed to get same result:
1) cryptsetup luksFormat --type luks1 /dev/sdx
2) cryptsetup convert --type luks2 /dev/sdx
3) cryptsetup reencrypt --reduce-device-size 32M /dev/sdx
and I've got final data offset 35651584 bytes (2MiB original LUKS1 data
offset + 32MiB gained by data shift during reencryption).
Did you have original LUKS1 device data offset not aligned to 1 MB?
Anyway for anyone interested, I've uploaded some asciinema videos with
very basic tutorial for new LUKS2 reencryption code (includes detached
header examples, LUKS2 in head of data device encryption & more).
Reencryption: https://asciinema.org/a/268573
Encryption: https://asciinema.org/a/268574
Thank you for your feedback! And please report if you find any issue
with LUKS2 reencryption code
Ondra
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [dm-crypt] Reencrypt process questions
2019-10-01 12:25 ` Ondrej Kozina
@ 2019-10-01 15:03 ` Yexie2Fe
0 siblings, 0 replies; 4+ messages in thread
From: Yexie2Fe @ 2019-10-01 15:03 UTC (permalink / raw)
To: Ondrej Kozina; +Cc: dm-crypt@saout.de
Thanks for your answer (and Milan's).
> > I also noticed that `cryptesetup` doesn't have the legacy
> > `cryptsetup-reencrypt` option `--keep-key` which is useful to change the
> > parameters like the hash function without actually reencrypting the
> > data.
>
> With LUKS2 you can have each keyslot with different parameters (hash
> included, with pbkdf2 function) so it did not make sense to do
> 'reencryption' just to alter those parameters. As Milan pointed out we
> have luksConvertKey action for this. There's no need to replace whole
> LUKS2 header for it (that's what legacy cryptsetup-reencrypt utility did
> in fact with LUKS1 header).
I was actually referring to the MK digest. Consider the following
example:
$ dd if=/dev/zero of=luksVolume bs=1M count=1024
$ cryptsetup luksFormat luksVolume
$ cryptsetup luksDump luksVolume
Data segments:
0: crypt
offset: 16777216 [bytes]
Digests:
0: pbkdf2
Hash: sha256
Iterations: 98402
Now we reencrypt.
$ cryptsetup reencrypt --reduce-device-size=32M luksVolume
$ cryptsetup luksDump luksVolume
Data segments:
0: crypt
offset: 50331648 [bytes]
Digests:
0: pbkdf2
Hash: sha256
Iterations: 1000 # iterations value is wrong
The iterations are not computed properly, but the offset matches the
expected device size shrinking. That's the issue I mentioned in my
first message.
Now, in order to update this value (or changing the hash function for
instance), I can either use the `cryptsetup-reencrypt --keep-key` or the
following method, which requires a little more care (like writing the MK
to volatile memory):
$ cryptsetup luksDump --dump-master-key --master-key-file=luksKey luksVolume
$ cryptsetup luksFormat --master-key-file=luksKey luksVolume
$ cryptsetup luksDump luksVolume
Data segments:
0: crypt
offset: 16777216 [bytes] # the offset is "wrong"
Digests:
0: pbkdf2
Hash: sha256
Iterations: 101685
But since I "forgot" to specify the offset, it is now invalid. So I was
essentially asking for a `luksReset` function that does the job of
`luksFormat` while keeping the master key and the proper encrypted data
offset.
> > Using `reencrypt --reduce-device-size 32M` as advised, in the case a
> > non-encrypted device, the final data offset is 16777216 bytes, whereas
> > in case of a reencryption of an already encrypted device (with the LUKS1
> > header size), the final offset is 35618816 bytes. I expected the header
> > size to match the `--reduce-device-size` option value in the first case
>
> So only thing that seems odd to me is your offset 35618816 bytes. This
> is strange value. Could provide me with steps how you got that value?
I wrongly copied the keyslot area size instead of the offset.
> and I've got final data offset 35651584 bytes (2MiB original LUKS1 data
> offset + 32MiB gained by data shift during reencryption).
And thus I get the exact same value.
> After encryption is completed you have regular LUKS2 device with data
> offset 16MiB and free 16 MiB at the tail of the device (you can extend
> fs to take the remining 16MiBs at the end). That's where my
> documentation fails (I'm going to add note about it).
Thanks for your explanation. I did not understand why I would get an
header size of reduce-device-size / 2 when first encrypting (which might
actually be useful if one needs that extra keyslots space but it is not
my case).
Maybe is it possible to be more explicit by allowing to specify
`--luks2-keyslot-size` and `--luks2-metadata-size` when reencrypting,
checked against `--reduce-device-size` and computed based on the
existing header if any?
> Thank you for your feedback!
You're welcome.
--
yexie
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2019-10-01 15:03 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-09-30 20:51 [dm-crypt] Reencrypt process questions Yexie2Fe
2019-10-01 7:18 ` Milan Broz
2019-10-01 12:25 ` Ondrej Kozina
2019-10-01 15:03 ` Yexie2Fe
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.