Skip to content

Secure Boot on Raspberry Pi 4

This page explains the bootloader authentication and secure boot setup for the Raspberry Pi 4.

References:

Acronyms:

  • CUSTPBK: Customer Public Key
  • CUSTPVK: Customer Private Key
  • BL2: Boot Loader stage 2, in the EEPROM, contains the pieeprom binary, its configuration, the configuration signature and CUSTPBK
  • BL3: Boot Loader stage 3, in the SD card, contains boot.img and boot.sig, its signature
  • PBKH: Public Key Hash (SHA256 of CUSPBK)

Raspberry Pi 4 Secure boot Overview

Raspberry Pi 4 secure boot overview

The SoC contains some proprietary keys from Raspberry that authenticate bootsys and bootmain. It also contains OTP to store the customer PBKH to authenticate the EEPROM configuration file and the content of the SD card.

The SD card must contain a vfat boot partition which itself contains two files called boot.img and its signature boot.sig.

boot.img is a vfat image of the original Raspberry Pi boot partition and contains all the bootfiles (start.elf, config.txt, cmdline.txt...), the DTBs and their overlays and the U-Boot binary (referred to as kernel in the image above).

Secure boot stages

The secure boot process involves multiple stages of verification. It begins with the ROM code and continues through the loading and execution of all bootloader firmware components.

Throughout all authentication and signature processes, we use RSA-2048 key pairs (2048-bits) and SHA-256 for hash computation.

  1. BL2:

    • Assets contained in BL2:

      • bootloader code
      • bootloader config (and signature)
      • CUSTPBK
    • Authentication:

      • The ROM code authenticates the bootloader code using the proprietary keys stored in the SoC.
      • The ROM code starts the bootloader code.
      • BL2 authenticates the CUSTPBK using the PBKH stored in the OTP fuses.
      • BL2 authenticates the bootloader config using CUSTPBK.
  2. BL3

    • Assets contained in BL3:

      • boot.img (and signature)
    • Authentication:

      • BL2 authenticates boot.img using CUSTPBK.
  3. BL2 starts BL3 (start.elf, ..., U-Boot)

Setting up your Secure Boot

This section will guide you through the process of building and running an image with secure boot.

It is assumed the following context:

  • Raspberry Pi 4B
  • Default Welma partition layout
  • Default Welma development keys used in the Yocto build
  • Production keys owned by a separate entity (other than the development team)

Building your Image

Welma requirements:

  • machine.conf:

    • Set BOOT_SIGNING_MECHANISM = "raspberrypi" (this is the default)
  • In local.conf

    • Activate secure boot by defining WELMA_SECURE_BOOT = "1" (this is the default)
    • Adjust or keep the default values for WELMA_KEY_SWK1_PUB and WELMA_KEY_SWK1_PRIV
  • u-boot:

    • Disable the U-Boot command line or restrict its access by a password (not done in Welma), because it would allow an attacker to bypass the secure boot mechanism.
  • In SYSRO and APPRO: have your programs not start other programs located in SYSRW, as this filesystem is not covered by secure boot. Keep in mind that /home is located in SYSRW and make sure that files such as ~/.profile, ~/.bashrc, etc. do not get executed automatically if they were created by an attacker.

Signing your Image with Production Keys

Input:

  • Generated by the build:

    • BL2 Firmware
    • BL3 boot image
    • fitImage (BOOT)
    • .verity images (SYSRO, APPRO)
  • Production Keys: SWK1.priv, SWK1.crt

Output (signed images provisioned with necessary public keys and certificates):

  • BL2 Firmware
  • BL3 boot image
  • BOOT vfat partition
  • SYSRO and APPRO verity partitions

