# Raspberry Pi 5 - secure boot

# Required packages
```bash
sudo apt install xxd python3-pycryptodome
```

## Optional. Specify the private key file in an environment variable.
Alternatively, specify the path when invoking the helper scripts.
```bash
export KEY_FILE="${HOME}/private.pem"
```

## Optional. Customise the EEPROM config.
Customise with the desired bootloader settings.
See: [Bootloader configuration](https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#raspberry-pi-bootloader-configuration)

## Sign the EEPROM and the second stage bootloader
The BCM2712 boot ROM requires the second-stage firmware (recovery.bin / bootcode5.bin) to be counter-signed with the customer private key in secure-boot mode.
Pass the `f` flag to enable firmware counter-signing.

### Using a private key file
```
../tools/update-pieeprom.sh -f -k "${KEY_FILE}"
```

If secure-boot has already been enabled on the device, then `recovery.bin` must also be counter-signed.
However, booting a counter-signed `recovery.bin` image on a fresh board without secure-boot enabled will fail
because the ROM is effectively checking this against a key hash of zero.
```
../tools/update-pieeprom.sh -fr -k "${KEY_FILE}"
```

### Using an HSM wrapper
When using a Hardware Security Module (HSM), you need to provide both the HSM wrapper script and the corresponding public key:

```
../tools/update-pieeprom.sh -f -H hsm-wrapper -p public.pem
```

For recovery.bin signing with HSM:
```
../tools/update-pieeprom.sh -fr -H hsm-wrapper -p public.pem
```

The HSM wrapper script should:
- Take a single argument which is a temporary filename containing the data to sign
- Output the PKCS#1 v1.5 signature in hex format
- Return a non-zero exit code if signing fails

`pieeprom.bin` can then be flashed to the bootloader EEPROM via `rpiboot`.

## Programming the EEPROM image using rpiboot
* Power off the device
* Set nRPIBOOT jumper (or hold power button before power on) and remove EEPROM WP protection
```bash
cd secure-boot-recovery5
mkdir -p metadata
../rpiboot -d . -j metadata
```

## Requirement for flashed OTP
The BCM2712 will not boot a signed EEPROM image unless it holds the public key in its One Time Programmable (OTP) memory. If you try to boot a signed EEPROM image without burning the public key into OTP:

* The EEPROM firmware will not run and there will be no output on the debug header. The device will not boot.
* On the BCM2712 C1 stepping (found on older Pi 5B models), the boot LED on the Raspberry Pi 5B will display an error code by flashing green 2 times.
* On the BCM2712 D0 stepping (found on Pi 500, CM5, and newer Pi 5Bs), the boot LED will not display an error code, however the device will still not boot.

This is different from the BCM2711 chip used in the Raspberry Pi 4B and CM4. On the BCM2711, it was possible to test out the secure boot flow without making irreversible changes to the OTP. The user could flash a signed `pieeprom.bin` EEPROM firmware image and test that it would verify the signature of the `boot.img` file correctly. On the Pi 5, this is not possible.

However, it is possible to check that your signed `boot.img` file is bootable on the BCM2712. To do this, place the files `boot.img` and `boot.sig` in the `boot` partition of your Raspberry Pi OS image. Then modify the file `config.txt` on the boot partition to contain the entry `boot_ramdisk=1`. On the next boot, the Raspberry Pi will unpack the `boot.img` into memory and treat it as the boot partition.

### Example UART output
This output is given by the EEPROM bootloader when it verifies the signature of a `boot.img`. It can be read over the [3-pin Serial Debug Port](https://datasheets.raspberrypi.com/debug/debug-connector-specification.pdf). This is accessible via a JST-SH header on the Pi 5B. On the CM5, it is unpopulated on the top side of the board.
```
3.04 OTP boardrev b04170 bootrom a a
3.06 Customer key hash 8251a63a2edee9d8f710d63e9da5d639064929ce15a2238986a189ac6fcd3cee
3.13 VC-JTAG unlocked
3.36 RP1_BOOT chip ID: 0x20001927
3.41 bootconf.sig
3.41 hash: f71ede8fad8bea2f853bcff41173ffedde48c5b76ed46bc38fa057ce46e5d58b
3.47 rsa2048:  
3.94 RSA verify
3.10 rsa-verify pass (0x0)

```

### Metadata
Metadata output is enabled by default to stdout. Optional argument can be used to specify writing a JSON file to the given directory.
This can be useful for debug or for storing in a provisioning database.

Example metadata:
```json
{
        "USER_SERIAL_NUM": "a7eb274c",
        "MAC_ADDR": "2c:cf:67:70:76:f3",
        "EEPROM_UPDATE": "success",
        "EEPROM_HASH": "dfc8ef2c77b8152a5cfa008c2296246413fd580fdc26dfacd431e348571a2137",
        "SECURE_BOOT_PROVISION": "success",
        "CUSTOMER_KEY_HASH": "8251a63a2edee9d8f710d63e9da5d639064929ce15a2238986a189ac6fcd3cee",
        "BOOT_ROM": "0000000a",
        "BOARD_ATTR": "00000000",
        "USER_BOARDREV": "b04170",
        "JTAG_LOCKED": "0",
        "SIGNATURE_MODE": "0",
        "MAC_WIFI_ADDR": "2c:cf:67:70:76:f4",
        "MAC_BT_ADDR": "2c:cf:67:70:76:f5",
        "FACTORY_UUID": "001000911006186073"
}
```

* Power ON the DUT

## Locking secure-boot mode
After verifying that the signed OS image boots successfully the system
can be locked into secure-boot mode.  This writes the hash of the
customer public key to "one time programmable" (OTP) bits. From then
onwards:

* The 2712 boot ROM verifies that the second-stage firmware (recovery.bin / bootsys) is
  signed with the customer private key in addition to the Raspberry Pi private key.
* The bootloader will only load OS images signed with the customer private key.
* The EEPROM configuration file must be signed with the customer private key.
* It is not possible to downgrade to an old version of the bootloader that doesn't
  support secure boot.


To enable this, edit the `config.txt` file in this directory and set `program_pubkey=1`
before flashing the Pi firmware as described in the section `Programming the EEPROM image using rpiboot`.

Note that the file `config.txt` in this directory is unrelated to the `config.txt` commonly
found in the boot parition of Raspberry Pi OS. The file `config.txt` in this directory
is used to configure the `rpiboot` tool.

## Disabling VideoCore JTAG

VideoCore JTAG may be permanently disabled by setting `program_jtag_lock` in
`config.txt`. This option has no effect unless the public key hash (`program_pubkey`) has been successfully programmed.

See [config.txt](config.txt)
