Firmware security for Windows

From OLPC
Jump to: navigation, search

Firmware_security describes the Open Firmware (OFW) aspects of Bitfrost security with specific reference to booting Linux. This document describes the extension of that scheme to booting Windows XP. One goal is to preserve as much of the existing model and the existing code as possible, thereby retaining the validity of the testing and review that has already happened for that code.

OFW/Bitfrost Overview

Briefly, when Bitfrost security in enabled in OFW, the booting process is as follows. For clarity, this summary omits provisions for firmware update, operating system update, activation-level security, and developer keys, concentrating on the usual process of booting the operating system.

  • OFW searches a list of devices (e.g. USB, SD, internal mass storage) for a file named "/boot/runos.zip".
  • runos.zip is a ZIP archive containing two sub-files - "data.img" and "data.sig"
    • data.img is the code (typically a machine code program) that OFW will execute to boot the OS
    • data.sig is a cryptographic signature of the contents of "data.img"
  • If the stored and computed signatures do not match, OFW aborts the booting process
  • On the same device where OFW found runos.zip, it look for another file named "/boot/runrd.zip"
  • runrd.zip is a ZIP archive containing two sub-files - "data.img" and "data.sig"
    • data.img is a "ramdisk" image of additional files that "runos" needs to complete booting
    • data.sig is a cryptographic signature of the contents of "data.img"
  • If the stored and computed signatures do not match, OFW aborts the booting process

OFW/Bitfrost uses this bundling format - a ZIP archive containing data.img and data.sig - consistently for all the signed objects that it handles. Bundling in this way keeps the signed data and its signature together. The "data.img" and "data.sig" files inside the ZIP archive are not compressed at the ZIP level - they are "stored", not "deflated" - but they may very well be compressed internally. The point is that the OFW code that processes the bundle at this level does not automatically "inflate" the contents. It just uses the ZIP archive format as a convenient way of grouping the two files together, computing the signature on the verbatim contents of data.img.

For reference, in the Linux case:

  • "runos" (the "data.img" inside "runos.zip") is a Linux kernel in standard Linux bzimage format.
  • "runrd" (the "data.img" inside "runrd.zip") is a Linux "initramfs" image in standard Linux cpio format.
  • "/boot/runos.zip" and "/boot/runrd.zip" are files in the device's default partition. That partition is formatted with one of the filesystems for which OFW has a built-in reader (FAT, ext2, JFFS2), so OFW can read the files directly.

This OFW/Bitfrost security scheme can be applied to booting Windows as follows:

  • "runos" is NTLDR
  • "runrd" is an NTFS filesystem image containing the files that NTLDR reads prior to handing control to the Windows kernel
  • "/boot/runos.zip" and "/boot/runrd.zip" are stored in a "hidden" area on the SD card, after the MBR sectors and before the start of the system partition.

Additional details are described below.

Conventional WindowsXP Booting

For reference, a conventional PC boots Windows XP as follows:

  1. BIOS sector 0 from the disk into memory at 0x7c00 and jumps to it in real mode. The code in sector 0 is called the Master Boot Record or MBR. At the end of that sector, starting at offset 0x1be, there is a partition table describing up to four primary partitions.
  2. The MBR code relocates itself to address 0x600, then uses BIOS INT 13 to read the first sector of the partition that is marked bootable into memory at 0x7c00, and jumps to it, still in real mode.
  3. The code that is now executing (the partition boot record) reads the first 16 sectors of the partition into memory at 0xd000 (thus rereading the first sector of the partition), and jumps to an entry point, still in real mode. That new code contains a rudimentary NTFS reader. I shall call that code the "early booter" for want of a better name.
  4. The early booter uses its NTFS reader to search the system partition for the file NTLDR, reads it into memory, and jumps to it. At this stage, low-level disk I/O is still done with BIOS INT 13.
  5. NTLDR reads several files from the NTFS system partition, including BOOT.INI, NTDETECT.COM, NTOSKRNL.EXE, and numerous system files. Low-level I/O is still done with BIOS INT 13.
  6. When all of the necessary files have been loaded, NTLDR jumps to NTOSKRNL
  7. NTOSKRNL completes the booting process, using its own driver for the system disk (which was one of the files that NTLDR loaded). BIOS INT 13 is no longer used. The only BIOS calls after this point are for VGA mode switching.

Secure WindowsXP Booting with OFW/Bitfrost

To boot WindowsXP securely, OFW replaces steps 1-3 above with the Bitfrost booting procedure described earlier. OFW gets NTDLR from the file "runos.zip", verifies its signature, and executes it directly, bypassing the MBR and early booter steps.

In secure mode, OFW implements BIOS INT 13 so that, instead of returning data directly from disk blocks, it returns data from the ramdisk image that was loaded (and its signature verified) from "runrd.zip". That ramdisk image contains a verbatim image of an NTFS filesystem that contains all of the files that NTLDR accesses prior to jumping to NTOSKRNL.