Steps:

  • Inject SWK1.crt into DTB
    • Mount boot.img using a loop device
      mkdir boot
      sudo mountboot.img boot -o loop
      
    • Create the Device Tree Overlay containing SWK1:
      welma-signing-tools/raspberrypi4/create-dtbo-public-key SWK1.crt \
          swk1.dtbo
      
    • Copy the DTBO in the overlays directory
      cp swk1.dtbo boot/overlays
      
    • Unmount the directory
      sudo umount boot
      
  • Sign BL2
  • Sign the boot image

  • Sign fitImage:

    welma-signing-tools/common/sign-fitimage SWK1.priv fitImage
    

    • Create the BOOT partition (vfat) populated with the signed fitImage, using mkdosfs & mcopy
  • Sign .verity images:

    welma-signing-tools/common/sign-verity-device \
                --device <appro.verity> \
                --key SWK1.priv
    
    welma-signing-tools/common/sign-verity-device \
                --device <sysro.verity> \
                --key SWK1.priv
    

Install Secure Boot compatible BL2

To enable secure boot, you need to flash a different BL2 that authenticates your bootable media. This new BL2 is created during the build and signed with CUSTPVK. To flash your Raspberry Pi, you need a SD card with only these files, available in the deploy dir:

  • pieeprom.bin
  • pieeprom.sig
  • recovery.bin

On your PC from the build directory:

  • mount the first vfat partition of your SD card to path/to/SD
  • erase all files
    rm path/to/SD
    
  • copy the files
    DEPLOYDIR=tmp/deploy/images/$MACHINE
    cp $DEPLOYDIR/pieeprom.bin \
        $DEPLOYDIR/pieeprom.sig \
        $DEPLOYDIR/recovery.bin \
        path/to/SD
    

Then on the Raspberry Pi:

  • insert this SD card
  • power on
  • wait either for the green LED to blink rapidly or the screen to fill in green (if you have a HDMI-connected screen) to confirm the BL2 update

Fusing your Products

Offline signing of BL2 and boot image

In order to sign BL2 and boot image, you need two Raspberry scripts in your PATH: rpi-eeprom-config, rpi-eeprom-digest. These scripts are accessible in this Github repo.

git clone https://github.com/raspberrypi/rpi-eeprom.git
PATH=$PATH:$PWD/rpi-eeprom

BL2 signing

DEPLOYDIR=tmp/deploy/images/$MACHINE
welma-signing-tools/raspberrypi4/rpi-sign bl2 $DEPLOYDIR/pieeprom.bin \
    path/to/public.pem \
    path/to/private.pem

Boot image signing

DEPLOYDIR=tmp/deploy/images/$MACHINE
welma-signing-tools/raspberrypi4/rpi-sign bootimg $DEPLOYDIR/boot.img \
    path/to/private.pem

Burning the eFuses

  1. Prerequisites
  2. Erase the EEPROM (Raspberry Pi 4B/400 only)
  3. Define the RPIBOOT GPIO (Raspberry Pi 4B/400 only)
  4. Write the PBKH

Prerequisites

OTP provisioning needs the RPIBOOT utility, which let you boot the board using a USB connection. You can clone it using the repo usbboot.

To create the rpiboot binary, run:

git clone https://github.com/raspberrypi/usbboot.git
cd usbboot
git submodule update --init
make

Create a directory to work with and copy all the useful files

mkdir work
cp firmware/2711/recovery.bin \
    secure-boot-recovery/bootcode4.bin \
    secure-boot-recovery/config.txt work

Add pieeprom.bin and pieeprom.sig from the Yocto deploy directory

Erase the EEPROM

In order to avoid the RPIBOOT OTP being accidentally set on Pi 4B/400 this option can only be set via RPIBOOT. To force RPIBOOT on a Pi 4B/400, we need to erase the SPI EEPROM using a SD card.

  • go in your work directory
    cd work
    
  • mount the first vfat partition of your SD card to path/to/SD
  • erase all files
    rm path/to/SD
    
  • add erase_eeprom=1 to config.txt
  • copy recovery.bin and config.txt
    cp recovery.bin config.txt path/to/SD
    

