dex6 / sed-opal-unlocker

Micro-utility for unlocking TCG-OPAL encrypted disks
Apache License 2.0
33 stars 4 forks source link

System drive unlocking via partial locking ranges #3

Closed Tronic closed 2 years ago

Tronic commented 3 years ago

I am thinking of leaving both ends of the disk and the UEFI system partition unlocked, while setting lockingrange 1 to cover my Linux system partition. Kernel (built with efi stub and initramfs integrated and signed) loads from the unprotected EFI partition, and a tool in initramfs unlocks locking range 1 prior to mounting of filesystems.

Technically this should work but no-one seems to be doing anything like it. I think of trying with modifications on your tool (currently hardcoded for locking range 0) but do you know of any particular reason why this wouldn't work?

dex6 commented 3 years ago

This should be possible but I've never tried such configuration. If I recall correctly, sedutil can define locking ranges so assuming the disk has properly implemented firmware, and you have modified my tool, it should work.

Regarding the "why nots", the only obvious reason is that such configuration requires additional protections to kernel, etc. cause otherwise "evil maid" attack and adding a password logger to the initramfs may be quite trivial. But since you're planning to integrate and sign both, it should be safe. Remember to built-in and lock the kernel command line too, and password-protect the BIOS (otherwise anybody can disable Secure Boot and replace your kernel with something evil).

Tronic commented 3 years ago

Notes on findings so far:

dex6 commented 3 years ago

Note that sedutil password hashing is not "plain SHAx"; the algorithm is sedutil's invention (I think) and it uses disk serial number as a salt and therefore is not trivial to implement in my micro-tool itself. So if you use password hashing (sedutil without -n), you need to prehash your password with sedutil-passhasher.py python script. See README for more info.

For similar reason, probably your UEFI Firmware just uses plaintext password to unlock drive and fails. You may verify it by initializing the drive with sedutil -n (disable hashing) and then try unlocking with UEFI. (To avoid potential encoding problems, ASCII-only password recommended.)

Regarding the locking only on power loss, that's how SED OPAL drives work. My system also locks the drive when it goes to S3 sleep, so do yours probably, cause S3 should cut power from the drive. Probably "regular reboot" is not something the drive can tell just from ATA/SCSI/NVMe commands it receives from firmware during initialization. The best workaround you can do is locking the drive in your initramfs just before asking for the password to unlock it.

Tronic commented 3 years ago

Update: I have been using the ladar fork of sedutil-cli, which uses SHA-512 but with 75000 iterations (instead of the 500000 of the ChubbyAnt fork). Modifying the source code of your tool allowed replicating the same hash and consequently unlocking my ranges. And yes, LockingRange 1 works well too.

The ladar fork also supports input of passwords in hex and can print the current password hash in hex, both of which can be useful with the no-hashing option. Unfortunately there is no support (in any sedutil fork) for migration between hashing styles and for some reason attempting the password change with hex hashes gives INVALID_PARAMETER. I will need to dig deeper in the source code to find out why (the hex hash works fine with other commands and password changes work fine when I let sedutil do the hashing).

EDIT: Apparently the hex and no-hashing options were not correctly handled in the password change functions. Some source code hacking to skip hashing the new password, and now my drives are back to plain text passwords. Might do custom Argon2 key derivation or something but not gonna let sedutil do any more hashing.

Tronic commented 2 years ago

I am settled with my current hack but it seems that I won't have time to make a generic patch that would enable this for other users. This is unfortunate but hopefully someone else who is interested can find the documentation here useful.

Summary: Partial Locking Ranges for system partition / RAID work great. Need to have unencrypted UEFI system partition and on it systemd-boot & sed-opal-unlocker (with source code modified to use LR = 1). My script needs to assemble the unlocked RAID manually and then systemd finds it and immediately boots into normal mode (killing any local shell or ssh connection I had to initrd to do the unlocking). MUCH faster boot than with traditional PBA, and doing it over ssh is nicer on a headless server.

Tronic commented 10 months ago

Typically you would only allow UEFI Secure Boot to your trusted system, where soft reboots don't pose a security risk. Be sure to remove the Microsoft keys and only have your own if you use this for protection.

Tronic commented 10 months ago

@youk It is a big security risk if you don't mitigate properly.

You can sign your systemd-boot and kernel with your own UEFI keys. That's what I do, because forensics tools surely will be Microsoft-signed.

Dracut can build kernel+initrd+cmdline combined images that are EFI executable and signed by it such that none of the three components can be altered. Use sbctl to create and control your UEFI keys from Linux. When the boot loader and unified kernel image are signed with your own keys and you don't have the Microsoft keys at all, no untrusted code can boot on that machine. Entering UEFI setup to alter settings does a hard power cycle (at least on ASUS motherboards), clearing the disk keys (and you ought to have a setup password anyway). If you are paranoid, keep the signing keys off that machine, but for automatic kernel updates you might prefer keeping them on an encrypted rootfs (Arch-based distros at least do Dracut kernel upgrades automatically then).

GRUB AFAIK doesn't really do secure boot, so ditch that and the Ubuntu shim (your grub.conf can be freely manipulated by attackers). Systemd-boot is better anyway and doesn't require any config file, it auto discovers the kernel image under EFI/Linux folder. Alternatively, your UEFI firmware can directly boot the unified kernel image without any boot loader, provided you name it EFI/boot/bootx64.efi on the EFI partition.

Surely it is still not 100% secure, as a running system can potentially be hacked, or someone could deliver power to the drive externally, avoiding the reset by ATX power-off, but I think it would suffice in all normal situations one might encounter with theft or the law enforcement. If you are not Edward Snowden or something...

There is a kernel module to instantly power off when an unknown USB device is attached. One can implement other traps for instant power-off too, to dodge hacking attempts. These of course help with both software encryption and with drive encryption.

Tronic commented 10 months ago

That's one way to mitigate but an attacker can still warm boot their own Microsoft-signed system from a USB drive (UEFI firmware will automatically load any boot loader found, including USB drives, if it for any reason cannot boot the configured boot options, even if no USB drives are included in those).

Tronic commented 10 months ago

You cannot disable boot from USB, it seems. As I said, the firmware boots from USB anyway as a fallback. Perhaps if you entirely disable USB controllers in firmware setup, but not by removing the boot option, and one could still plug in a SATA or other drive for which the controller is enabled.