All of lore.kernel.org
 help / color / mirror / Atom feed
* [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.