Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 20 Mar 2016 15:10:55 -0400
From:      Eric McCorkle <eric@metricspace.net>
To:        Allan Jude <allanjude@freebsd.org>
Cc:        freebsd-hackers@freebsd.org
Subject:   Re: boot1-compatible GELI and GPT code?
Message-ID:  <CCE83F63-4CDA-47EA-9D5F-3BDDA752072A@metricspace.net>
In-Reply-To: <56EEEFBF.1000203@freebsd.org>
References:  <8F22A0E2-45A3-463B-8CAC-16BEC8DA8883@metricspace.net> <1458497121.68920.83.camel@freebsd.org> <56EEEFBF.1000203@freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
In EFI, you don't have the bootinfo struct, you just have command-line style=
 args going from boot to loader.  Right now, the efi loader doesn't even loo=
k at the args.

Some thoughts:
* The ideal solution (if you trust HSMs and have one at all) would be to loa=
d the keys into an HSM in boot, and rely on it from there.  That's a lot of h=
ardware support in boot, though.
* There is some incentive to avoid args/env variables. There's a very real r=
isk of your keys getting leaked by debugging/logging messages.  Also, at lea=
st in the efi boot to loader transition, I wouldn't put it past the likes of=
 Lenovo to record all ExecImage activity, which would slurp the keys if that=
 method was used. Also, it'd be big change to the efi loader to add args (an=
d a potential vuln to parse them)
* With the variable injection method I proposed as well as with a method of s=
ynthesizing a loadable module in memory, an attacker capable of getting the k=
eys would have to be able to access kernel memory.

The only safe option to me seems to be either injecting the keys straight in=
to the executable, or else synthesizing modules containing them and loading t=
hem.  Now, you'll need to also do this for loader, which is a COFF binary.  B=
oth approaches have their merits, though I think I slightly prefer the injec=
tion method.

> On Mar 20, 2016, at 14:45, Allan Jude <allanjude@freebsd.org> wrote:
>=20
>> On 2016-03-20 14:05, Ian Lepore wrote:
>>> On Sun, 2016-03-20 at 13:13 -0400, Eric McCorkle wrote:
>>> Hello everyone,
>>>=20
>>> I'm working (among other things) on expanding the capabilities of the
>>> EFI boot block to be able to load GELI-encrypted partitions, which
>>> may contain a GPT partition table, in order to support full-disk
>>> encryption.
>>>=20
>>> I'm wondering, is there any code for reading either of these formats
>>> that could be used in boot1 hiding out anywhere?  It'd be best to
>>> avoid rewriting this stuff if possible.
>>>=20
>>> Also, I haven't investigated the capabilities of loader with regard
>>> to GELI yet beyond cursory inspection.  Most importantly, I need to
>>> know if loader can handle GPTs and other partition formats inside a
>>> GELI, or just single filesystems.
>>>=20
>>> As an additional note, it'd be best if there was a method for having
>>> boot1 pass the key(s) along to loader and ultimately the kernel, so
>>> the users don't have to input their keys 3 times.  I'm open to
>>> suggestions as to how to do this.  My initial thought is to create
>>> some kind of variable in both loader and kernel, then use the elf
>>> data to locate it and directly inject the data prior to booting.  The
>>> rationale is to avoid mechanisms like arguments that could
>>> potentially reveal the keys.
>>=20
>> GELI keys are currently passed from loader(8) to the kernel as
>> environment variables.  I was semi-horrified when I stumbled across
>> that -- not the knee-jerk-reaction you'd expect from a security
>> -obsessed person (because I'm soooo not one of those), but rather
>> because it means that the memory passed from loader to the kernel
>> containing the initial env vars must be writable, so that the geli key
>> stuff can be zeroed after it's acccessed.  That prevents making the
>> pointer to that memory const everywhere, as it should be.
>>=20
>> It seems to me that a more correct way to pass the information may be
>> as an opaque data blob, roughly the same way kernel modules and other
>> loaded data gets passed from loader to the kernel.  That might
>> facilitate obscuring the info in some way as well.
>>=20
>> That doesn't really answer your question of how to pass it from boot1
>> to loader(8), though.  There really isn't a lot of leeway there, you
>> pretty much have to put it in memory somewhere (likely into an arch
>> -specific bootinfo struct), and pass a pointer to it in a register when
>> jumping to the loader(8) entry point.  (Remember that all of this stuff
>> applies to multiple platforms, not just x86, so it can't just be
>> dropped into some well-known location in memory or anything like that.)
>=20
> This is how I did it in my recent work. Added an additional field to the
> 'extended boot info' struct, to pass the data from boot2 to the loader.
> My work only targeted i386/amd64.
>=20
>> -- Ian
>>=20
>> _______________________________________________
>> 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
>=20
> --=20
> Allan Jude
>=20



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CCE83F63-4CDA-47EA-9D5F-3BDDA752072A>