[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Guaranteeing initramfs integrity during Secure Boot


This is a basically a recap of ideas I had while talking to Ben Hutchings
  (benh@) and my friend and colleague Johannes Winter, so a good part of the
  credit should go to them.  All blame, however, should be directed to me.

The current plans for implementing Secure Boot are (roughly) as follow:
- a shim bootloader is signed by Microsoft [0];
  it contains a Debian-specific, (public) signature key;
- the actual bootloader is signed by Debian,
  and the signature is checked by the shim;
- the bootloader checks the signature of the kernel;
- the kernel only loads signed modules, and disables features that
  would lead to untrusted ring0 code being executed (securemode = 1).

[0] Sadly, Microsoft is the one organisation with a signing key that
    is trusted out-of-the-box by most computers.
    Nothing prevents us from packaging a Debian-signed shim for people
    who wish to mess with their trust store and trust only Debian.

While all of that give some guarantees that the kernelspace code is
  trustworthy [1], it doesn't do anything to ensure that the userspace is.

A first step [2] in that direction would be to ensure that a legitimate
  initrd is booted.  This is difficult: the initrd is generated on
  the device, and so cannot be signed using the Debian key; because of this,
  I will not even attempt to protect the initrd against somebody gaining
  root access on the running system [3].

A solution for this could be as follows:
- When the shim bootloader is installed, a HMAC key [4] is generated, and
  sealed to the TPM in such a way that it is accessible iff the platform
  booted on this specific shim bootloader; the sealed blob is stored on /boot.
- The HMAC of each installed initrd is written on /boot (say, in
  initrd.img-${VERSION}-${ARCH}-${SHIM_VERSION}.mac; the shim version matters).
- During boot, the kernel loads a built-in “shim initrd” [5] (that is part of
  the same binary, and covered by the Debian signature), which unseals the HMAC
  key, checks that the initrd is correct, and transfers control to it.

All of this nicely prevents an adversary (who doesn't have local root) from
  making us load their “custom” initrd:
- it must be authenticated with a HMAC;
- the HMAC key is only available after booting on the shim bootloader;
- the adversary is in a catch-22: they need local code execution to HMAC
  the code they want to make us execute.

[1] Note that this doesn't do much against an adversary with a kernel 0day.
    It's not meant to.

[2] Actually, ensuring integrity until the initrd is started /and/
    using full disk encryption should thwart somebody attempting to
    compromise a powered down laptop (if we forget that LUKS doesn't,
    on principle, guarantee integrity of the volume, and if the
    adversary doesn't replace the on-flash firmware).

[3] In principle, it is possible to measure the mkinitramfs run and only
    allow properly-generated initrdes to be signed.
    In practice, this very likely breaks in horrible ways because the OS
    is not meant to protect running processes from root (who can poke at
    the processes, change the initramfs-tools config, change the data it
    consumes, ...).

[4] I started off with having a device-specific signing key, but ended up
    with this scheme, where using asymetric crypto isn't required.

[5] This seemed to be, to Johannes and I, the least annoying place where to
    put Debian-specific code; I might be very mistaken.

What I glossed over until now is how to deal with a shim {up,down}grade,
  or with the system being restored from backups.

The good news is that there is no state put in the TPM [6], so restoring
  a backup of /boot should be completely transparent.  Handling shim versions
  change is similarly transparent: generate a new HMAC key for that shim
  version, seal it to the TPM under the right PCR constraints, and compute
  HMACs of all currently-installed initrds [7].

However, should a backup of /boot be restored that contains no (sealed) key
  for the installed shim bootloader, the system would fail to boot;
  I'm not sure how to handle such a mismatch, nor how likely it is.

[6] Aside from the TPM proof value, which would be nuked assuming someone
    clears ownership, preventing the HMAC keys from being unsealed,
    which would make the system fail to boot.  Oops.

[7] Filthy lies: an initrd being built after the shim was changed but before
    reboot would require special care; it's not a big issue in principle, but
    still introduces more complexity.

This should be effective against an adversary that gains physical access to a
  device, yet cannot tamper with the live system (by plugging in a device that
  exploits a buggy driver, by messing with the memory bus or a DMA-capable
  interface, ...) and cannot replace the firmware.

As you can see, this does not outright prevent evil-maid style attacks:
  the goal here is to make such attacks harder/less practical.



Attachment: signature.asc
Description: PGP signature

Reply to: