Hi,
Thanks a lot, these info are very helpful. Better to keep it for debugging for now, and ask users to use it very carefully.
On Tue, Apr 20, 2021 at 3:54 PM Milan Broz gmazyland@gmail.com wrote:
Hi,
TL;DR what you are trying to do is to actually reverse many security measures we added. It is perhaps acceptable for debugging but hardly for real generic system.
- using memory-hard function increases cost of dictionary and brute-force
attacks You can always decrease amount of memory needed, but you should do it only if you know that security margin is ok (like password is randomly generated with enough entropy).
- key is in keyring to remove possibility for normal userspace to receive
the key from kernel. Moreover, there is no need to retain kernel in keyring once dm-crypt device is activated. (It is still in kernel memory but only in crypto functions context). (Systemd also uses keyring to cache passphrase but that's different thing.)
You can still use old way for activation with --disable-keyring activation, but then you disable this possibility.
More comments below.
On 19/04/2021 12:00, Kairui Song wrote:
Hi all,
I'm currently trying to add kdump support for systemd with full-disk LUKS encryption. vmcores contain sensitive data so they should also be protected, and network dumps sometimes are not available. So kdump has to open the LUKS encrypted device in the kdump environment.
I'm using systemd/dracut, my work machine is running Fedora 34, and there are several problems I'm trying to solve:
- Users have to input the password in the kdump kernel environment.
But users often don't have shell access to the kdump environment. (headless server, graphic card not working after kexec, both are very common) 2. LUKS2 prefers Argon2 as the key derivation function, designed to use a lot of memory. kdump is expected to use a minimal amount of memory. Users will have to reserve a huge amount of memory for kdump to work (eg. 1G reserve for kdump with 4G total memory which is not reasonable).
When I added Argon2 to LUKS2, I actually expected such issues. Despite some people beats me that they cannot use arbitrary amount of memory, we have some hard limits that were selected that it should work on most recent systems. Maybe kdump can live with it.
- maximum memory cost limit is 4GB, no LUKS2 device can use more for Argon2
- we never use more than half of available physical memory (measured on the host where the device was formatted)
- required amount of memory is visible in LUKS2 metadata (luksDump) for the particular keyslot (Memory: the value is in kB)
- we use benchmark to calculate memory cost with prefered unlocking time 2 seconds (again, on the device where LUKS was formatted) Small systems (like RPi2) the uses much smaller acceptable values.
You can configure all costs (time, memory, threads) during format or even set them to predefined values.
I am sorry, but there is really no way around this - and the requeired memory must be physical memory (otherwise it slows down extremely). This is a feature, not a bug :-)
To fix these problems, I tried to pass the master key to the second kernel directly via initramfs. Kdump will modify the initramfs in ramfs to include the key, kexec_load it, and never write to any actual back storage. This worked with old LUKS configurations.
Well, passing volume key this way is quite insecure, but perhaps acceptable for debugging.
But LUKS2/cryptsetup now stores the key in the kernel keyring by default. The key is accessible from userspace.
If you are talking about volume key (not passsphrase), it is not available from userspace. Only reference to it. But you can use this reference to construct in-kernel dm-crypt device. Please read https://gitlab.com/cryptsetup/cryptsetup/-/blob/master/docs/Keyring.txt
Users can enter the password to start kdump manually and then it will work, but usually people expect kdump service to start automatically.
(WIP patch series: https://lists.fedoraproject.org/archives/list/kexec@lists.fedoraproject.org/...)
I've several ideas about how to improve it but not sure which one is better, and if this is a good idea after all:
- Simply introduce a config to let systemd-cryptsetup disable kernel
keyring on setup, there is currently no such option.
Well, that option could be useful anyway and we have support for it in cryptsetup (--disable-keyring CLI option) and libcryptsetup, so why not. Just this should not be a default option.
This is should be patch for systemd-cryptsetup only as libcryptsetup supports it.
...
- If we can let the key stay in userspace for a little longer, eg.
for systems booted with dracut/systemd, when systemd-cryptsetup@%s.service opens the crypt device, keep the key in dm-crypt. And later when services like kdump have finished loading, cryptsetup can refresh the device and store the key in the kernel keyring again.
We invalidate volume key in keyring after libceyposetup operation is finished (and kernel removes the reference once keyring garbage collection is run).
I can imagine to add some option to keep key inside keyring even after call is finished, but as said above, this removes some security margin we intentionally introduced here.
I agree with your comments, thanks! These two approaches seem not a good idea now.
...
Milan
How about plan 3 and 4?
- Let kdump use some custom helper/service to load all needed
resources in the early initrd boot stage, prior to systemd-cryptsetup@%s.service. It will ask the password / parse the keyfile and load kdump, then provide info for systemd-cryptsetup or just do the setup. Or maybe let systemd-cryptsetup support some kind of "plugins" so other tools can use it.
Some details could be changed/improved, but systemd-cryptsetup@%s.service will prompt for a password or use a keyfile anyway. So I think at this point, loading kdump with the volume key should be safe? At least long as the kdump kernel/environment itself isn't compromised. Loaded kdump resources can be restricted to be only accessible from the kernel side. After panic, kernel kexec jumps to kdump kernel, and that's an minimized emergency environment that only lives for a very short period.
- A better and safer solution seems to keep a consistent key ring
between kexec boots but also more complex and difficult as different arch implements kexec differently.
Maybe plan 4 will be a good idea if doable? Since that keeps the key consistent in the kernel between kexec boots, and cryptsetup can just reuse it.
-- Best Regards, Kairui Song
Hi Kairui,
On Tue, Apr 20, 2021 at 05:23:49PM +0800, Kairui Song wrote:
Hi,
Thanks a lot, these info are very helpful. Better to keep it for debugging for now, and ask users to use it very carefully.
On Tue, Apr 20, 2021 at 3:54 PM Milan Broz gmazyland@gmail.com wrote:
Hi,
TL;DR what you are trying to do is to actually reverse many security measures we added. It is perhaps acceptable for debugging but hardly for real generic system.
- using memory-hard function increases cost of dictionary and brute-force
attacks You can always decrease amount of memory needed, but you should do it only if you know that security margin is ok (like password is randomly generated with enough entropy).
- key is in keyring to remove possibility for normal userspace to receive
the key from kernel. Moreover, there is no need to retain kernel in keyring once dm-crypt device is activated. (It is still in kernel memory but only in crypto functions context). (Systemd also uses keyring to cache passphrase but that's different thing.)
You can still use old way for activation with --disable-keyring activation, but then you disable this possibility.
More comments below.
How about plan 3 and 4?
Have you got any reply from Milan about his input on plan 3 and 4? If so, can you forward his email(s) to me? Thanks!
- Let kdump use some custom helper/service to load all needed
resources in the early initrd boot stage, prior to systemd-cryptsetup@%s.service. It will ask the password / parse the keyfile and load kdump, then provide info for systemd-cryptsetup or just do the setup. Or maybe let systemd-cryptsetup support some kind of "plugins" so other tools can use it.
Some details could be changed/improved, but systemd-cryptsetup@%s.service will prompt for a password or use a keyfile anyway. So I think at this point, loading kdump with the volume key should be safe? At least long as the kdump kernel/environment itself isn't compromised. Loaded kdump resources can be restricted to be only accessible from the kernel side. After panic, kernel kexec jumps to kdump kernel, and that's an minimized emergency environment that only lives for a very short period.
- A better and safer solution seems to keep a consistent key ring
between kexec boots but also more complex and difficult as different arch implements kexec differently.
Maybe plan 4 will be a good idea if doable? Since that keeps the key consistent in the kernel between kexec boots, and cryptsetup can just reuse it.
-- Best Regards, Kairui Song
Hi Coiby,
So sorry to say that I forgot to back up some old emails so I lost them...
Plan 3 is not a good idea either. Making things too complicated and not safe.
Plan 4 is definitely the right choice, and no one was against it, and I vaguely remember it is doable as we were discussing. As the cryptsetup tool stores the device key as a logon key in kernel (logon so userspace can't access the key content), the idea to keep the logon key used by dm-crypt consistent in kernel over kexec reboot, just keep the reference in userspace (eg. pass a key-reference in kernel cmdline). cryptsetup tool in kdump kernel can just use that key reference to setup the dm-crypt device again. The only problem was that key have KEY_SPEC_THREAD_KEYRING flag, which means it's reference was no longer available in user space too after the initial cryptsetup thread exited. May need to loose this security measure a little bit, eg. to KEY_SPEC_GROUP_KEYRING? You can definitely reboot the discussion in the cryptsetup mail list.
Coiby Xu coxu@redhat.com 于2021年11月4日周四 下午6:05写道:
Hi Kairui,
On Tue, Apr 20, 2021 at 05:23:49PM +0800, Kairui Song wrote:
Hi,
Thanks a lot, these info are very helpful. Better to keep it for debugging for now, and ask users to use it very carefully.
On Tue, Apr 20, 2021 at 3:54 PM Milan Broz gmazyland@gmail.com wrote:
Hi,
TL;DR what you are trying to do is to actually reverse many security measures we added. It is perhaps acceptable for debugging but hardly for real generic system.
- using memory-hard function increases cost of dictionary and brute-force
attacks You can always decrease amount of memory needed, but you should do it only if you know that security margin is ok (like password is randomly generated with enough entropy).
- key is in keyring to remove possibility for normal userspace to receive
the key from kernel. Moreover, there is no need to retain kernel in keyring once dm-crypt device is activated. (It is still in kernel memory but only in crypto functions context). (Systemd also uses keyring to cache passphrase but that's different thing.)
You can still use old way for activation with --disable-keyring activation, but then you disable this possibility.
More comments below.
How about plan 3 and 4?
Have you got any reply from Milan about his input on plan 3 and 4? If so, can you forward his email(s) to me? Thanks!
- Let kdump use some custom helper/service to load all needed
resources in the early initrd boot stage, prior to systemd-cryptsetup@%s.service. It will ask the password / parse the keyfile and load kdump, then provide info for systemd-cryptsetup or just do the setup. Or maybe let systemd-cryptsetup support some kind of "plugins" so other tools can use it.
Some details could be changed/improved, but systemd-cryptsetup@%s.service will prompt for a password or use a keyfile anyway. So I think at this point, loading kdump with the volume key should be safe? At least long as the kdump kernel/environment itself isn't compromised. Loaded kdump resources can be restricted to be only accessible from the kernel side. After panic, kernel kexec jumps to kdump kernel, and that's an minimized emergency environment that only lives for a very short period.
- A better and safer solution seems to keep a consistent key ring
between kexec boots but also more complex and difficult as different arch implements kexec differently.
Maybe plan 4 will be a good idea if doable? Since that keeps the key consistent in the kernel between kexec boots, and cryptsetup can just reuse it.
-- Best Regards, Kairui Song
-- Best regards, Coiby
Hi Kairui,
On Thu, Nov 04, 2021 at 11:23:14PM +0800, Kairui Song wrote:
Hi Coiby,
So sorry to say that I forgot to back up some old emails so I lost them...
That's fine.
Plan 3 is not a good idea either. Making things too complicated and not safe.
Plan 4 is definitely the right choice, and no one was against it, and I vaguely remember it is doable as we were discussing. As the cryptsetup tool stores the device key as a logon key in kernel (logon so userspace can't access the key content), the idea to keep the logon key used by dm-crypt consistent in kernel over kexec reboot, just keep the reference in userspace (eg. pass a key-reference in kernel cmdline). cryptsetup tool in kdump kernel can just use that key reference to setup the dm-crypt device again. The only problem was that key have KEY_SPEC_THREAD_KEYRING flag, which means it's reference was no longer available in user space too after the initial cryptsetup thread exited. May need to loose this security measure a little bit, eg. to KEY_SPEC_GROUP_KEYRING?
According to [1], "using this feature dm-crypt no longer maintains a direct key copy (but there's always at least one copy in kernel crypto layer).". So maybe KEY_SPEC_THREAD_KEYRING isn't a problem since the master key is always there.
Another question seems to be more concerning is how we can retrieve the master key in the 2nd kernel? It seems currently there is no way to pass data from the 1st second to 2nd second kernel. I'm aware there is work using the so called "kexec buffer" to carrying the IMA measurement list across kexec. But the patches haven't been merged.
[1] https://gitlab.com/cryptsetup/cryptsetup/-/blob/master/docs/Keyring.txt
[2] https://lists.ozlabs.org/pipermail/linuxppc-dev/2016-November/150790.html
You can definitely reboot the discussion in the cryptsetup mail list.
Coiby Xu coxu@redhat.com 于2021年11月4日周四 下午6:05写道:
Hi Kairui,
On Tue, Apr 20, 2021 at 05:23:49PM +0800, Kairui Song wrote:
Hi,
Thanks a lot, these info are very helpful. Better to keep it for debugging for now, and ask users to use it very carefully.
On Tue, Apr 20, 2021 at 3:54 PM Milan Broz gmazyland@gmail.com wrote:
Hi,
TL;DR what you are trying to do is to actually reverse many security measures we added. It is perhaps acceptable for debugging but hardly for real generic system.
- using memory-hard function increases cost of dictionary and brute-force
attacks You can always decrease amount of memory needed, but you should do it only if you know that security margin is ok (like password is randomly generated with enough entropy).
- key is in keyring to remove possibility for normal userspace to receive
the key from kernel. Moreover, there is no need to retain kernel in keyring once dm-crypt device is activated. (It is still in kernel memory but only in crypto functions context). (Systemd also uses keyring to cache passphrase but that's different thing.)
You can still use old way for activation with --disable-keyring activation, but then you disable this possibility.
More comments below.
How about plan 3 and 4?
Have you got any reply from Milan about his input on plan 3 and 4? If so, can you forward his email(s) to me? Thanks!
- Let kdump use some custom helper/service to load all needed
resources in the early initrd boot stage, prior to systemd-cryptsetup@%s.service. It will ask the password / parse the keyfile and load kdump, then provide info for systemd-cryptsetup or just do the setup. Or maybe let systemd-cryptsetup support some kind of "plugins" so other tools can use it.
Some details could be changed/improved, but systemd-cryptsetup@%s.service will prompt for a password or use a keyfile anyway. So I think at this point, loading kdump with the volume key should be safe? At least long as the kdump kernel/environment itself isn't compromised. Loaded kdump resources can be restricted to be only accessible from the kernel side. After panic, kernel kexec jumps to kdump kernel, and that's an minimized emergency environment that only lives for a very short period.
- A better and safer solution seems to keep a consistent key ring
between kexec boots but also more complex and difficult as different arch implements kexec differently.
Maybe plan 4 will be a good idea if doable? Since that keeps the key consistent in the kernel between kexec boots, and cryptsetup can just reuse it.
-- Best Regards, Kairui Song
-- Best regards, Coiby
Coiby Xu coxu@redhat.com 于2021年11月5日周五 下午6:10写道:
Hi Kairui,
On Thu, Nov 04, 2021 at 11:23:14PM +0800, Kairui Song wrote:
Hi Coiby,
So sorry to say that I forgot to back up some old emails so I lost them...
That's fine.
Plan 3 is not a good idea either. Making things too complicated and not safe.
Plan 4 is definitely the right choice, and no one was against it, and I vaguely remember it is doable as we were discussing. As the cryptsetup tool stores the device key as a logon key in kernel (logon so userspace can't access the key content), the idea to keep the logon key used by dm-crypt consistent in kernel over kexec reboot, just keep the reference in userspace (eg. pass a key-reference in kernel cmdline). cryptsetup tool in kdump kernel can just use that key reference to setup the dm-crypt device again. The only problem was that key have KEY_SPEC_THREAD_KEYRING flag, which means it's reference was no longer available in user space too after the initial cryptsetup thread exited. May need to loose this security measure a little bit, eg. to KEY_SPEC_GROUP_KEYRING?
According to [1], "using this feature dm-crypt no longer maintains a direct key copy (but there's always at least one copy in kernel crypto layer).". So maybe KEY_SPEC_THREAD_KEYRING isn't a problem since the master key is always there.
Yes, it is still there, but the reference is dropped, so userspace no longer have the reference, and can't re-setup the dm-crypt. Kernel can't setup dm-crypt device by itself.
Another question seems to be more concerning is how we can retrieve the master key in the 2nd kernel? It seems currently there is no way to pass data from the 1st second to 2nd second kernel. I'm aware there is work using the so called "kexec buffer" to carrying the IMA measurement list across kexec. But the patches haven't been merged.
You can check "security/integrity/ima/ima_kexec.c" in kernel and also check git log of that file, this should be the IMA measure list carrying feature you are talking about? It's merged, the patch may get some other update before being merged, so it looks a bit different from that mail.
[1] https://gitlab.com/cryptsetup/cryptsetup/-/blob/master/docs/Keyring.txt
[2] https://lists.ozlabs.org/pipermail/linuxppc-dev/2016-November/150790.html
You can definitely reboot the discussion in the cryptsetup mail list.
Coiby Xu coxu@redhat.com 于2021年11月4日周四 下午6:05写道:
Hi Kairui,
On Tue, Apr 20, 2021 at 05:23:49PM +0800, Kairui Song wrote:
Hi,
Thanks a lot, these info are very helpful. Better to keep it for debugging for now, and ask users to use it very carefully.
On Tue, Apr 20, 2021 at 3:54 PM Milan Broz gmazyland@gmail.com wrote:
Hi,
TL;DR what you are trying to do is to actually reverse many security measures we added. It is perhaps acceptable for debugging but hardly for real generic system.
- using memory-hard function increases cost of dictionary and brute-force
attacks You can always decrease amount of memory needed, but you should do it only if you know that security margin is ok (like password is randomly generated with enough entropy).
- key is in keyring to remove possibility for normal userspace to receive
the key from kernel. Moreover, there is no need to retain kernel in keyring once dm-crypt device is activated. (It is still in kernel memory but only in crypto functions context). (Systemd also uses keyring to cache passphrase but that's different thing.)
You can still use old way for activation with --disable-keyring activation, but then you disable this possibility.
More comments below.
How about plan 3 and 4?
Have you got any reply from Milan about his input on plan 3 and 4? If so, can you forward his email(s) to me? Thanks!
- Let kdump use some custom helper/service to load all needed
resources in the early initrd boot stage, prior to systemd-cryptsetup@%s.service. It will ask the password / parse the keyfile and load kdump, then provide info for systemd-cryptsetup or just do the setup. Or maybe let systemd-cryptsetup support some kind of "plugins" so other tools can use it.
Some details could be changed/improved, but systemd-cryptsetup@%s.service will prompt for a password or use a keyfile anyway. So I think at this point, loading kdump with the volume key should be safe? At least long as the kdump kernel/environment itself isn't compromised. Loaded kdump resources can be restricted to be only accessible from the kernel side. After panic, kernel kexec jumps to kdump kernel, and that's an minimized emergency environment that only lives for a very short period.
- A better and safer solution seems to keep a consistent key ring
between kexec boots but also more complex and difficult as different arch implements kexec differently.
Maybe plan 4 will be a good idea if doable? Since that keeps the key consistent in the kernel between kexec boots, and cryptsetup can just reuse it.
-- Best Regards, Kairui Song
-- Best regards, Coiby
-- Best regards, Coiby