|
| 1 | +# Secure boot |
| 2 | + |
| 3 | +This page describes how to enable secure-boot mode using the `rpiboot` provisioning tool and provides a low-level overview of how secure-boot works on a Raspberry Pi 4 (or newer). These tools are used by the [Raspberry Pi - Secure Boot Provisioner](https://github.com/raspberrypi/rpi-sb-provisioner), the officially supported application for provisioning secure-boot on Raspberry Pi devices. |
| 4 | + |
| 5 | +Before programming secure-boot, a suitable OS image must be created. This is part of the application or product design process and is outside the scope of this document. We recommend using [rpi-image-gen](https://github.com/raspberrypi/rpi-image-gen) to generate custom Debian-based operating system images, though it is also possible to use Yocto or Buildroot. |
| 6 | + |
| 7 | +**Once secure-boot has been enabled by programming the one-time programmable (OTP) fuses, it cannot be disabled and a different key cannot be programmed.** |
| 8 | + |
| 9 | + |
| 10 | +## Secure-boot overview |
| 11 | + |
| 12 | +## Verified boot flow - chain-of-trust |
| 13 | +Secure-boot uses cryptographic signing to ensure the OS kernel and all required boot components loaded into RAM are authenticated using the customer’s private key. The bootloader firmware verifies these signatures, and the bootloader itself is verified by the SoC BootROM using the Raspberry Pi public keys embedded in the BootROM. The BootROM is fused into the silicon and serves as the immutable root of trust. |
| 14 | + |
| 15 | +### Secure-boot high-level flow |
| 16 | +* BootROM loads the second-stage (`bootsys`) from SPI flash and verifies it is signed by a valid Raspberry Pi BootROM key. |
| 17 | +* `bootsys` loads the customer’s public key from EEPROM and checks it against the customer key hash stored in OTP, previously written via `rpiboot`. |
| 18 | +* `bootsys` initializes SDRAM and loads `bootmain`. When loading firmware dependencies from SPI flash, it verifies each dependency’s hash against a list embedded within `bootsys` at build time. |
| 19 | +* `bootmain` loads the OS boot ramdisk files (`boot.img` and `boot.sig`) from SD/EMMC/USB/NVMe/Network into memory. It verifies that the hash of `boot.img` matches `boot.sig` and that the RSA signature in `boot.sig` can be validated using the customer’s public key. |
| 20 | +* `bootmain` then uses the verified ramdisk to load the GPU firmware (`start.elf`) and start the operating system. With secure-boot enabled, firmware only loads files from the verified ramdisk, ensuring the OS kernel and all dependencies are authenticated against the customer’s key. |
| 21 | + |
| 22 | +If any signature or hash verification fails, the current boot mode is aborted and the firmware advances to the next boot mode. |
| 23 | + |
| 24 | +See also:- |
| 25 | +* Secure boot BCM2711 [chain of trust diagram](docs/secure-boot-chain-of-trust-2711.pdf). |
| 26 | +* Secure boot BCM2712 [chain of trust diagram](docs/secure-boot-chain-of-trust-2712.pdf). |
| 27 | + |
| 28 | +## boot.img files |
| 29 | +Secure-boot requires a self-contained ramdisk (`boot.img`) FAT image containing the GPU firmware, kernel and any other dependencies that would normally be loaded from the boot partition. |
| 30 | + |
| 31 | +This enables the bootloader to verify that the kernel and all dependencies loaded into memory can be validated against the signature in `boot.sig`, signed with the customer's private RSA key. |
| 32 | + |
| 33 | +The `boot.img` and corresponding `boot.sig` file must be placed in the device's boot partition or network download location. |
| 34 | + |
| 35 | +The `boot.img` file should contain: |
| 36 | +* config.txt |
| 37 | +* Device tree and overlay files |
| 38 | +* GPU firmware (`start.elf` and `fixup.dat`) |
| 39 | +* Linux kernel image |
| 40 | +* Linux initramfs containing the application OR scripts to mount/create an encrypted filesystem. |
| 41 | + |
| 42 | +### Additional documentation |
| 43 | + |
| 44 | +* Secure boot [configuration properties](https://www.raspberrypi.com/documentation/computers/config_txt.html#secure-boot-configuration-properties). |
| 45 | +* Device tree [bootloader signed-boot property](https://www.raspberrypi.com/documentation/computers/configuration.html#bcm2711-and-bcm2712-specific-bootloader-properties-chosenbootloader). |
| 46 | +* Device tree [public key - NVMEM property](https://www.raspberrypi.com/documentation/computers/configuration.html#nvmem-nodes). |
| 47 | +* Raspberry Pi [OTP registers](https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#otp-register-and-bit-definitions). |
| 48 | +* Raspberry Pi [device specific private key](https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#device-specific-private-key). |
| 49 | + |
| 50 | +## Configuring and running the rpiboot secure-boot tools |
| 51 | + |
| 52 | +### Host Setup |
| 53 | +Secure boot requires a 2048-bit RSA asymmetric keypair and the Python `pycryptodome` module to sign the bootloader EEPROM config and boot image. |
| 54 | + |
| 55 | +#### Install Python Crypto Support (the pycryptodomex module) |
| 56 | +```bash |
| 57 | +sudo apt install python3-pycryptodome |
| 58 | +``` |
| 59 | + |
| 60 | +#### Create an RSA key-pair using OpenSSL. Must be 2048 bits |
| 61 | +Secure-boot requires that the SPI flash configuration and `boot.img` file is signed with the customer's RSA private key. |
| 62 | + |
| 63 | +It is **critical** that this key is stored securely and backed up. It should not be installed in the target OS image. |
| 64 | + |
| 65 | +For reference, this command will generate a private key in the expected format. |
| 66 | +```bash |
| 67 | +cd $HOME |
| 68 | +openssl genrsa 2048 > private.pem |
| 69 | +``` |
| 70 | + |
| 71 | +### Programming the OTP and signed EEPROM image |
| 72 | +* Please see the [secure boot EEPROM guide](secure-boot-recovery/README.md) to enable via rpiboot `recovery.bin`. |
| 73 | +* Please see the [secure boot MSD guide](mass-storage-gadget64/README.md) for instructions about how to mount the eMMC via USB mass-storage once secure-boot has been enabled. |
| 74 | + |
| 75 | +### Disk encryption |
| 76 | +Secure-boot is responsible for loading the Kernel + initramfs and loads all of the data |
| 77 | +from a single `boot.img` file stored on an unencrypted FAT/EFI partition. |
| 78 | + |
| 79 | +**There is no support in the ROM or firmware for full-disk encryption.** |
| 80 | + |
| 81 | +Instead, we recommend storing the root filesystem within a LUKS container that is mounted by scripts within initramfs. The LUKS passphrase can be derived from a key stored in OTP. |
| 82 | + |
| 83 | +See [device specific private key](https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#device-specific-private-key). |
| 84 | + |
| 85 | +The OTP key is protected against external access by the verified boot flow provided by secure-boot. However, Raspberry Pi computers do not have a secure hardware enclave, and within the secure-boot OS image this key is accessible to any process with access to `/dev/vcio` (`vcmailbox`). |
| 86 | + |
| 87 | +**It is not possible to prevent code running in ARM supervisor mode (e.g. kernel code) from accessing OTP hardware directly.** |
| 88 | + |
| 89 | +See also: |
| 90 | +* [LUKS](https://en.wikipedia.org/wiki/Linux_Unified_Key_Setup) |
| 91 | +* [cryptsetup FAQ](https://gitlab.com/cryptsetup/cryptsetup/-/wikis/FrequentlyAskedQuestions) |
| 92 | +* [rpi-otp-private-key](./tools/rpi-otp-private-key) |
| 93 | + |
| 94 | +The [secure boot tutorial](secure-boot-example/README.md) contains a `boot.img` that supports cryptsetup and a simple example. |
| 95 | + |
| 96 | +### Building `boot.img` using buildroot |
| 97 | + |
| 98 | +The `secure-boot-example` directory contains a simple `boot.img` example with working HDMI, |
| 99 | +network, UART console and common tools in an initramfs. |
| 100 | + |
| 101 | +This was generated from the [raspberrypi-signed-boot](https://github.com/raspberrypi/buildroot/blob/raspberrypi-signed-boot/README.md) |
| 102 | +buildroot config. Whilst not a generic fully featured configuration it should be relatively |
| 103 | +straightforward to cherry-pick the `raspberrypi-secure-boot` package and helper scripts into |
| 104 | +other buildroot configurations. |
| 105 | + |
| 106 | +#### Minimum firmware version |
| 107 | +The firmware must be new enough to support secure boot. The latest firmware APT |
| 108 | +package supports secure boot. To download the firmware files directly, run: |
| 109 | + |
| 110 | +```bash |
| 111 | +git clone --depth 1 --branch stable https://github.com/raspberrypi/firmware |
| 112 | +``` |
| 113 | + |
| 114 | +To check the version information within a `start4.elf` firmware file run |
| 115 | +```bash |
| 116 | +strings start4.elf | grep VC_BUILD_ |
| 117 | +``` |
| 118 | + |
| 119 | +#### Verifying the contents of a `boot.img` file |
| 120 | +To verify that the boot image has been created correctly use losetup to mount the .img file. |
| 121 | + |
| 122 | +```bash |
| 123 | +sudo su |
| 124 | +mkdir -p boot-mount |
| 125 | +LOOP=$(losetup -f) |
| 126 | +losetup ${LOOP} boot.img |
| 127 | +mount ${LOOP} boot-mount/ |
| 128 | + |
| 129 | +echo boot.img contains |
| 130 | +find boot-mount/ |
| 131 | + |
| 132 | +umount boot-mount |
| 133 | +losetup -d ${LOOP} |
| 134 | +rmdir boot-mount |
| 135 | +``` |
| 136 | + |
| 137 | +#### Signing the boot image |
| 138 | +For secure-boot, `rpi-eeprom-digest` extends the current `.sig` format of |
| 139 | +sha256 + timestamp to include a hex-format RSA PKCS#1 v1.5 signature. The key length |
| 140 | +must be 2048 bits. |
| 141 | + |
| 142 | +```bash |
| 143 | +../tools/rpi-eeprom-digest -i boot.img -o boot.sig -k "${KEY_FILE}" |
| 144 | +``` |
| 145 | + |
| 146 | +To verify the signature of an existing image set the `PUBLIC_KEY_FILE` environment variable |
| 147 | +to the path of the public key file in PEM format. |
| 148 | + |
| 149 | +```bash |
| 150 | +../tools/rpi-eeprom-digest -i boot.img -k "${PUBLIC_KEY_FILE}" -v boot.sig |
| 151 | +``` |
| 152 | + |
| 153 | + |
| 154 | +#### Hardware security modules |
| 155 | +`rpi-eeprom-digest` is a shell script that wraps a call to `openssl dgst -sign`. |
| 156 | +If the private key is stored within a hardware security module instead of |
| 157 | +a .PEM file the `openssl` command will need to be replaced with the appropriate call to the HSM. |
| 158 | + |
| 159 | +`rpi-eeprom-digest` is called by `update-pieeprom.sh` to sign the EEPROM config file. |
| 160 | + |
| 161 | +The RSA public key must be stored within the EEPROM so that it can be used by the bootloader. |
| 162 | +By default, the RSA public key is automatically extracted from the private key PEM file. Alternatively, |
| 163 | +the public key may be specified separately via the `-p` argument to `update-pieeprom.sh` and `rpi-eeprom-config`. |
| 164 | + |
| 165 | +To extract the public key in PEM format from a private key PEM file, run: |
| 166 | +```bash |
| 167 | +openssl rsa -in private.pem -pubout -out public.pem |
| 168 | +``` |
| 169 | + |
| 170 | +#### Copy the secure boot image to the boot partition on the Raspberry Pi. |
| 171 | +Copy `boot.img` and `boot.sig` to the boot filesystem. |
| 172 | +Secure boot images can be loaded from any of the normal boot modes (e.g. SD, USB, Network). |
0 commit comments