Then on the Raspberry Pi:

  • insert this SD card
  • power on
  • wait either for the green LED to blink rapidly or the screen to fill in green (if you have a HDMI-connected screen) to confirm the erasing.

Now you can use RPIBOOT once to program the GPIO to use for future RPIBOOT.

Define the RPIBOOT GPIO

Warning

These commands are writing to One-Time Programmable (OTP) eFuses. Be absolutely certain that you want to write to the OTP before running these commands. Once written, the data cannot be changed or erased.

Raspberry recommends to choose GPIO 8.

  • go in your work directory
    cd work
    
  • edit config.txt to program the GPIO, you can comment the other lines
    program_rpiboot_gpio=8
    
  • start rpiboot
    ../rpiboot -d . -v
    
  • connect a cable between the USB-C power supply port from the board to a USB from your PC. You can see the logs in UART:
      5.43 Read config.txt bytes     1868 hnd 0x0
      5.45 Updating OTP to use GPIO8 to enable USB-device boot (rpiboot)
      5.35 pieeprom.sig
      5.35 hash: 054e271515554d4328691f29c41cf76967f7fd05c8ade25304c81b5f2cfce56a
      5.36 ts: 1754990568
      5.63 Reading EEPROM: 524288 bytes 0xc0b60000
      6.96 630ms
      6.42 Writing EEPROM
    ********************************************************************************************************************************  7.78
      7.81 1438ms
    
      7.81 Verify BOOT EEPROM
      7.82 Reading EEPROM: 524288 bytes 0xc0b60000
      8.32 645ms
      8.86 BOOT-EEPROM: UPDATED
      8.59 USB-OTG disconnect
      8.90 RECOVERY: COMPLETE: REBOOT 0
    

Now, if you put a jumper like on the picture below, your board will boot on RPIBOOT instead of the SD card:

image rpiboot on rpi4b

Here we use GPIO 8 connected to the ground with the white jumper and GPIO 14, 15 and ground to read serial.

Write the PBKH

Warning

These commands are writing to One-Time Programmable (OTP) eFuses. Be absolutely certain that you want to write to the OTP before running these commands. Once written, the data cannot be changed or erased.

  • go in your work directory
    cd work
    
  • edit config.txt to program the OTP, you can comment the other lines
    program_pubkey=1
    
  • connect the GPIO to the ground using a jumper
  • start rpiboot
    ../rpiboot -d . -v
    
  • connect a cable between the USB-C power supply port from the board to a USB from your PC. You can see the logs in UART:
      5.17 Read config.txt bytes     1867 hnd 0x0
      5.22 pieeprom.sig
      5.22 hash: 054e271515554d4328691f29c41cf76967f7fd05c8ade25304c81b5f2cfce56a
      5.22 ts: 1754990568
      5.30 Reading EEPROM: 524288 bytes 0xc0b60000
      6.63 630ms
      6.16 Bootloader EEPROM is up to date
      6.21 secure_boot_provision program_pubkey 1
      6.22 bootconf.sig
      6.22 hash: d7c7f93ddb4805ddd847c358e4e4770c68a2e5dcd0448f2352128b8cf4b58957
      6.22 rsa2048: 8e86e0ac94afa6c03bdb61c718ba6b0d4d0858e9f14ea890873f4621320e391df4e43f51e10a7cfa1ecc184d111a013a1f41fa52874fdf3c65d9295c3e3ad9450e4ffcc3449dadd6d09ecb699a15bc6224c31c69924e7601c3e38f8ba9b2c015900328361d95eb305285c561c1751a72ae70e3f2da27639f41a571e6aa78bbd4e14e5264292b70d71fd82e49be72579226ca1ced9e2eb0e79653c071a3de5f22c22171186e0c9c543974e98608b59d99b7602699fa0a122629f1092d65407238b30505eb90f21708fef188451647ab9855664346e3ec6fc2c64f6ae9c20bc835d58f6f756c17ce9e10d0edafd804ebd950d2cddfaa6c58c32a55e4eac9841c93
      6.27 RSA verify
      6.10 rsa-verify pass (0x0)
      6.10 Updating OTP to use GPIO8 to enable USB-device boot (rpiboot)
      6.31 Public key hash b6038838aedb25f9ecf268e94b3226f578b52a579cb839a2a0ac1badafda0298
      6.32 OTP-WR: boot-mode 000048b0
      6.32 OTP-WR: boot-mode 000048b0
      6.33 OTP-WR: flags 00000080
      6.33 Write OTP key
      6.36 OTP updated for key b6038838aedb25f9ecf268e94b3226f578b52a579cb839a2a0ac1badafda0298
      6.36 USB-OTG disconnect
      6.68 RECOVERY: COMPLETE: REBOOT 0
    

Secure boot is now enabled on your Raspberry Pi! To update the BL2, you must now use RPIBOOT and it will only boot if the configuration file is signed with your CUSTPVK.

Test cases

The following test cases are designed to verify the secure boot process. The main objective is to ensure that there are no authentication error in BL2 or boot image and that it doesn't boot if one of them is corrupted.

BL2 and boot image signed with matching keys

When BL2 and boot image are signed with the keys corresponding to the PBKH fused, a notice message is displayed:

  1.41 OTP boardrev b03114 bootrom 48b0 48b0
  1.41 Customer key hash b6038838aedb25f9ecf268e94b3226f578b52a579cb839a2a0ac1badafda0298
  1.41 VC-JTAG unlocked
  1.45 bootconf.sig
  1.45 hash: d7c7f93ddb4805ddd847c358e4e4770c68a2e5dcd0448f2352128b8cf4b58957
  1.45 rsa2048: 8e86e0ac94afa6c03bdb61c718ba6b0d4d0858e9f14ea890873f4621320e391df4e43f51e10a7cfa1ecc184d111a013a1f41fa52874fdf3c65d9295c3e3ad9450e4ffcc3449dadd6d09ecb699a15bc6224c31c69924e7601c3e38f8ba9b2c015900328361d95eb305285c561c1751a72ae70e3f2da27639f41a571e6aa78bbd4e14e5264292b70d71fd82e49be72579226ca1ced9e2eb0e79653c071a3de5f22c22171186e0c9c543974e98608b59d99b7602699fa0a122629f1092d65407238b30505eb90f21708fef188451647ab9855664346e3ec6fc2c64f6ae9c20bc835d58f6f756c17ce9e10d0edafd804ebd950d2cddfaa6c58c32a55e4eac9841c93
  1.50 RSA verify
  1.20 rsa-verify pass (0x0)
  .
  .
  .
  2.83 secure-boot
  2.85 Loading boot.img ...
  2.38 boot.sig
  2.38 hash: 159da5e8db9e7b64c80d9058a644231e49133f3cad62a0d1b1d9ceabbb382173
  2.39 ts: 1302044400
  2.39 rsa2048: 5c3b8b1d13d68598d8a36aefcfc901e1d558d960811bf211758090cea340c66ee7d96e63c198fb700ce726c3f35ec96467870b161ab1ed098d279a830adb4ee3056051e068f2bba6f0e0dce9897910b19da8bfa0d3feca5fcbf55bd022bcc1631740263f0d014600eea60b29abb94c8fa10e2369b3a02502f7325f202f83d49aa64f57d3391398214d5256e36abbe1edaaf2b93b569e2191951b0b374d30a76cca849fe84672b92f068da2aa3ecf844f44530087f50545bd6d07d9de571bbd23ce77f9ff20eeb5c4d57e46215c421351182c824c531ccdf813783e096c558251b1e2053fc162f2e2d9d2643aaff4dc161f76083eaffee9a87cc49dfe45ff008e
  3.13 Verifying
  6.27 RSA verify
  6.83 rsa-verify pass (0x0)

