Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 15 May 2016 16:37:38 -0400
From:      Eric McCorkle <eric@metricspace.net>
To:        Oliver Pinter <oliver.pinter@hardenedbsd.org>,nao@enuenu.org
Cc:        "freebsd-hackers@freebsd.org" <freebsd-hackers@freebsd.org>
Subject:   Re: Update on EFI work: refactoring ready for testing, GELI coming very soon
Message-ID:  <1C7554E1-DF5F-4D86-B4D3-757CF55FCB9E@metricspace.net>
In-Reply-To: <CAPQ4ffuo2DpwWZjEw8pAEJaQMFc_k=KCadj0LjwGhZ%2BAEZGyNw@mail.gmail.com>
References:  <C54B6238-4186-4DC0-8FDB-067E1724D808@metricspace.net> <CAPQ4ffuo2DpwWZjEw8pAEJaQMFc_k=KCadj0LjwGhZ%2BAEZGyNw@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
How close is that patch to going in?

Something like this would be pretty straightforward following the refactoring; however, its worth considering all the options here:

* GRUB works fine pulling loader off the disk, with either ZFS or UFS, with no boot1 at all.  This was my setup for developing the ZFS support, actually. 
* In theory it should be possible to install loader itself on the ESP and install a /boot/config that points it to the real kernel and rootfs

The takeaway is that boot1 is kind of an odd citizen in the EFI world. When you get into things like GELI support and secure boot (my next planned thing after this), its role is much clearer, but at that point it also becomes a key attack vector in a system that's presumably trying to resist some level of tampering. 

What I'm getting at is that there is a future-oriented case for keeping boot1 simple, and if it's a boot menu you want, grub is already an option (also, the loader-only method).

To be clear: I'm not opposed to adding this feature; I just want to make sure these issues are given due consideration. 

On May 15, 2016 12:00:58 PM EDT, Oliver Pinter <oliver.pinter@hardenedbsd.org> wrote:
>Hi Eric!
>
>Could you please take a look at this PR:
>https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=207940
>This feature would be nice too.
>
>On 5/15/16, Eric McCorkle <eric@metricspace.net> wrote:
>> Hello everyone,
>>
>> I've been working on a rather significant refactoring of the EFI
>boot/loader
>> code.  While this was originally in support of adding GELI support,
>it has
>> grown to such a scope that it could be considered a patch in its own
>right.
>>
>> The branch containing my work can be found here:
>> https://github.com/emc2/freebsd/tree/efize
>>
>> The following is a summary of the changes:
>> * Both boot1 and loader have been redesigned to look for instances of
>> EFI_SIMPLE_FILESYSTEM_PROTOCOL and load using that interface.  In
>loader,
>> this is accomplished through a new synthetic filesystem driver
>(called
>> efifs) that is just a wrapper around EFI_SIMPLE_FILESYSTEM_PROTOCOL. 
>In
>> boot, this is achieved by calling the interface directly.
>> * The efipart and filesystem back ends (including ZFS) have been
>moved into
>> a drivers directory, where they have been wrapped up into a
>filesystem
>> backend driver that does the same probing that loader does today, and
>then
>> installs an EFI_SIMPLE_FILESYSTEM_INTERFACE on all device handles
>that host
>> supported filesystems.  This interface is a wrapper around the
>filesystem
>> interface currently used by loader.
>> * boot now uses the same filesystem backend code as loader.  This
>increased
>> its size, necessitating recreation of the FAT templates.  The old
>boot
>> filesystem code and boot modules have been discarded.
>> * loader can use any protocol interface installed by boot just fine. 
>These
>> remain valid until ExitBootServices is called.  Moreover, the probing
>> process is idempotent, and is run by both boot and loader, with the
>first
>> one to run actually installing the interfaces.
>> * I had originally hoped to move the entire code base to use the EFI
>driver
>> model, which would support hotplugging devices.  However, the new
>bcache
>> stuff currently requires that all devices be statically detected
>before the
>> caches are used, which is fundamentally incompatible with this way of
>doing
>> things.  This was the sole blocker of such a transition (the
>handles.c code
>> requires some minor modification as well, but nothing problematic)
>> * I had also considered altering the device name code to use textual
>> representations of EFI device paths, but I don't see any real reason
>for
>> doing so.
>> * I have not touched efinet or nfs in this changeset.
>>
>> The rationale for these changes is as follows:
>> * The model of looking for EFI_SIMPLE_FILESYSTEM_PROTOCOL instances
>and
>> using them to load things increases interoperability with other
>systems.
>> For example, the new boot and loader would work just fine with
>interfaces
>> installed by GRUB or another boot loader, or perhaps custom
>filesystem
>> modules added into an open-source firmware implementation like
>coreboot.
>> * This model works really well for functionality like GELI or custom
>> partition schemes that potentially create new devices.  All you do is
>create
>> one or more new device nodes, attach device paths and block io
>interfaces,
>> and call ConnectController on them (for now, it's necessary to make
>sure the
>> fs_driver runs AFTER) all new nodes have been created. This also
>vastly
>> simplifies passing information between stages about filesystems and
>devices
>> (this is important for GELI).
>> * This approach can leverage drivers that are mandated by the EFI
>spec, like
>> the GPT partition driver.  This avoids reimplementing such a driver
>to
>> support partition schemes nested inside GELI volumes, for example.
>> * This model provides most of the groundwork for supporting hot
>plugging of
>> devices at boot time.  All that is required at this point is a
>refactoring
>> of bcache to support adding new devices dynamically (I had to draw
>the line
>> somewhere, and this had already gotten big enough, and I want to
>focus on
>> GELI support)
>> * Getting rid of the duplicated and minimized filesystem code in
>boot1
>> improves maintainability.  Indeed, the actual boot1 code is quite
>small
>> now.
>>
>> Some notes and future work:
>> * In general, the FreeBSD loader framework and the EFI framework do
>many
>> similar things.  For the most part, there is a fairly direct mapping,
>though
>> EFI interfaces tend to be more tedious.  The one thing EFI does
>decidedly
>> better is support dynamic detection of devices (hotplugging).
>> * There are some interesting possibilities for hotplugging beyond
>just the
>> obvious.  For example, loading GELI or other keys off of hotplugged
>USB
>> sticks.
>> * I didn't touch efinet or nfs on this patch.  It is certainly
>possible to
>> efize them as well, but I don't have a test setup for doing so (or
>frankly,
>> the motivation to do so).
>> * It might make more sense to use the EFI_LOAD_FILE_PROTOCOL to do
>the
>> actual loading, as some applications support this without supporting
>a full
>> filesystem interface (some embedded devices do this, as do some
>network boot
>> protocols).  However, this would involve changing the non-EFI boot
>code and
>> interfaces, which is something I specifically wanted to avoid in this
>work.
>>
>> This changeset can be tested as is, and should just work. 
>Disclaimer: I
>> rebased it to head yesterday, and haven't had time to build and test
>it yet,
>> but I will.  I know it works with ZFS, but I have no UFS systems on
>which to
>> test that functionality.
>>
>> If you intend to test this, I STRONGLY recommend installing an EFI
>shell on
>> your ESP, and then installing the modified boot block under something
>like
>> boot.tst.  This will allow you to run the modified boot block, but
>fall back
>> to a working boot if it fails.  Also, I had modified the loader path
>to
>> /boot/loader.tst for similar reasons, and it may still be set to that
>in the
>> code.
>>
>> I am currently adding GELI support as a proper EFI driver, and should
>be
>> coming in the very near future (the code is already written, in
>fact).  If
>> anyone wants to test the refactoring by itself, any results or
>comments are
>> certainly appreciated.
>> _______________________________________________
>> 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"
>>

-- 
Sent from my Android device with K-9 Mail. Please excuse my brevity.
From owner-freebsd-hackers@freebsd.org  Sun May 15 22:06:07 2016
Return-Path: <owner-freebsd-hackers@freebsd.org>
Delivered-To: freebsd-hackers@mailman.ysv.freebsd.org
Received: from mx1.freebsd.org (mx1.freebsd.org
 [IPv6:2001:1900:2254:206a::19:1])
 by mailman.ysv.freebsd.org (Postfix) with ESMTP id B2F64B3B32E
 for <freebsd-hackers@mailman.ysv.freebsd.org>;
 Sun, 15 May 2016 22:06:07 +0000 (UTC)
 (envelope-from eric@metricspace.net)
Received: from mail.metricspace.net
 (207-172-209-83.c3-0.arl-ubr1.sbo-arl.ma.static.cable.rcn.com
 [207.172.209.83])
 by mx1.freebsd.org (Postfix) with ESMTP id 6B20111C6
 for <freebsd-hackers@freebsd.org>; Sun, 15 May 2016 22:06:06 +0000 (UTC)
 (envelope-from eric@metricspace.net)
Received: from [172.16.0.5] (unknown [172.16.0.5])
 (using TLSv1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits))
 (Client did not present a certificate) (Authenticated sender: eric)
 by mail.metricspace.net (Postfix) with ESMTPSA id BBA64158A
 for <freebsd-hackers@freebsd.org>; Sun, 15 May 2016 22:06:05 +0000 (UTC)
