diff --git a/Readme.md b/Readme.md index aa9c913..5acc200 100644 --- a/Readme.md +++ b/Readme.md @@ -76,7 +76,7 @@ via RPIBOOT on Compute Module 4. | [secure-boot-msd](secure-boot-msd/README.md) | Scripts for signing the MSD firmware so that it can be used on a secure-boot device | | [secure-boot-example](secure-boot-example/README.md) | Simple Linux initrd with a UART console. -** The `secure-boot-msd`, `rpi-imager-embedded` and `mass-storage-gadget` extensions require that the `2022-04-26` (or newer) bootloader EEPROM release has already been written to the EEPROM using `recovery.bin` ** +**The `secure-boot-msd`, `rpi-imager-embedded` and `mass-storage-gadget` extensions require that the `2022-04-26` (or newer) bootloader EEPROM release has already been written to the EEPROM using `recovery.bin`** ## Booting Linux The `RPIBOOT` protocol provides a virtual file-system to the Raspberry Pi bootloader and GPU firmware. It's therefore possible to @@ -91,6 +91,9 @@ Secure Boot requires the latest stable bootloader image. WARNING: If the `revoke_devkey` option is used to revoke the ROM development key then it will not be possible to downgrade to a bootloader older than 2022-01-06 OR disable secure-boot mode. +### Tutorial +Creating a secure-boot system from scratch can be quite complex. The [secure-boot tutorial](secure-boot-example/README.md) uses a minimal example OS image to demonstrate how the Raspberry Pi specific aspects of secure-boot work. + ### Host setup Secure boot require a 2048 bit RSA asymmetric keypair and the Python `pycrytodomex` module to sign the EEPROM config and boot image. @@ -130,7 +133,7 @@ script depends upon the `mkfs.fat` and `losetup` tools and only runs on Linux. ### Root file-system Normally, the Kernel modules and overlays for a secure-boot system would be provided in an [initramfs](https://www.raspberrypi.com/documentation/computers/config_txt.html#initramfs) -and built with (buildroot)[https://buildroot.org/] or (yocto)[https://www.yoctoproject.org/]. +and built with [buildroot](https://buildroot.org/) or [yocto](https://www.yoctoproject.org/). This ensures that all of the kernel modules and device tree dependencies are covered by the secure-boot signature. @@ -201,7 +204,7 @@ the public key may be specified separately via the `-p` argument to `update-piee To extract the public key in PEM format from a private key PEM file, run: ```bash -openssl rsa -in private.pem -pubout -out public.pem` +openssl rsa -in private.pem -pubout -out public.pem ``` #### Copy the secure boot image to the boot partition on the Raspberry Pi. diff --git a/secure-boot-example/README.md b/secure-boot-example/README.md index b9d5147..ca17f3d 100644 --- a/secure-boot-example/README.md +++ b/secure-boot-example/README.md @@ -1,8 +1,158 @@ -This directory contains an example secure boot image signed with the example private key in this directory. +# Secure-boot quickstart + +## Overview +Secure-boot is a mechanism for verifying the integrity of the kernel image and +other files required during boot by storing them in a signed ramdisk image. +These files include the GPU firmware (start.elf etc), Kernel, initrd, device-tree tree +and overlays. +Secure-boot does not depend on particular OS, nor does it provide services +to the OS after startup. However, since the secure-boot will only load trusted +kernel + initrd images the kernel/initrd can safely verify or mount an +an encrypted file-system e.g. by using a TPM. + +N.B The memory for the secure ramdisk is reclaimed as soon as the CPU is started. + +## Example OS +This example includes a simple buildroot image for Compute Module 4 in order +to demonstrate secure-boot on a simple but functional OS. + +The example does NOT modify the OTP or make other permanent changes to the system +and the code-signing can be disabled by reflashing the default bootloader EEPROM. + +The tutorial does not cover how to create the `boot.img` file or permanently +require secure-boot in OTP. Please see the top level [README](../Readme.md#building) and +[secure-boot-recovery/README](../secure-boot-recovery/README.md) guides for +more information. + +### Requirements for running this example +* A Raspberry Pi Compute Module 4 +* Micro USB cable for `rpiboot` connection +* USB serial cable (for debug logs) +* Linux or Cygwin (Windows 10) +* OpenSSL +* Python3 +* Python `cryptodomex` + +```bash +python3 -m pip install pycryptodomex +# or +pip install pycryptodomex +``` + +### Clean configuration +Before starting it's advisable to create a fresh clone of the `usbboot` repo +to ensure that there are no stale configuration files. + +```bash +git clone https://github.com/raspberrypi/usbboot secure-boot +cd secure-boot +make +``` +See the top-level [README](../Readme.md) for build instructions. + +### Hardware setup for `rpiboot` mode +Prepare the Compute Module for `rpiboot` mode. + +* Set the `nRPIBOOT` jumper which is labelled `Fit jumper to disable eMMC Boot' on the Compute Module 4 IO board. +* Connect the micro USB cable to the `USB slave` port on the CM4 IO board. +* Power cycle the CM4 IO board. +* Connect the USB serial adapter to [GPIO 14/15](https://www.raspberrypi.com/documentation/computers/os.html#gpio-and-the-40-pin-header) on the 40-pin header. + +### Reset the Compute Module EEPROM +Enable `rpiboot` mode and flash the latest EEPROM image +```bash +./rpiboot -d recovery +``` + +### Boot the example image +Enable `rpiboot` mode and load the OS via `rpiboot` without enabling code-signing. +```bash +./rpiboot -d secure-boot-example +``` +The OS should load and show activity on the boot UART and HDMI console. + +### Generate a signing key +Secure-boot requires a 2048 bit RSA private key. You can either use a pre-existing +key or generate an specific key for this example. The `KEY_FILE` environment variable +used in the following instructions must contain the absolute path to the RSA private key in +PEM format. + +```bash +openssl genrsa 2048 > private.pem +export KEY_FILE=$(pwd)/private.pem +``` + +**In a production environment it's essential that this key-file is stored privately and securely.** + +### Update the EEPROM to require signed OS images +Enable `rpiboot` mode and flash the bootloader EEPROM with updated setting enables code-signing. + +The `boot.conf` file sets the `SIGNED_BOOT` property `1` which instructs the bootloader to only +load files (firmware, kernel, overlays etc) from `boot.img` instead of the normal boot partition and verify the `boot.img` signature `boot.sig` using the public key in the EEPROM. + +The `update-pieeprom.sh` generates the signed `pieeprom.bin` image. + +```bash +cd secure-boot-recovery +# Generate the signed EEPROM image. +../tools/update-pieeprom.sh -k "${KEY_FILE}" +cd .. +./rpiboot -d secure-boot-recovery +``` + +At this stage OTP has not been modified and the signed image requirement can be reverted by flashing a default, unsigned image. +However, once the [OTP secure-boot flags](../secure-boot-recovery/README.md#locking-secure-boot-mode) are set then `SIGNED_BOOT` is permenantely enabled and cannot be overriden via the EEPROM config. + + +### Update the signature for the example OS image +```bash +cd secure-boot-example +../tools/rpi-eeprom-digest -i boot.img -o boot.sig -k "${KEY_FILE}" +cd .. +``` + +### Launch the signed OS image +Enable `rpiboot` mode and run the example OS as before. However, if the +`boot.sig` signature does not match `boot.img` the bootloader will refuse to +load the OS. -To sign the image with a different key run ```bash +./rpiboot -d secure-boot-example +``` + +This example OS image is minimal Linux ramdisk image. Login as `root` with the empty password. + +### Mount the CM4 SD/EMMC after enabling secure-boot +Now that `SIGNED_BOOT` is enabled the bootloader will only load images signed with private key generated earlier. +To boot the Compute Module in mass-storage mode a signed version of this code must be generated. + +**This signed-image should not be made available for download because it gives access to the EMMC as a block device** + + +#### Sign the mass storage firmware image +Sign the mass-storage drivers in the `secure-boot-msd` directory. Please see the [top level README](../Readme.md#compute-module-4-extensions) for a description of the different `usbboot` firmware drivers. +```bash +cd secure-boot-msd ../tools/rpi-eeprom-digest -i boot.img -o boot.sig -k "${KEY_FILE}" +cd .. ``` -Clearly, product releases should never be signed with `example-private.pem`. +#### Enable MSD mode. +A new mass-storage device should now be visible on the host-OS. On Linux check `dmesg` for something like '/dev/sda' +```bash +./rpiboot -d secure-boot-msd +``` + +### Loading `boot.img` from SD/EMMC. +The bootloader can load a ramdisk `boot.img` from any of the bootable modes defined by the [BOOT_ORDER](https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#BOOT_ORDER) EEPROM config setting. + +For example. + +* Boot the CM4 in MSD mode as explained in the previous step. +* Copy the `boot.img` and `boot.sig` files from the `secure-boot-example` stage to the mass-storage-drive. No other files are required. +* Remove the `nRPIBOOT` jumper. +* Power cycle the CM4 IO board. +* The system should now boot into the OS. + +N.B. The example image is currently the same as the `mass-storage-gadget so the EMMC/SD will appear as block devices on the host PC if the micro USB cable is still connected. + diff --git a/secure-boot-example/boot.img b/secure-boot-example/boot.img index 2582ff8..8b488f2 100644 --- a/secure-boot-example/boot.img +++ b/secure-boot-example/boot.img diff --git a/secure-boot-example/boot.sig b/secure-boot-example/boot.sig index ffa9f4e..25a50ca 100644 --- a/secure-boot-example/boot.sig +++ b/secure-boot-example/boot.sig @@ -1,3 +1,3 @@ -f2557e1745433a570d9f2f0d9f69b7ca3123d2be20425c0fd80c5ffbec0cba69 -ts: 1645529528 -rsa2048: b4e1467691c03a1faf467166d4d1439704fb52cd8fd8b8016f6bd144fb750a80dbb933ea85e352c080f9cccd170cdd71565d00b4e80d6d8ec6374aa5826eb5470b17a8bb47a3ef5ad111cd253092c9dca3488c73d653a3ed04c92fab08e142908e2f7f5e393d65a2e1cb8e7748d3f75ae66d904e1ff253e4e28ed58b66e93bac4e88ea4b544353310f103bf6e2cbd59df9df0e2d548f71219d8d1aeeb101dc5a3d507d87b26ae656d00b14554af30bc2ba18b76783c3666db1743bd210b3f31e4ee49743ba04bd27e05d7c1d244c4066dc312ec793cda30f93f3031b8394206b1cd488d8589040392a3a5186332c134be1a6c25b72212fed12ff4bb7032fa5ea +087d95cc403464a5d2385a0832c912fffb084799952c207a0867d8269acb1c55 +ts: 1652640519 +rsa2048: d97c850205fde305a24e12ea4c31994d57c95f394b83cc62e2878ab122f3b4688a0a577acb7de74f800866c6676cba1d646cb7e3b4e2ea30786aa193326db6461776d30264a4e7ef9f5465a8e4c31129515305ffa4ca91499372d663b18e3f7505e4d1a83fd930df8296bee056d1ec823bc8909a836e2ae21d131ed33779665abfc2d0b47b66f109246b89a6d4b8ee8df8334d6ef7e910b5624c299fcb16efb62d43d7b228d2ef770d0326132b97d54a8d2afbbf09bf53034f2c1f3c748a619437cd523c5c6a706d12fc2e3e285ec7d3b65be16c1ed33e47faf6565ab13cee4a01682ecc70d10c683c193caf02a6a2380572aa590f06be13481f365c0e686a78 diff --git a/secure-boot-example/bootcode4.bin b/secure-boot-example/bootcode4.bin new file mode 100644 index 0000000..e31e21e --- /dev/null +++ b/secure-boot-example/bootcode4.bin diff --git a/secure-boot-example/config.txt b/secure-boot-example/config.txt new file mode 100644 index 0000000..4fcb5e9 --- /dev/null +++ b/secure-boot-example/config.txt @@ -0,0 +1,3 @@ +# Load the boot files from the ramdisk which is signed in secure-boot mode +boot_ramdisk=1 +uart_2ndstage=1