[gPXE-devel] Trusted boot for gPXE

Stefan Hajnoczi stefanha at gmail.com
Sun May 16 15:24:31 EDT 2010


Secure network booting is becoming increasingly important with services like
boot.kernel.org that enable booting over the internet.  Also, users in
commercial settings sometimes need to implement security policies where the
local network is not trusted much.  I have implemented a working demo of
trusted boot and am inviting others to help develop it further into a feature
that can be added to a future gPXE version.

Trusted boot performs checks to ensure that only genuine images can be booted.
Images that have been tampered with or are not blessed by the person deploying
gPXE are refused.

For example, boot.kernel.org can reassure its users that only known good images
can be booted.  Any tampering of downloaded images is detected.  Also, the
boot.kernel.org client will refuse to boot images from other origins (this
prevents hijacking or tricking users into using a malicious server).

Design
------

The TRUSTED_BOOT config option can be used to enable trusted boot.  By default
gPXE builds with trusted boot disabled and behavior remains unchanged.

When TRUSTED_BOOT is enabled, an image can only be executed if it is trusted.
An untrusted image will fail to boot with the EPERM error code.

Images can be trusted by verifying their contents against a hash.  This is the
same idea as checking the hash of an ISO you have downloaded.  If the hash
matches, then the original file has been downloaded and the image is marked as
trusted.

The 'imgdigest' command works like this:
imgdigest bzImage 2dd53ebe0c19b4602d192d0e5dec082d

'bzImage' is the name of a loaded kernel image and the hash is the MD5 checksum
of that file on the server.

Embedded images are automatically trusted because anyone who is able to modify
the gPXE binary could also simply disable TRUSTED_BOOT.

To make trusted boot more powerful, there is a mechanism for signing gPXE
scripts.  This makes it possible to perform a trusted boot over the network
without an embedded image - new images can be added and scripts can be modified
without reconfiguring trusted boot gPXE clients.

The first line of a signed gPXE script looks like this:
#!gpxe f2fdeea481852e55c47a38f4bb754a70b9f2f0ee9e80e740a619b5271bbb169323bcd561dadb3c15d66079429c3029d448e99556985b0c442c20f1d30cbcccb5

In addition to the usual '#!gpxe' magic, there is a signature that can be
verified against a public key embedded inside the gPXE image.

When gPXE loads a signed script, it tries to verify the signature against its
embedded public keys.  If signature verification succeeds, the script is
considered trusted.

gPXE can be built with embedded RSA DER keys like this:
make EMBEDDED_PUBKEY=/path/to/rsa.der

Example
-------

Let's put together a trusted boot of TinyCoreLinux.  TinyCoreLinux is a small
distro that needs only a kernel and initramfs.  The following gPXE script boots
untrusted TinyCoreLinux:
#!gpxe
kernel http://vmsplice.net/bzImage initrd=/boot/tinycore.gz quiet max_loop=256
initrd http://vmsplice.net/tinycore.gz
boot

First we need to calculate the hashes of bzImage and tinycore.gz:
$ md5sum bzImage
2dd53ebe0c19b4602d192d0e5dec082d  bzImage
$ md5sum tinycore.gz
a039e4877d814273f8bad3f47292e835  tinycore.gz

The hashes need to be added to the script so that bzImage and tinycore.gz can
be trusted:
$ cat tinycore_signed.gpxe
#!gpxe
kernel http://vmsplice.net/bzImage initrd=/boot/tinycore.gz quiet max_loop=256
initrd http://vmsplice.net/tinycore.gz
imgdigest bzImage 2dd53ebe0c19b4602d192d0e5dec082d
imgdigest tinycore.gz a039e4877d814273f8bad3f47292e835
boot

The script itself is not trusted yet and the way to do that is by signing it.

First generate an RSA key pair:
$ openssl genrsa -out rsa
Generating RSA private key, 512 bit long modulus
......++++++++++++
.....++++++++++++
e is 65537 (0x10001)

Now generate a signature for tinycore_signed.gpxe:
$ openssl dgst -sign rsa -hex tinycore_signed.gpxe
MD5(tinycore_signed.gpxe)=
091eafe9354fa2827b09afd68b0565e1d9f503139ee76284229b6e3ec7093bf0846cbd2f55fa3ec16dbef8d231a65412da2d079b7ff5276aee16f412ef1243dd

Add the signature into the signed file:
$ cat tinycore_signed.gpxe
#!gpxe 091eafe9354fa2827b09afd68b0565e1d9f503139ee76284229b6e3ec7093bf0846cbd2f55fa3ec16dbef8d231a65412da2d079b7ff5276aee16f412ef1243dd
kernel http://vmsplice.net/bzImage initrd=/boot/tinycore.gz quiet max_loop=256
initrd http://vmsplice.net/tinycore.gz
imgdigest bzImage 2dd53ebe0c19b4602d192d0e5dec082d
imgdigest tinycore.gz a039e4877d814273f8bad3f47292e835
boot

The signed script is ready.  Embedding the RSA public key in gPXE requires a
public key in DER format:
$ openssl rsa -pubout -outform DER -in rsa -out rsa.der
writing RSA key

Now enable the trusted boot config option in config/general.h:
#define TRUSTED_BOOT 1          /* Only boot trusted images */

Finally build gPXE with the embedded public key:
$ make EMBEDDED_PUBKEY=/tmp/rsa.der

You can try out this example with the gPXE image from here:
http://etherboot.org/share/stefanha/trustedboot.usb

Point it at http://vmsplice.net/tinycore_signed.gpxe or try the following
QEMU/KVM invocation to test it in a virtual machine:
kvm -bootp 'http://vmsplice.net/tinycore_signed.gpxe' trustedboot.usb

Help wanted
-----------

I have no background in crypto.  I stuck with the default 512-bit RSA and MD5
because I'm not even going to attempt to choose something secure.  Can someone
with more clue explain which primitives and key sizes should be used?  Please
include a links or references.

What use cases does this design satisfy?  For example, how can a NIC vendor
ship a trusted boot enabled gPXE in ROM?  I'm hoping that the main use cases
can use this design.

Weaknesses/holes in this design:
 * initramfs/initrd and multiboot modules are currently not verified,
easy to fix
 * trusted SAN boot not supported

This is very early work in progress.  I only hacked this up today.
Code is here:
http://git.etherboot.org/?p=people/stefanha/gpxe.git;a=commitdiff;h=fc57644c5897fe75b81b2d5493dc0d093b237aed

Thoughts?

Stefan


More information about the gPXE-devel mailing list