Hi,
On 06-12-18 11:04, Javier Martinez Canillas wrote:
Hello,
On 12/5/18 9:20 PM, Hans de Goede wrote:
[snip]
Javier and Peter (added to the Cc) have been working on making full-disk encryption storing the secret in the tpm work.
This is what Windows with bitlocker does and what most smart phones do now (more or less).
Yes. The clevis project has TPM2 support since Fedora 28, so you can bind a LUKS volume to a TPM2 and it will automatically be unlocked on boot but only on that machine.
The idea here is (Javier / Peter please correct me if I'm wrong) that the firmware send a hash of itself to the tpm and a hash of the bootloader, and the bootloader sends a hash of the kernel + initrd to the tpm.
The tpm hashes all these hashes together and when the kernel wants to access the encrypted root filesystem, it asks the tpm for the key, if all the hashes together match what the tpm expects it will give the key. This means that even if someone steals the entire laptop he cannot modify anything, the rootfs is crypted so it cannot be modified without the key and everything which comes before it is hashed so it cannot be replaced either. This leaves the attacker essentially stuck at the gdm login prompt. An advanced adversary will certainly be able to find a way around this, but it is a good level of security to start with.
This gives us full disk encryption without the need to ask for a diskcrypt password from plymouth (in the initrd) or from grub at all. Thus avoiding all downsides wrt keymaps and the lack of other advanced input methods like having e.g. a pinyin input method. This also avoids other internationalization issues like font-rendering of non western scripts.
This is correct, but we still don't have all the needed pieces. Both shim and grub2 currently measures all the components in the boot path: Secure Boot configuration, all certificates from the cert databases, shim, grub2 binaries, grub commands executed, kernel, kernel cmdline and the initrd.
What we are missing is a robust mechanism to to re-seal the LUKS key every time that one of these components is updated. If this process is fragile, you may end with an unbootable system (you always have the pass-phrase as fallback though).
Until we have a way to re-seal the secrets, binding to a TPM will make the system less secure since it means that an attacker could just replace the initramfs or your kernel cmdline an unlock your encrypted disk easily.
It's useful though for other use cases like VM or servers.
Also, the measurements will change if you boot different kernels so it has to support multiple valid PCR states. We could for example have a different LUKS key sealed against different PCR sates for each kernel. But that means a maximum of 7 as Chris pointed out (since slot 0 will be the fallback key).
My understanding is that even Windows doesn't do this, but instead what they do is to seal the KEK only against PCR7 that contains the Secure Boot policy:
https://docs.microsoft.com/en-us/previous-versions/windows/hardware/hck/jj92...
So basically what they do is to combine TPM measurements with Secure Boot to make sure that your encrypted disk is only decrypted if all the binaries are signed.
We could also do the same but the problem is the initramfs. My guess is that Windows doesn't have that limitation and their plain text boot partition has everything that's needed to decrypt the root partition. So they can just sign the kernel and drivers to make sure that the system has not been tamper with.
Hmm, so if we sign the initramfs and make grub or the kernel check this, then we could do what Windows does without the re-sealing issue, right?
We've discussed moving to an initramfs which is pre-generated on the buildsystem in the past, if we do a separate initramfs for network boots, then this will actually not grow the initrams all that much (*) and this would allow signing the initramfs.
To me this sounds like a saner path then trying to hash all boot path components and re-seal all the time. One thing which would still be an issue with this is the kernel commandline. But the kernel commandline does not change on kernel updates, so we could perhaps use a combination of Secure Boot policy + kernel commandline hash to unlock the disk encryption key?
*) And we could spend some time to see if we can cut down the size a bit
This is a guess though, I know nothing about Windows internals.
On top of this we could do what Ubuntu does and encrypt home directories at the filesystme level using the password the user uses to login to protect/unlock the key for this. The downside of this is that all the file metadata (filename, size) is not encrypted, but the contents is and this would come *on top of* the full disk encryption using the tpm. The advantage of using filesystem level per file encryption this way is that it avoids the diskspace problem entirely.
Ubuntu does not support this anymore btw. They used to support encrypting the home directory using ecryptfs and decrypting automatically through PAM login, but now they dropped that and support encrypting the root volume using dm-crypt and LUKS like we do in Fedora. I don't know why they decided to change that but this launchpad says that ecryptfs-utils is "buggy, under-maintained, not a fit":
https://bugs.launchpad.net/ubuntu/+source/ecryptfs-utils/+bug/1756840
Ah, right so it seems that we would need to use fscrypt and not ecryptfs, my bad. fscrypt still has an active upstream and is very much supported by its upstream AFAICT.
Regards,
Hans
On Thu, Dec 6, 2018 at 11:49 AM Hans de Goede hdegoede@redhat.com wrote:
Hi,
On 06-12-18 11:04, Javier Martinez Canillas wrote:
Hello,
On 12/5/18 9:20 PM, Hans de Goede wrote:
[snip]
Javier and Peter (added to the Cc) have been working on making full-disk encryption storing the secret in the tpm work.
This is what Windows with bitlocker does and what most smart phones do now (more or less).
Yes. The clevis project has TPM2 support since Fedora 28, so you can bind a LUKS volume to a TPM2 and it will automatically be unlocked on boot but only on that machine.
The idea here is (Javier / Peter please correct me if I'm wrong) that the firmware send a hash of itself to the tpm and a hash of the
bootloader,
and the bootloader sends a hash of the kernel + initrd to the tpm.
The tpm hashes all these hashes together and when the kernel wants to access the encrypted root filesystem, it asks the tpm for the key, if all the hashes together match what the tpm expects it will give the key. This means that even if someone steals the entire laptop he cannot modify anything, the rootfs is crypted so it cannot be modified without the key and everything which comes before it is hashed so it cannot be replaced either. This leaves the attacker essentially stuck at the gdm login prompt. An advanced adversary will certainly be able to find a way around this, but it is a good level of security to start with.
This gives us full disk encryption without the need to ask for a diskcrypt password from plymouth (in the initrd) or from grub at all. Thus avoiding all downsides wrt keymaps and the lack of other advanced input methods like having e.g. a pinyin input method. This also avoids other internationalization issues like font-rendering of non western scripts.
This is correct, but we still don't have all the needed pieces. Both shim and grub2 currently measures all the components in the boot path: Secure Boot configuration, all certificates from the cert databases, shim, grub2 binaries, grub commands executed, kernel, kernel cmdline and the initrd.
What we are missing is a robust mechanism to to re-seal the LUKS key
every
time that one of these components is updated. If this process is fragile, you may end with an unbootable system (you always have the pass-phrase as fallback though).
Until we have a way to re-seal the secrets, binding to a TPM will make
the
system less secure since it means that an attacker could just replace the initramfs or your kernel cmdline an unlock your encrypted disk easily.
It's useful though for other use cases like VM or servers.
Also, the measurements will change if you boot different kernels so it
has
to support multiple valid PCR states. We could for example have a
different
LUKS key sealed against different PCR sates for each kernel. But that
means
a maximum of 7 as Chris pointed out (since slot 0 will be the fallback
key).
My understanding is that even Windows doesn't do this, but instead what
they
do is to seal the KEK only against PCR7 that contains the Secure Boot
policy:
https://docs.microsoft.com/en-us/previous-versions/windows/hardware/hck/jj92...
So basically what they do is to combine TPM measurements with Secure
Boot to
make sure that your encrypted disk is only decrypted if all the binaries
are
signed.
We could also do the same but the problem is the initramfs. My guess is
that
Windows doesn't have that limitation and their plain text boot partition
has
everything that's needed to decrypt the root partition. So they can just
sign
the kernel and drivers to make sure that the system has not been tamper
with.
Hmm, so if we sign the initramfs and make grub or the kernel check this, then we could do what Windows does without the re-sealing issue, right?
We've discussed moving to an initramfs which is pre-generated on the buildsystem in the past, if we do a separate initramfs for network boots, then this will actually not grow the initrams all that much (*) and this would allow signing the initramfs.
I had a conversation with Harald Hoyer this week and he's not against the idea of the "deterministic" initramfs.
He tried to do this in the past and there were some concerns about creating an rpm that did not include the source code of its binaries to comply with GPL and whatnot. We'd need to crack that problem but otherwise we could achieve this and it would save many headaches.
To me this sounds like a saner path then trying to hash all boot path
components and re-seal all the time. One thing which would still be an issue with this is the kernel commandline. But the kernel commandline does not change on kernel updates, so we could perhaps use a combination of Secure Boot policy + kernel commandline hash to unlock the disk encryption key?
*) And we could spend some time to see if we can cut down the size a bit
This is a guess though, I know nothing about Windows internals.
On top of this we could do what Ubuntu does and encrypt home directories at the filesystme level using the password the user uses to login to protect/unlock the key for this. The downside of this is that all the
file
metadata (filename, size) is not encrypted, but the contents is and this would come *on top of* the full disk encryption using the tpm. The advantage of using filesystem level per file encryption this way is that it avoids the diskspace problem entirely.
Ubuntu does not support this anymore btw. They used to support
encrypting the
home directory using ecryptfs and decrypting automatically through PAM
login,
but now they dropped that and support encrypting the root volume using
dm-crypt
and LUKS like we do in Fedora. I don't know why they decided to change
that but
this launchpad says that ecryptfs-utils is "buggy, under-maintained, not
a fit":
https://bugs.launchpad.net/ubuntu/+source/ecryptfs-utils/+bug/1756840
Ah, right so it seems that we would need to use fscrypt and not ecryptfs, my bad. fscrypt still has an active upstream and is very much supported by its upstream AFAICT.
Regards,
Hans
On Thu, Dec 6, 2018 at 4:28 AM Alberto Ruiz aruiz@redhat.com wrote:
I had a conversation with Harald Hoyer this week and he's not against the idea of the "deterministic" initramfs.
Host only initramfs is ~ 18MiB to 24MiB. Whereas a generic initramfs is ~70MiB. That's 3x larger. Load time goes from 2.5s to 7.5s. And /boot requires more storage since there are four initramfs files by default.
Hi,
On 06-12-18 20:00, Chris Murphy wrote:
On Thu, Dec 6, 2018 at 4:28 AM Alberto Ruiz aruiz@redhat.com wrote:
I had a conversation with Harald Hoyer this week and he's not against the idea of the "deterministic" initramfs.
Host only initramfs is ~ 18MiB to 24MiB. Whereas a generic initramfs is ~70MiB. That's 3x larger. Load time goes from 2.5s to 7.5s. And /boot requires more storage since there are four initramfs files by default.
For me it is 20MB normally, 50MB for a generic initramfs.
So I've taken a quick look at shrinking this, which turns out to not be all that easy. A more interesting approach might be to figure out why this takes so much time, AFAIK this time does not include the actual loading from the disk as that happens before measurements start, so for some reason the kernel is taking 7.5 seconds to unpack the initrd.
One possible solution would be to create a generic initrd for popular hardware and a complete initrd for other hw, such a generic initrd should be able to cover 90 - 95% of all hardware.
The tricky part with this would be to write code to decide which initrd to use. But we could use a whitelist based approach here, where we check that / is:
a) On a filesystem supported by the generic initrd b) Backed by block layers (lvm / dmcrypt) which are supported by the generic initrd c) Backed by a "physical" blockdev supported by the generic initrd
And only then use the generic initrd, the code for this can be borrowed from dracut's existing code to detect which modules to load. Thinking more about this, we should probably have dracut itself provide a tool which we can run at install time to decide which initrd to use.
This might be as simple as building a hostonly initrd and checking all the files in the hostonly initrd are in the generic initrd.
Regards,
Hans
desktop@lists.stg.fedoraproject.org