Skip site navigation (1)Skip section navigation (2)
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>