Firmware security

From OLPC
Revision as of 12:26, 12 July 2007 by CScott (talk | contribs) (C-Scott)
Jump to: navigation, search

Scope

!!! Strawman Version !!!

This page describes the role of Open Firmware in BitFrost security on XO.

Goals

  1. Run recovery firmware if primary firmware is bad
  2. No access to ok prompt without developer key
  3. Firmware update images must be signed
  4. Boot images must be signed
  5. Unactivated laptops will only boot the activation image
  6. Boot alternate OS image if primary OS image is bad

Files

The files listed below are on NAND FLASH in JFFS2. (The zip archives listed below must be created without compression (-n option) and without paths (-j option).) Implementation notes and rationale are in italics.

  • Primary images are in /boot, secondary images are in /boot-alt
    At the start of an upgrade process, boot is copied to boot-alt; this doesn't need to be atomic. When upgrade is complete and validated, the upgraded files will be moved atomically to /boot. The atomic substitution requires /boot to be a symlink to the 'real' boot directory, which will be /boot-XXXXXX, where the X's are chosen by mkdtemp to be unique.
  • The activation key is named "/security/lease.xxx". Format and extension TBD.
  • The developer key is name "/security/develop.key".
    Rationale: The /security directory is left untouched by the upgrade process.
  • The normal OS image is in "/boot/os.zip", containing "os.img", "os.key", "rd.img", and "rd.key"
    • os.img is one of the load formats that OFW supports, e.g. Linux bzImage
    • os.key is ASN.1 signature of os.img as defined by the bios_crypto (SHA256->ECC256)
    • rd.img is a ramdisk image in a format supported by the kernel in os.img (typically initramfs)
    • rd.key is ASN.1 signature of rd.img as defined by the bios_crypto (SHA256->ECC256)
  • A zero-length file "/boot/no-rd" indicates that the boot process can skip the ramdisk.
    Rationale: The ramdisk is only used during activation and certain upgrades. As an optimization, we can skip authenticating and loading the ramdisk when it is not needed in order to simplify and speed up boot. To be conservative, we'll boot from the ramdisk if the /boot/no-rd file is lost.
  • The new firmware image is "/boot/bootfw.zip", containing "bootfw.img" and "bootfw.key"
    • bootfw.img is the usual OFW image format
    • bootfw.key is ASN.1 as defined by the bios_crypto (Whirl->RSA, SHA512->RSA, Whirl->ECC521, SHA512->ECC521)
  • The backup files in /boot-alt have the same names and are in the same formats as /boot.

On USB disk or SD card, the files are as follows:

  • Only one directory, /boot, containing os.zip and bootfw.zip as before
  • Security dicates that we boot from an authenticated filesystem. Rather than have OFW authenticate the full USB/SD contents, we'll boot from an authenticated ramdisk, which can then authenticate whatever other files it needs (if any) from the USB/SD disk. For this reason, any /boot/no-rd file is ignored, and the ramdisk is always used.
    We should be careful to ensure that the files are authenticated after they have been loaded into memory, to prevent attacks involving switching files between authentication and later use.

Process

  1. If OFW fails to come up correctly, a firmware recovery procedure is attempted - details TBD.
  2. In the following, the "primary" images are the files in /boot, and the "secondary" images are the files in /boot-alt, unless the "check" gamepad key is held down during boot, in which case the roles reverse: the primary files come from /boot-alt, and the secondary files come from /boot. In this case, OFW will pass "altboot" on the kernel command line (in addition to any other parameters) and ignore the no-rd file.
    This allows early boot code in the ramdisk to swap /boot and /boot-alt and the appropriate filesystem roots (outside the scope of this spec, but we'll call them /fsroot and /fsroot-alt for now) in order to ensure that we boot from an filesystem consistent with the kernel. This also ensures that the alternate boot is "sticky": we won't try to boot from /boot and /fsroot again until we've performed another upgrade, hopefully fixing the problem with the first.
  3. OFW checks for a new firmware image in the /boot directory on an attached SD or USB device. If one exists and verifies, OFW reflashes itself and reboots.
  4. OFW checks for a new firmware image in the primary directory in the NAND flash. If one exists and verifies, OFW reflashes itself and reboots.
  5. OFW locks out further SPI FLASH writing with the hardware lock.
  6. If a valid developer key is present, OFW enters non-secure mode, where it behaves as it currently does. Otherwise ...
  7. If an activation key is not "present and valid" (fill in details), we will add "activate" to the kernel command line (in addition to any other parameters) and ignore the no-rd file (forcing the boot to use the ramdisk).
  8. Iff the activation key is present and valid, OFW attempts to verify and boot the OS image in /boot on an attached SD or USB device. We ignore any no-rd file.
  9. OFW verifies and boots the primary OS image.
  10. OFW verifies and boots the secondary OS image, toggling the presence of the 'altboot' command line option, and using the ramdisk.
    Do we need this step? It is a bit more user-friendly, but maybe we should instead warn the user that the boot (or upgrade) failed and ask them to reboot with check pressed down instead.
  11. If none of the above booting steps succeed, OFW displays and error screen and halts.

Notes

  • The kernel is going to be identical in the activation and standard boot; no need to store it in /boot twice.
  • Some upgrades have to be able to "move the world", which is hard if you're trying to do them after you're already running code out of the root fs. It's much easier (and more reliable) to do it from an initramfs. Since most of the userland components of this initramfs will be the same as for activation (libc, mount, etc take up most of the space), there is no sense using separate initramfs'en (or kernels) for this.
  • I am assuming that the primary use of USB/SD boot is to do OS, firmware, or activity upgrades where bandwidth is a limitation. These can easily be done with the mechanism provided by just sticking a (properly signed) "magic upgrade key" into the USB port and power-cycling.
  • If USB/SD probing is time-consuming or failure-prone, we might only do those steps if some other special "boot from USB/SD" gamepad key is pressed during boot. But I'm reluctant to add additional magic.
  • We could be even more user-friendly by detecting "failed boot after linux kernel invocation" in some way, and automatically booting from the backup in this case. This seems like post-FRS work.