Subject: Proposal for an interface for communicating keys from loader to kernel
From: Eric McCorkle <eric@metricspace.net>
Content-Type: text/plain;
	charset=us-ascii
X-Mailer: iPad Mail (13D15)
Message-Id: <DDDBBE34-1020-4ED4-8619-8BD95DCB76E8@metricspace.net>
Date: Sun, 15 May 2016 18:06:04 -0400
To: "freebsd-hackers@freebsd.org" <freebsd-hackers@freebsd.org>
Content-Transfer-Encoding: quoted-printable
Mime-Version: 1.0 (1.0)
X-BeenThere: freebsd-hackers@freebsd.org
X-Mailman-Version: 2.1.22
Precedence: list
List-Id: Technical Discussions relating to FreeBSD
 <freebsd-hackers.freebsd.org>
List-Unsubscribe: <https://lists.freebsd.org/mailman/options/freebsd-hackers>, 
 <mailto:freebsd-hackers-request@freebsd.org?subject=unsubscribe>
List-Archive: <http://lists.freebsd.org/pipermail/freebsd-hackers/>;
List-Post: <mailto:freebsd-hackers@freebsd.org>
List-Help: <mailto:freebsd-hackers-request@freebsd.org?subject=help>
List-Subscribe: <https://lists.freebsd.org/mailman/listinfo/freebsd-hackers>, 
 <mailto:freebsd-hackers-request@freebsd.org?subject=subscribe>
X-List-Received-Date: Sun, 15 May 2016 22:06:07 -0000

I've developed a plan for a general interface for communicating keys from lo=
ader to kernel as part of my ongoing work.  As it involves creating an inter=
face between kernel and loader, I wanted to put it out for discussion before=
 I start writing code on it.

I'm aware of the current solution based on environment variables.  It has a n=
umber of shortcomings I aim to address with this proposal:
* It communicates only a single key to the kernel
* It could lead to accidental key disclosure by debugging (also, when last I=
 checked, the memory holding the key isn't properly zeroed out, which is a s=
ecurity risk)
* It is incompatible with hardware security modules (HSMs)

The basic idea is that the interface for doing this will look like a KMS (ke=
y management system) to loader.  In EFI land, this will be accomplished usin=
g the EFI_KMS_PROTOCOL interface (see UEFI spec 2.6).  This should allow loa=
der to treat a software-based approach and one that uses a hardware security=
 module of some kind as similarly as possible (some difference in the exact c=
lient data may be necessary, but the interface as a whole should be the same=
).

In EFI land, GELI (and any other crypto module) will be able to be configure=
d to store keys into a KMS with a given name.  There will be a software kern=
el injection driver which implements EFI_KMS_PROTOCOL which functions as fol=
lows:
* The kernel (or a module) will have a static key buffer added, which includ=
es space for some number of keys and their descriptors.  The exact format of=
 this is TBD.  It will have a specified name, and will be exposed as a linka=
ble symbol.
* The loader-side driver (which implements EFI_KMS_PROTOCOL) will maintain t=
his data in a buffer whose size and format exactly matches the one in the ke=
rnel.
* boot1 and loader will store keys for any system that requests them (such a=
s GELI) using the EFI_KMS_PROTOCOL functions.
* Adding a client named "kernel", with the client data being a pointer to an=
 ELF image will cause the driver to resolve the symbol for the kernel key bu=
ffer and copy all the data into place.  Updating the client data will cause t=
he driver to zero out the previous data and perform the lookup and copy agai=
n.
* During boot, the kernel is expected to check this buffer for keys first wh=
en initializing any system that may require key input (such as GELI).  It is=
 expected to zero out the buffer at the end of boot.

This could alternately be implemented as a device driver.  If there is an ex=
isting generic KMS interface, then I should use it as a template for such a s=
ystem (I am not aware of one, but that doesn't mean it doesn't exist).

Should support for some kind of HSM device be added, this approach should re=
quire minimal modification to support it fully.  This should also be orthogo=
nal to the current environment variable solution, so that approach can conti=
nue to be used for as long as necessary.

I anticipate having GELI probing and access working by next weekend, after w=
hich I will implement the system I've described here.  So I wanted to get th=
is out for consideration before then.

Comments and suggestions are welcome.  Feel free to forward this proposal to=
 anyone or any list that should see it.=



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1C7554E1-DF5F-4D86-B4D3-757CF55FCB9E>