Proposal for a design for signed kernel/modules/etc

Eric McCorkle eric at metricspace.net
Thu Mar 30 02:22:46 UTC 2017


On 03/27/2017 14:37, Shawn Webb wrote:

> The only other major thing to discuss is supporting public key chaining.
> Ideally, digital signature support should also support chaining multiple
> keys (similar to X.509 PKI). If the accepted solution supported cert
> chaining, then the solution would be more modular. I don't want to go
> down the route of the SSL/TLS PKI mess, but supporting chaining is a
> must in some enterprise environments.
> 
> If we were to support chaining, we could even stuff the pubkey half of
> the key material into another ELF section, so that if a key becomes
> compromised, the old pubkey can be revoked from the trust store and a
> new binary can be generated with new key material. The trusted root
> doesn't need to be cycled as often. HardenedBSD, for example,
> distributes the pubkey that corresponds to the signing privkey inside
> the update tarball for binary updates[1]. This allows us to change key
> material often if desired without the user even noticing.

I've done more research and design work in this area, to the point where
I think I can talk about specific formats.

I've also done some really preliminary work on the signelf utility (just
sketching out the various use cases and marking the API calls I'll need,
no real implementation yet).

Here's what I've got:

== Use Cases ==

The command-line utility ought to be able to verify signed ELF files too
(so people can sanity check things).  There's basically three cases that
emerge for signing:

1) Vendor key + ephemeral key: I point you at the vendor key-pair (the
public key for which is presumably compiled into the loader/kernel), you
generate an ephemeral key-pair.  You then sign the ELF with the
ephemeral key-pair, sign the ephemeral public key with the vendor
key-pair and include it in the ELF as well, then securely delete the
ephemeral private key.

2) Direct signing with an application key: I point you at an application
key-pair, which is signed by a vendor key somewhere (which is presumably
compiled into loader/kernel).  You sign the ELF with the application
key-pair and include the signed application public key in the ELF as
well.  (Case (1) is basically the same as this one, except we generate
and sign a one-time application key)

3) Direct signing without a vendor key: I point you at a key, which you
use to sign the ELF; however, you don't include the public key in the
ELF (it's presumably compiled into loader/kernel).

On the verification side, you have two cases:

A) ELF with signed application key: You have a set of vendor public
keys.  The ELF has a signed application public key and a file signature
produced with said application public key.  You check that the file
signature is valid using the application public key, then check that the
application key signature is valid using the vendor public keys.

B) Direct-signed ELF: You have a set of vendor public keys.  The ELF has
a file signature produced by one of them (presumably).  You check that
the file signature is valid using the vendor public keys.

Cases (1) and (A) should be the default behavior on both sides, and the
signelf utility ought to be able to batch-sign a whole bunch of files
with one ephemeral key.  Case (2) is included in anticipation of a
situation where it's not feasible to do all the signing in one fell
swoop.  Cases (3) and (B) are simplified behavior for when a vendor key
isn't needed (ex. some kind of all-in-one embedded system image).

== Formats ==

There are two formats (or rather, families thereof):

* OpenSSL- formats based around ASN.1 DER and PEM, PKCS#8 format for
private keys (which supports both encrypted and unencrypted storage),
X509 for public keys, PKCS#7 or its successor, CMS for signatures.

* OpenPGP (GnuPG) formats

OpenSSL is directly supported by base, and is arguably more widely-used
(it's the foundation for SSL/TLS).  It also provides direct support for
cert-chaining as I discussed in the use case analysis (in fact, it can
go way beyond that).

GRUB needs public keys to be in GnuPG format.  On the other hand, the
gnutls library handles X509 and PKCS#7.  There's also some interesting
possibilities with vendor keys and PGP's web-of-trust functionality.

Fortunately, the monkeysphere project (port security/monkeysphere) comes
with utilities for converting between OpenSSL certs/keys and GnuPG
keyring databases.  With this in play, it just makes sense to use the
formats that are directly supported by base.

== Specifics ==

So, here's what I'm proposing WRT the gritty format details:

* The command-line tool will expect to see public keys in X509 format
and private keys in PKCS#8 format, both with PEM encoding.

* The vendor keys will be stored in a standard location (say, /etc/keys
or something), and there would be a build utility that converts the
public keys into a C file containing the data, so it can be baked
directly into loader and kernel.

* A signed ELF will definitely contain a .sign section containing a
single detached signature in PKCS#7 format with DER encoding.

* Signatures are computed by hashing the contents of the entire file
minus the .sign and .cert sections.  (Crypto hashes effectively consume
a byte stream, so this is pretty straightforward to do)

* A signed ELF may also contain a .cert section, which contains a single
X509 certificate.  In use case (1), this would contain the ephemeral
public key.  In use case (2), this would contain the application public
key.  In use case (3), this section would be omitted.  You could
presumably include an entire cert-chain here, but I think that's
probably overkill.




An alternative to the .cert section would be to have the ability to
point kernel/loader at an X509 cert and pull the whole thing in as long
as there's a root signature coming from a valid vendor key.  I'm a bit
split as to which one is better, though I seem to like the non-.cert
solution the more I think about it...

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <http://lists.freebsd.org/pipermail/freebsd-hackers/attachments/20170329/9d768864/attachment.sig>


More information about the freebsd-hackers mailing list