NTOSKRNL operates the same as in the conventional case, accessing the "real" system partition via its native driver for the system disk.

Locations of runos.zip and runrd.zip

When the system volume is on an SD card, Windows requires that the card must have a single partition containing an NTFS filesystem. Sector 0 must contain a conventional FDISK-style partition map describing that one partition. (As described above, sector 0 also contains the MBR code.) There may be unused space after sector 0 and before the beginning of the NTFS partition.

OFW does not have an NTFS reader, so runos.zip and runrd.zip cannot be inside the system partition. The solution is to leave some extra space before the start of the system partition. The MBR occupies sector 0, so runos.zip and runrd.zip can start at sector 1 and extend to just before the system partition. The FDISK partition map does not have an explicit partition entry for that area - it is just "hidden" space.

We will call that extra hidden space the "Secure Boot Area", or SBA.

The SBA needs to contain multiple files - runos.zip, runrd.zip, and optional others that will be described later - so it needs some kind of filesystem structure. Since the SBA is very rarely changed, it's not necessary for the filesystem to support frequent updates, thus a "read mostly" filesystem is appropriate. The desirable features are:

  • Must support named files, preferably with pathnames
  • The file sizes must be determinable
  • The format should be easy to read (simple code in OFW)
  • Tools for creating the filesystem image (offline) must be readily available

The ZIP format fulfils these requirements nicely. Thus the SBA contains a single ZIP archive which in turn contains "/boot/runos.zip" and "/boot/runrd.zip" - multiple zip files inside a zip file. It may contain other files as needed.

Additional Files for Other Scenarios

In addition to /boot/runos.zip and /boot/runrd.zip, OFW/Bitfrost looks for some other optional files in the boot volume. Some of these may be useful in the Windows case too:

  • /boot-alt/runos.zip and /boot-alt/runrd.zip - These are used for "recovery" booting, in case you install a new OS and it doesn't work right. OFW uses these files instead of the normal /boot/* versions if you hold down the "O" button on the game pad while starting. This feature may be useful for Windows. As an alternative to the intended case where the "-alt" files contain the last older version of the files, the "-alt" files could instead be used for "maintenance mode" or "repair console" files.
  • /boot[-alt]/actos.zip and /boot[-alt]/actrd.zip - OFW loads these files instead of the "run" versions when the OLPC machine does not have a valid and up-to-date "activation lease". I am assuming that activation-level security will not be used for Windows - or if it is used, it will be handled using a different mechanism. If so, this feature will not be needed for Windows. In the Linux case, the separation between the "run" and "act" files is actually used in practice. There is really only one "os" file and one "rd" file, using symbolic links to make them appear with the multiple name prefixes "run" and "act".
  • /security/lease.sig - This is the time-based activation lease file. As above, I assume that this will not be used for Windows.
  • /security/develop.sig - This is the machine-specific developer key that disables security for this machine. If it were present in the SBA ZIP archive, the feature would work, but I think we don't need to worry about it. Firstly, recreating the SBA ZIP with develop.sig inside would be inconvenient. Secondly, you can get the same effect by putting develop.sig on a USB key and booting from that.
  • /fs.zip - This is a signed bundle containing a that can be used to rewrite the entire contents of the system disk. On XO-1, as currently implemented, it is specific to the XO-1's internal raw NAND FLASH, so it's not applicable to Windows. On XO-1.5, it has been extended to support SD cards, so in principle it could be used for installing Windows onto an SD card. The fs.zip file is typically much too large to fit in the Secure Boot Area, so we don't have to worry about it in regards to what is on the bootable Windows SD card. If you wanted to use this mechanism for a Windows image install, the fs.zip file could just be stored on a FAT-formatted device as is the usual case.

The possibility of OLPC machines being either not activated or permanently activated begs the question of whether to name the files with the "run" or the "act" prefix. I think the best solution is to use the same approach as Linux - symbolic links to give the same file both names. The ZIP file format supports symbolic links.

SBA Size

The suggested size for the SBA is 64 MB minus 512 bytes. The system partition would thus start at byte offset 64 MB (sector 131072) and the SBA would start at byte offset 512 bytes (sector 1). The SBA size - nearly 64 MB - gives enough room for alternate copies of runos.zip and runrd.zip (/boot-alt/* instead of /boot/*), so recovery booting is possible, plus some headroom for future expansion.

Note that this size is not a fixed parameter as far as OFW is concerned. OFW will treat the entire space from sector 1 to the beginning of the first partition as the SBA. Thus it is possible to change the SBA size without changing OFW.

Tools

Command line tools (Linux-based) for managing OFW/Bitfrost signed objects can be found at http://dev.laptop.org/git/bios-crypto . The tools include facilities for creating new key pairs, signing images with those keys, and bundling keys and images into a .zip file (with the help of the common Linux "zip" utility). You can check out a copy of the directory with

 git clone git://dev.laptop.org/bios-crypto

Compile the toolset with

 cd build
 make

"build/README" contains brief usage instructions.