EFI GELI support ready for testers
Eric McCorkle
eric at metricspace.net
Fri May 27 23:39:59 UTC 2016
I am pleased to announce that my work to add support for GELI in the EFI boot loader (as well as perform more general refactoring) is now ready for testing. I am able to successfully detect multiple GELI partitions in boot1 and pass the keys into the kernel.
My work can be found here: https://github.com/emc2/freebsd/tree/geli_efi
Also of note is the efize branch, which I posted about two weeks ago. I have not yet merged this with master, but I will begin doing so on a regular schedule.
I have left the LOADER_PATH variable as "/boot/loader.tst" If you plan on testing this, I *strongly* recommend the following procedure:
* Be aware that because of the nature of this patch, A PROBLEM COULD RESULT IN YOUR FILES BEING INACCESSIBLE! Take necessary precautions to protect your data, read carefully, ask before you leap, and proceed with caution!
* Read and understand thoroughly the basics of EFI and the FreeBSD boot architecture before you do anything.
* Install an EFI shell program on your ESP.
* Install the modified boot1 to something like /efi/boot/bootx64.tst on your ESP
* Install the modified loader to /boot/loader.tst
* Try creating an auxiliary encrypted partition containing unimportant data first
* After this, try a minimal root image on the auxiliary partition.
* Only move to an encrypted root once you have tried the above steps, and BACK UP YOUR DATA FIRST.
I have personally done the following tests on this:
* Detect ZFS filesystem at boot (ZFS checksum verification gives a high level of certainty that decryption is correct)
* Load a kernel and multiple modules from a ZFS partition and boot them.
* AES CBC and XTS encryption (see notes on limited GELI feature support)
* Multiple encrypted partitions with different keys, both shared and different pass phrases.
* Ensure that keys are passed into the kernel properly.
Normally I would convert my own system and wait a week or two; however, the graphics update 4.6 testing is going on, and I want to make sure my hardware (purism laptop) is accounted for in that. Two experimental patches is just too much branch management (especially when a misstep would effectively destroy all my files!)
Due to the scope of this changeset and the material risks associated with it, I am NOT recommending that it be considered for the 11 release. It's just too close to be adding something like this.
A note on GELI feature support: the current GELI boot code does not support all features. Only AES encryption is supported, only 512 block sizes are supported, authentication is not supported, and key files are not supported. (These are limitations inherited from the GELI boot code, and my refactoring a may make them easier to address). Make sure not to use an unsupported mode!
The contents of this work break down into roughly four areas, which apply in the following order:
EFI Refactoring: see my earlier mail for full details. The abridged version is that the EFI boot1 and loader are refactored to make much greater use of the EFI API. Filesystems are now managed by attaching an EFI_SIMPLE_FILE_SYSTEM_PROTOCOL interface. The filesystem drivers in loader have been replaced with a single driver that talks through this interface. This allows loader to use any filesystem driver installed by itself, boot1 or another tool, or the native firmware. This refactoring also puts both boot1 and loader on a common code base driver-wise, eliminating the duplication that previously existed. I was unable to move the efipart and backend filesystem drivers fully into the EFI driver model, however, as the bcache code is fundamental built on the model of static detection.
Boot Crypto: this is a small refactoring that moves crypto code out of the existing geliboot code and into a common framework. This should make the business of adding new ciphers easier. A difficulty with this is resolving the need for building a 32-bit version of the library for legacy BIOS geliboot, as well as a native version for EFI. I currently resolve this by building a static library for EFI, and including the source files in the BIOS make files. If someone with a better handle on the build system could figure out how to build both a 32-bit and native version of the library, I'd be grateful.
GELI EFI driver: this is simply an EFI driver that detects GELI partitions and creates a new device handle with a EFI_BLOCK_IO_PROTOCOL interface implementing access to the partition. This driver, as well as the kernel KMS driver could be exported from the FreeBSD sources and contributed to the likes of GRUB without much trouble.
Kernel key intake framework: this adds a kernel interface (and one that will likely be imminently useful, at the very least to the BIOS GELI support), so it warrants further discussion:
* On the boot/loader side, there is a "kernel injector KMS" driver which creates a device handle that implements the EFI_KMS_PROTOCOL. The GELI driver attempts to obtain the handle supporting this interface, and uses it to report both GELI pass phrases as well as the raw keys as it discovers them. It also uses the handle to obtain previous keys and passphrases, and tries the before asking for a new passphrase.
* The kernel injector KMS uses the register client function to inform the KMS of a kernel. This is done in the same code path that adds metadata to the kernel image (the existing metadata is how the kernel gets the EFI frame buffer info, among other things)
* On the kernel side, a new kind of metadata is added for the key intake buffer. A simple interface for accessing the key intake buffer is presented in crypto/intake.h
* The GELI kernel-side code has been modified to check the intake buffer when detecting GELI partitions at boot before asking for a passphrase.
* The existing environment variable used by the BIOS GELI support has been left alone. However, it would probably be a good idea to move to the key intake buffer, as it is more featureful and marginally more secure.
A guiding principle behind this design was the desire to make it easy to add support for hardware-based key storage options. This is why I used KMS interfaces on the EFI side. I also designed it to support a wider range of keys than what GELI alone needed, intending for it to become a common interface for communicating keys from the loader to the kernel.
Let me know if there are any questions about this work. I would prefer that it undergo a period of testing before moving towards commit (which is necessary anyway in light of the upcoming release).
More information about the freebsd-hackers
mailing list