Date: Sun, 29 May 2016 10:10:16 -0400 From: Eric McCorkle <eric@metricspace.net> To: Konstantin Belousov <kostikbel@gmail.com> Cc: Allan Jude <allanjude@freebsd.org>, freebsd-hackers@freebsd.org Subject: Re: EFI GELI support ready for testers Message-ID: <46B3F9E2-A25B-4F9D-B35F-11AC782495B1@metricspace.net> In-Reply-To: <20160529091827.GD38613@kib.kiev.ua> References: <519CC1FC-84DF-4710-8E62-AF26D8AED2CF@metricspace.net> <20160528083656.GT38613@kib.kiev.ua> <d6b96a6c-4e92-35a5-e78b-cc674b6d2f25@freebsd.org> <20160528172618.GB38613@kib.kiev.ua> <6A9DADE0-B214-424A-BB14-0B0848F0D08D@metricspace.net> <20160529091827.GD38613@kib.kiev.ua>
next in thread | previous in thread | raw e-mail | index | archive | help
> On May 29, 2016, at 05:18, Konstantin Belousov <kostikbel@gmail.com> wrote= : >=20 >> On Sat, May 28, 2016 at 04:02:43PM -0400, Eric McCorkle wrote: >>=20 >>>> On May 28, 2016, at 13:26, Konstantin Belousov <kostikbel@gmail.com> wr= ote: >>>>=20 >>>>> On Sat, May 28, 2016 at 10:27:40AM -0400, Allan Jude wrote: >>>>>> On 2016-05-28 04:36, Konstantin Belousov wrote: >>>>>> On Fri, May 27, 2016 at 07:39:57PM -0400, Eric McCorkle wrote: >>>>>> I am pleased to announce that my work to add support for GELI in the E= FI boot loader (as well as perform more general refactoring) is now ready fo= r testing. I am able to successfully detect multiple GELI partitions in boo= t1 and pass the keys into the kernel. >>>>>=20 >>>>> Can somebody explain in which way this is useful ? >>>>> Same question for the GELI code for non-EFI loader. >>>>>=20 >>>>> BIOS cannot read raw data from the encrypted partition, so you need >>>>> either old boot or the loader and some additional data on EFI boot >>>>> partition anyway. >>>>>=20 >>>>> Features adds significant amount of code, which must be maintained in >>>>> parallel with the kernel code. >>>>> _______________________________________________ >>>>> freebsd-hackers@freebsd.org mailing list >>>>> https://lists.freebsd.org/mailman/listinfo/freebsd-hackers >>>>> To unsubscribe, send any mail to "freebsd-hackers-unsubscribe@freebsd.= org" >>>>=20 >>>> The motivation for my work (GELI in boot2 and loader for non-EFI boot) >>>> was supporting ZFS boot environments. Previously, when you use GELI you= >>>> needed to have two ZFS pools, one for an unencrypted /boot and one for >>>> the encrypted / >>>>=20 >>>> This breaks ZFS boot environments, since a snapshot of the root file >>>> system won't include the correct kernel etc. >>> Why cannot /boot included into the boot environment ? >>> When I last saw Solaris, somewhere in its 10-th, any amount of >>> filesystems could be added to the bootenv. But whatever the definition >>> of bootenv is used, it exists at a level of the shell scripts and select= ing >>> the actual partition for loader. Throw thousand lines of code into >>> the unstable and very hard to debug environment of loader looks somewhat= >>> unproductive. >>=20 >> You misunderstand. Alan was talking about pure ZFS systems, where there i= s one big ZFS pool holding everything. You need to be able to access /boot o= bviously, but ZFS does not allow you to assign separate out data on to a sin= gle device. It creates a pool, which combines all devices. >>=20 >> To have /boot unencrypted, you have to have a separate partition for just= /boot, which is undesirable. > Why it is undesirable ? You must have EFI boot partition by any means. >=20 > And why it is simultaneously desirable to add a bunch of code to loader > to hide this ? >=20 It's undesirable because the whole point of ZFS is to have one ZFS volume fo= r the whole system. The ESP is a minor annoyance that's unavoidable. But h= aving to have a UFS volume or two ZFS systems just so I can keep the kernel,= loader, and all the modules unencrypted is bad. >>=20 >>>>=20 >>>> The final version of my geliboot took an extra effort to reuse the AES >>>> code from sys/crypto/rijndael and sys/opencrypto and GELI directly from= >>>> sys/geom/eli to avoid maintaining a separate copy of that code in sys/b= oot >>> Which means that kernel code must be also runnable in the strange and >>> incompatible environment of the loader. I cannot see how this reduces >>> code maintanability even a bit. I am already rather unhappy about ZFS >>> kernel code being compiled as the userspace library, which hurt me >>> and other people more than once. Now (?) the kernel code must be also >>> verified for the loader. >>=20 >> I mean, the loader has to be able to access the filesystems, there's no w= ay around it (barring crazy coreboot stuff). >>=20 >> Also, it should be possible to create a synthetic EFI test-harness that r= uns in *userland*. EFI is basically just a bunch of tables of function point= ers, no bios interrupts or anything. As long as you implement the interface= s, any loader should also run in your synthetic environment. I had plans to= look into this after this work is done. > Of course EFI is not 'just a bunch of tables'. It might look so when you > have tunnel vision and all you do is writing code making calls, but it > is definitely not when you consider it as a part of platform. =46rom the standpoint of building a synthetic test environment to make it ea= sy to test and debug boot and loader code, it is. > UEFI makes it absurdly easy to distribute a code that gets executed on > every boot before boot loaders. The most straighforward is to put UEFI > driver binary into the UEFI FAT and register it into some variables (too > lazy to remember details). You get this way both boot- and runtime- > injection, officially supported. This was one of the reason for secure > boot. >=20 > To avoid trivial debunks, I put a note that of course drivers are not > the only way for such code to appear on the system, without > requiring any hardware modifications. The rich programming environment, > with flat memory and full control over hardware, with easily explorable > data structures, with documented and compatible ways to get code > persistent are the characteristics of it. >=20 > It is much easier to target such preboot env then to maintain dynamic > list of the userspace escalation code. Ok fine. But this is a risk anyone using EFI has to assume, and it doesn't e= nd at the boot environment. There are plenty of nasty tricks an EFI boot en= vironment can play that affect the OS as well. It's simply impossible for a= n OS to provide reliable security when the hardware or firmware is compromis= ed, and this isn't limited to the boot loader. This kind of thing is the reason for projects like coreboot gaining traction= . If you really don't trust EFI, then the right answer is to use something l= ike coreboot, or else don't use a system with EFI. Trying to compensate for= this by keeping stuff out of the boot loader (and exposing vital parts of y= our system in a powered-off state) is futile, as a determined attacker can j= ust set things up to compromise the kernel anyway. >=20 >>>>=20 >>>> Hopefully the work I did to make sys/opencrypto and sys/geom/eli more >>>> reusable outside of the kernel will make it easier for Eric to do the >>>> same for the EFI version. >>>>=20 >>>> The motivation for the EFI version is the same, ZFS boot environments, >>>> plus the obvious security advantages of having the kernel stored >>>> encrypted rather than not. >>>=20 >>> Obvious security advantages ? Seriously ? >>> What is a single 'security' advantage of hiding the kernel ? >>=20 >> There are plenty. >>=20 >> Right up at the top, an attacker able to access /boot is free to tamper w= ith anything, and can insert back-doors into the kernel, loader, or any modu= le. If you assume that the attacker can't write, then they can still scan t= he kernel and modules for signatures for known vulnerabilities (since the ke= rnel itself has a commit id and detailed version info, they can compare this= against a CVE database). Even if they can't do that for some reason, they c= ould still potentially exfilt a kernel address map for use in rootkit attack= s against your system. Lastly, general security principles say to minimize t= he attack surface, which would definitely mean you should protect the core o= f the system. > I cannot believe that somebody considers hiding kernel binary even > remotely viable 'security' measure. But let me accompany that for a > second and see what attack surface does the attacker get from knowing > the kernel binary ? What you completely ignore in all this is the capability for an attacker to t= amper with the unencrypted kernel, loader, and drivers. > =46rom inspecting quirks in the syscalls it is (almost trivially) easy > to reconstruct the date of kernel sources up to probably month, without > causing much observable havoc in the system. The kern.osreldate is around= > as well, not only as sysctl, but also having some impact on the runtime > behaviour of several syscalls and image activators. >=20 > Same fingerprints are available from the sizes of the objects in UMA > zones, readily available from vmstat -z. Changes in the basic kernel > structures layout are reflected in the size changes. >=20 > Facilities like procstat -kk would show code reorganization and refactorin= g > changes. >=20 > The list above was written after about 10 minutes spent on thinking how > to identify the system sources without having access to binaries. I > believe another 10 minutes would give even more suggestions. This is all academic. Yes, maybe someone can piece together what version of= things I'm running. Of course, they'd have no idea what my address map loo= ks like, unless they can get my compiler version and custom kernel config. M= aybe there's some way to do that too. But they get all of this with 100% accuracy by scanning the unencrypted boot= partition, AND they can tamper with any of it. It's *just* less secure, pl= ain and simple. >=20 >=20 >>> Since you noted a 'security', I realized that your changes decrypt the >>> keys in the pre-kernel environment. In other words, very sensitive >>> material becoming accessible to strange and unknown code which is >>> managed by firmware. >>=20 >> The likelihood of such an attack, while something I considered, is very l= ow. A key should look like random binary data (much like the GUIDs prevalen= t in EFI code). I seriously doubt someone could write a firmware module tha= t could dig through the memory state of an arbitrary OS's boot loader and fi= nd keys. You'd basically have to put a full online binary analysis framewor= k in the firmware, and have it run fast enough to not be noticed. That woul= d be some serious Turing award-worthy work kept secret from the world solely= to build firmware backdoors. I don't think even Lenovo would go that far. >>=20 >> (I know I mentioned scanning the kernel as a threat above; that's an offl= ine attack that can be done on a copy. Online undetectable analysis of a ru= nning program is WAY harder.) > Nobody would scan for random data looking like keys. If attacker is > interested in keys from the freebsd loader or password decrypting the > keys, the address of the memory region where the material is stored and > region' layout are immediately available for any code collocated in the > common address space. No, they don't necessarily know the memory location at all. The keys are st= ored either in static variables (i.e. no symbol to tell you where it is), st= ack frames, or malloc data structures (and the static variable ones can be m= oved if it's REALLY a concern). Plus you've got other operating systems with their own full disk encryption m= ethods, as well as every revision of the FreeBSD boot loader. Unless you're specifically targeting an individual for attack (in which case= , going by your proposal, I could just tamper with their unencrypted kernel,= so why would I bother with EFI tricks), you'd have to have either a huge nu= mber of profiles for every version of every OS boot loader, or you'd have to= have some kind of analysis framework. > The hooks into the interfaces and pre-recorded sequence of calls for > the initialization of loader give unique execution profile which allow > to determine the password and key storage location. And this changes on every platform, with every revision, and is wildly diffe= rent for other OSes. Moreover, this sort of attack is in no way unique to G= ELI, and could just as easily be used to insert a backdoor into a kernel, or= anything else. > Exact attack scenario is not the point I am trying to make. Instead, I > point out that UEFI execution environment is shared one, with no walls > between software components from arbitrary sources. It is absolutely > unsuitable for exposing sensitive material. Even more laughtable to > simultaneosly hide kernel binary. >=20 > In contrast with the kernel environment, which even with ME/BMC/ACPI/UEFI > runtime components, is less penetrable by trying to own the execution > state of the machine. I see no reason why. Sure, it's bigger, but any method that could recover a= key from a boot loader should also work on a kernel. These sorts of things= have been demonstrated all the time in conference presentations, academic p= ublications, and other venues. >=20 >> Besides, if someone wants to do evil things in firmware, I think it's far= more likely they'd just backdoor the network or USB controllers to let some= one send an override packet and execute bundled code in kernel mode. That w= orks every time for every OS and doesn't require surreptitiously picking apa= rt arbitrary programs' data structures in real time. > Of course backdoring hardware is order of magnitude harder and requires > physical access to the machine. The realistic action by level of script > kiddie is getting UEFI driver installed. It seems you're considering only one kind of attacker, and specifically not t= he kind that are relevant to disk encryption. The whole point of disk encryption IS to deal with people who have varying l= evels of physical access to your machine. By definition, the script kiddie o= f which you speak would be running their attacks when the encrypted partitio= ns are all attached. So they'd have access to all the data anyway. The sam= e holds for a more sophisticated attacker. Why would they bother with a fan= cy EFI malware when they already have access to all the data anyway. I'll admit there may be some kind of persistent threat scenario where someon= e plants EFI malware to sniff keys at a later date, but this seems extraordi= nary rare. By contrast, data protection is a real thing: many organizations= have requirements for full disk encryption, and there are people in the wor= ld who have to deal with getting harassed and having their computers seized a= nd searched. > To close this branch, backdored busmasters (but not ME) are > trivially mitigated by enabling IOMMU, FWIW. >=20 >> For what it's worth, I have considered possible hardening measures: using= alias GUIDs to disguise interfaces and adding per-build padding or XOR mask= s to structures with keys to throw off scanners. However, I don't think the= threat is realistic enough to warrant such measures. > I do not see a way to comment about the measures, without adding > the word 'theatre'. Right, which is why I decided they aren't worth it. >=20 >>> Putting aside ineradicable evil of Intel ME or its >>> AMD twin, and SMM handler, you are exposing keys to whatever code happen= >>> to inhabit the preboot env, not neccessary originating from the firmware= >>> vendor. Secure Boot would not help there, since when the measurement >>> indicate that untrusted component was there, it is too late. I.e., >>> you making much easier for malice hacker to steal the keys. >>=20 >> I mean, the same argument holds for the kernel, if not moreso. You have A= CPI bytecode, SMM, device blobs, anything that the boot environment chose to= keep around for runtime by marking that memory as "unavailable", and of cou= rse, the evil that is Intel ME. This is an unavoidable risk of having keys i= n main memory ever. > See above. >=20 >> If you really want any kind of safety from this, you need to use a hardwa= re crypto device that stores keys in a separate memory (which, I specificall= y designed things to make it easy to add support for one). Of course, you t= hen have to trust the device... >=20 > No, what I want is avoiding bad choices which are seemingly made just > because code can be written. Code exposing sensitive material is written > for very weak and leaking environment, at least without secure boot > turned on. Arguments supporting that decision reference 'security' by > e.g. hiding kernel binary, and undesire to have /boot partition. Please > take a step outside and see bigger picture. I'd say the same to you... You are only considering one kind of scenario. Alan's and my work is aimed a= t protecting systems from attackers that have some level of physical access t= o the machines. There are people in the world who have to contend with this= sort of thing, and the major competing OSes (Apple, Linux, MS, etc) all hav= e their own full-disk encryption solutions. Moreover, my work is aimed at tamper-resilience at the OS level. Yes, I kno= w OS tamper-resistance can be undermined without trusted firmware, but we ar= e seeing projects like coreboot and others working toward that end. Moreove= r, these kinds of efforts are themselves pointless when the OS does things l= ike leaving the most sensitive part of the system wide open to tampering. Speaking personally, I would like to see a system where I have full disk enc= ryption combined with EFI secure boot with a unique platform key stored on m= y encrypted disk. Having an unencrypted boot partition in such a system just= opens up more attacks, plain an simple. (I would also like to see an open s= ource firmware and no ME, but that's out of scope here) Finally, it's not like Alan's and my work *forces* anyone to use GELI. If y= ou are really worried about some scenario where an attacker doesn't have phy= sical access and needs to backdoor the firmware to sniff keys so they can ac= cess data they can't see despite being able to write to firmware, then fine,= don't use GELI at boot. Better yet, use the compile flag to remove it from= boot1 and loader completely. But if you want full disk encryption, you hav= e the option of having it.=
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?46B3F9E2-A25B-4F9D-B35F-11AC782495B1>