Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for unsealing certain files at boot with TPM #108

Open
HPsaucii opened this issue Nov 1, 2024 · 7 comments
Open

Add support for unsealing certain files at boot with TPM #108

HPsaucii opened this issue Nov 1, 2024 · 7 comments

Comments

@HPsaucii
Copy link

HPsaucii commented Nov 1, 2024

So, i was intruiged about having a setup where a LUKS header is TPM sealed, so that even if someone has access to the file, i can retain a level of plausible deniability. I noticed that there is a pre-existing issue for unlocking a luks drive with TPM, but as you can tell, thats not exactly what i want. Other than that, ugRD is an amaxing piece of software 😄

@desultory
Copy link
Owner

I'm interested in the idea of adding some kind of TPM support, but I'm not sure how to reasonably do that.

I think the best way would involve writing context info to the nvram, but that means that could be read, and it would reveal that there is sealed data.

If you were to put that context in the initramfs image, that means you can't really use that initramfs to seal the data, since writing that context would change the hash.

If the context were stored on external storage, then you're just using the TPM to help a bit, but what do you seal it against?

https://github.com/desultory/cattleguard/blob/main/tpm_wrapper.py
I started working on that to wrap this TPM stuff a bit, but generally get to a point where I wonder why I would use that over a Yubikey. If you have any ideas to make this process a bit more straightforward and secure, I'm interested, but TPMs seem to have far more considerations than clear benefits.

I wrote a lot of this to try to learn the process more, and was able to perform some sealing/unsealing.
https://wiki.gentoo.org/wiki/Trusted_Platform_Module#Unseal_data
The issue is just where to put that context and how to handle re-sealing data when things change.

Additionally, if you were to seal your headers, then PCRs change, you may permanently lose access to those headers.

@HPsaucii
Copy link
Author

HPsaucii commented Nov 1, 2024

Yeah, im certainly not a wizard regarding TPM, and it does seem difficult to implement securely.

In terms of hard reasons why, it would mean that its effectively impossible to prove that you have an encrypted drive, as opposed to just random data, unless someone had access to your physical device and your boot drive, rather than just one of the other that comes with ususal mon-detatched / detatched headers. I have a yubikey, but the issue then becomes that when unlocking the drive, you cant assign multiple passwords that must be used in unison to unlock the drive, hence the reason i use a gpg-encrypted key file

@desultory
Copy link
Owner

I generally treat the header itself as a key/factor, it essentially is one. If you wanted to, you could have one USB for the header, and one for the initramfs. Currently, ugrd doesn't have any mechanism to cache the header, but that wouldn't be hard to implement, in case you wanted to only have it attached for a short period of time.

I feel it may be more worthwhile to try to support gpg encrypted header files too, I sorta expanded the keyfile mechanism to allow for some data to be stored in /run, the same could be done for the header, that also acts as a bit of a cache mechanism.

@HPsaucii
Copy link
Author

HPsaucii commented Nov 5, 2024

yeah, gpg encrypted header files would be nice, also, it'd be nice if there was an option to wait for a disk to appear before trying to mount it, rather than the current system of guestimating the time for increased UX, even though thats unrelated to the original topic of this issue

@desultory
Copy link
Owner

yeah, gpg encrypted header files would be nice, also, it'd be nice if there was an option to wait for a disk to appear before trying to mount it, rather than the current system of guestimating the time for increased UX, even though thats unrelated to the original topic of this issue

If you set mount_wait to true, it should wait for the user to press enter before attempting to mount anything. The timeout between attempts (for automatic usage) is set with mount_timeout. This is a bit of a hack but it provides a bit of automation where something like udev is not used.

Concerning gpg encrypted headers, I need to consider this carefully, the current "mount generator" for cryptsetup is getting quite complex, mostly because plymouth support means there have to be multiple methods to get keys/pins/etc, and I want to be sure that it always deletes key files after they are used without any chance that it touches the original key. If the keys are left in /run or somewhere like that, that's really bad. If ugrd deletes your keyfile, that is probably worse.

@HPsaucii
Copy link
Author

HPsaucii commented Nov 7, 2024

Yeah 100%, simplicity is often key, and thats why i use ugRD over dracut, because its just too damn complicated. In terms of the mount stuff, i have the timeout setup, but itd be nice if it could listen for when the mentioned disk is mounted or something? Like, having a fixed timeout / confirmation does work, but as you mentioned its quite hacky

@desultory
Copy link
Owner

Yeah 100%, simplicity is often key, and thats why i use ugRD over dracut, because its just too damn complicated. In terms of the mount stuff, i have the timeout setup, but itd be nice if it could listen for when the mentioned disk is mounted or something? Like, having a fixed timeout / confirmation does work, but as you mentioned its quite hacky

Currently the only option is to set mount_wait = true, if it were to wait for a device it would need to either handle udev events or constantly poll. The current solution is essentially just constant polling where you can adjust the total number of times it attempts to mount the device as well as the timeout.

Here, simplicity has a bit of a cost. There is no daemon running in the background watching for hardware changes, just a simple shell script. The initial mounts serve as a bit of a checkpoint, because if that step fails, the whole thing restarts. Originally, there was no timeout, you simply had to press enter once things were mounted. This was potentially very fast if you were paying attention and watching the kernel log, or you could just mash enter and it would eventually work.

My main concern trying to catch the storage being added, is how do you even really know it's the right device? What if it was already detected before that phase runs? Does it just hang when it can't see the device but it's there? I think it's simpler to just try to mount it a few times, or let the user press enter when ready.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants