Date: Wed, 29 Mar 2017 22:22:41 -0400 From: Eric McCorkle <eric@metricspace.net> To: Shawn Webb <shawn.webb@hardenedbsd.org> Cc: "freebsd-hackers@freebsd.org" <freebsd-hackers@FreeBSD.org>, freebsd-security@freebsd.org Subject: Re: Proposal for a design for signed kernel/modules/etc Message-ID: <e7932a8c-ab0d-4506-ba51-385f39809037@metricspace.net> In-Reply-To: <20170327183735.uokjhjaafkawc2id@mutt-hbsd> References: <6f6b47ed-84e0-e4c0-9df5-350620cff45b@metricspace.net> <20170327183735.uokjhjaafkawc2id@mutt-hbsd>
next in thread | previous in thread | raw e-mail | index | archive | help
This is an OpenPGP/MIME signed message (RFC 4880 and 3156) --o2TtOFM9E1kLqGqmdpTQ5s2xSHI3daBLW Content-Type: multipart/mixed; boundary="Di4UCV0TwwPjjxxo7nhqsEfixbrNrXmGj"; protected-headers="v1" From: Eric McCorkle <eric@metricspace.net> To: Shawn Webb <shawn.webb@hardenedbsd.org> Cc: "freebsd-hackers@freebsd.org" <freebsd-hackers@FreeBSD.org>, freebsd-security@freebsd.org Message-ID: <e7932a8c-ab0d-4506-ba51-385f39809037@metricspace.net> Subject: Re: Proposal for a design for signed kernel/modules/etc References: <6f6b47ed-84e0-e4c0-9df5-350620cff45b@metricspace.net> <20170327183735.uokjhjaafkawc2id@mutt-hbsd> In-Reply-To: <20170327183735.uokjhjaafkawc2id@mutt-hbsd> --Di4UCV0TwwPjjxxo7nhqsEfixbrNrXmGj Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: quoted-printable On 03/27/2017 14:37, Shawn Webb wrote: > The only other major thing to discuss is supporting public key chaining= =2E > Ideally, digital signature support should also support chaining multipl= e > 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. >=20 > 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: =3D=3D Use Cases =3D=3D 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). =3D=3D Formats =3D=3D 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. =3D=3D Specifics =3D=3D 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... --Di4UCV0TwwPjjxxo7nhqsEfixbrNrXmGj-- --o2TtOFM9E1kLqGqmdpTQ5s2xSHI3daBLW Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- iQIzBAEBCAAdFiEEzzhiNNveVG6nWjcH1w0wQIFco2cFAljca/EACgkQ1w0wQIFc o2dBtw/+M8Z/03eZqrmkN0WElSirvQTLU/orKe4t/XPJ+Rv7kqI3KjRhQEb76+0T 1KNJJrnhmiRiu9CEy8kVbatUQ75Hz5VmB4fbl4CeW5GQERSgaUp2ErPXT6Y4dENN dBc+yT+Sf0i1csN2lsfIVxD15bC+VweSuBDdsWHeEk7IjMBBNKaJ3TNxsGLTDV9f zgyiXLmwqgUXiR8l8dM3WavbwCdy0O9u/aNTS7gz+cFaeIRyjZaO7+041DSFFdjv ObymfvWCVEXmkIfFmsmtXCKCQSjJhyMmiqFYSKL2etM+gE0tdl9xHhjkviTXT7ov GlZCzxocLG1vMhzEfj5zEWOqHrQuu1NKmtSXv9yyaLGIHiTPSlro9bgDAlTlaThC vte3SRYNcFgazGTez2F8oqW87MrzsHzBA+hoeAbSyYiOO79e2EvgfmHsDxn/SvYl XGUHPPD+5OFek1wC28e/ofO3d99AMICZZzd5xc5Zif+JdAmSX6JeKk5HtqsXhk1P cV4s2ZF07PX8gHfcQtJJGz7TqJKZGdiV3iXZOrMaKQ/hmJ1R602M5pyMKH27sP8p e78IhlWw1tREbP0Koqk5Lrws5yFWyxaOr8TZobfhPYW3ZgvCAEbVVsFykOp3VXyu SLXSHiMInY7v55ih0johhh5YpXvCPj6xcYK5sW9HK5WbRoLu1/o= =qvz6 -----END PGP SIGNATURE----- --o2TtOFM9E1kLqGqmdpTQ5s2xSHI3daBLW--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?e7932a8c-ab0d-4506-ba51-385f39809037>