CUSTPBK mismatch (BL2)

If an installed BL2 doesn't contain the right public key according to the PBKH in the OTP:

  1.41 OTP boardrev b03114 bootrom 48b0 48b0
  1.41 Customer key hash b6038838aedb25f9ecf268e94b3226f578b52a579cb839a2a0ac1badafda0298
  1.41 VC-JTAG unlocked
  1.50 EEPROM RSA key mismatch b6038838aedb25f9ecf268e94b3226f578b52a579cb839a2a0ac1badafda0298 5a7a19896b5833df1ea6a4041500477ccffb063cb38cc0ab5e382d77bd1f2dec
  1.46 Customer public key not loaded.
  1.64 Failed to validate bootconf.txt
  1.46 USB-OTG disconnect
  1.70 BOOT ERROR: code 24 - 'File signature or hash mismatch'

boot.conf authentication error

  1.41 OTP boardrev b03114 bootrom 48b0 48b0
  1.41 Customer key hash b6038838aedb25f9ecf268e94b3226f578b52a579cb839a2a0ac1badafda0298
  1.41 VC-JTAG unlocked
  1.45 bootconf.sig
  1.45 hash: 4c57c85f53f17d63d829b34192f049c2a96bb12a7f11a03d04aa58913c3f9ba1
  1.45 rsa2048: 456ac20af13454c2b6c2e5fed37fdaf5886fc35cd54e83873a20335114b99688cc3e2a09ff4d0457cb4376e76149548ee44d65b4678e45356c8eab1abea6257b5f9dd19a6ed593b9ffcff74093873cb6ca4203ca7422df183632826b201f6d1d9b7f13d3f4f40ba93cd09a2fb7d47097b298eb73e86f855e8d3629ad5972b5420ddb7cf9b0e5e2296cd25431c940ab7e134193779380f2660dc09716852e33a0989b8382301e8f950f1426f3ab4272cbdcda376cea5846fed7183fa58f5971ef5dc3ab5031095aa607ad76660c969651de38906335f0d3423dcfe0c19601a3ab1fe807d78a9a439bc515c1aa9bb7699a411c91641103e8391faa505c655027c4
  1.04 bootconf.txt mismatch
  1.06 bootconf.txt hash mismatch b503f8ad7f8aea93a272a5ba5248cc5222d0c55af28a4345d0a496bdba9d16bf
  1.14 Failed to validate bootconf.txt
  1.51 USB-OTG disconnect
  1.20 BOOT ERROR: code 24 - 'File signature or hash mismatch'

Bad signature of boot.img (BL3)

  2.18 secure-boot
  2.20 Loading boot.img ...
  2.32 boot.sig
  2.32 hash: 159da5e8db9e7b64c80d9058a644231e49133f3cad62a0d1b1d9ceabbb382173
  2.33 ts: 1755089692
  2.33 rsa2048: 6f31796bfe93cb3807cb26fe5faca40e26f9bed7b465625fba8013f48fe9de04046509c1a612772d7065bd3d6ddfa048702cd0207c2cd31d582e09a3f6af0b1c5f3dd2da8f7d23794e26ac46a12bf27d2ef4e05f3c16267f8460e6bfede7bd5161e81268489d78c5777a232fd358197d46fbba0d44948972fab2e1da4b740520a55657b6225c90febb8d47e85578fe470cd7622ba01caebeb6538b2650715692cadbcadbdcdfe31aa2fb9ec9a796f90454ec9276a984f84cf33352eb233554d67f8435552a28c3373fc9feb3b6937a9f07133029f06f8900a2b65630be8a382a35183196e4c912872c3dce4985979bc599f6f6f28347b18d84434ac7f4abfc89
  3.47 Verifying
  6.10 RSA verify
  6.13 rsa-verify fail (0x4380)
  6.13 RSA signature not verified
  6.31 Bad signature boot.img
  6.62 Error 12 loading boot.img