From 9d05be4d327c687c8f10d1a63f0e38653d8bb8f2 Mon Sep 17 00:00:00 2001 From: pstruebi Date: Wed, 4 Mar 2026 17:43:11 +0100 Subject: [PATCH] secure boot working --- AGENTS.md | 32 ++++++++++++++++++++++++++++---- board/beacon-cm4/genbootfs.cfg | 4 ++-- board/beacon-cm4/genouterfs.cfg | 12 ++++++++++++ board/beacon-cm4/post-image.sh | 28 +++++++++++++++++++++++++++- 4 files changed, 69 insertions(+), 7 deletions(-) create mode 100644 board/beacon-cm4/genouterfs.cfg diff --git a/AGENTS.md b/AGENTS.md index c1cdbb2..a41ad46 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -17,7 +17,10 @@ make -C rpi-buildroot-fork O=$(pwd)/output BR2_EXTERNAL=$(pwd)/beacon-buildroot ## SSH / find IP ```bash +# Non-secure-boot CM4 (MAC e4:5f:01:e9:13:96): CM4=$(ip neigh show dev enp0s31f6 | awk '/e4:5f:01:e9:13:96/{print $1}') +# Secure-boot CM4 (MAC 2c:cf:67:fd:93:1a): +CM4=$(ip neigh show dev enp0s31f6 | awk '/2c:cf:67:fd:93:1a/{print $1}') sshpass -p beacon ssh user@$CM4 # login: user / beacon ``` @@ -27,9 +30,11 @@ sshpass -p beacon ssh user@$CM4 # login: user / beacon sshpass -p beacon ssh user@$CM4 'sudo tee /upload/rootfs.raucb >/dev/null' \ < output/images/rootfs.raucb # install + reboot: -sshpass -p beacon ssh user@$CM4 'rauc install /upload/rootfs.raucb && sudo reboot' -# after reboot — find new IP, then: -sshpass -p beacon ssh user@$CM4 'rauc status mark-good && rauc status' +sshpass -p beacon ssh -tt user@$CM4 'rauc install /upload/rootfs.raucb && sudo reboot' +# after reboot — find new IP, then mark-good (REQUIRED on every new boot to confirm slot): +sshpass -p beacon ssh -tt user@$CM4 'rauc status mark-good && rauc status' +# NOTE: rauc commands need -tt (PTY) on Dropbear SSH or output is silently dropped +# NOTE: mark-good MUST be called after each OTA reboot — without it RAUC falls back to previous slot ``` ## UART @@ -41,7 +46,26 @@ socat -u /dev/ttyUSB1,b115200,rawer,crnl OPEN:/tmp/uart.log,creat,trunc & # hea ## Rescue Short GPIO4 (pin 7) → GND (pin 9) during power-on → boots `/dev/mmcblk0p2`. -## Secure Boot (Milestone 2) +## Secure Boot — Unlock as MSD +```bash +# Sign the MSD boot image with private.pem (once, or after rpi-eeprom submodule init): +cd usbboot/secure-boot-msd +../tools/rpi-eeprom-digest -i boot.img -o boot.sig -k ../../private.pem +# Expose eMMC as USB mass storage (user must bridge EMMC_DISABLE jumper first): +sudo ./usbboot/rpiboot -d usbboot/secure-boot-msd +# Flash: +sudo bmaptool copy output/images/sdcard.img.xz /dev/sda +``` + +## UART / Power Cycle +> **The user handles power cycling and UART logging manually.** +> Ask user to: remove EMMC_DISABLE jumper → power-cycle → connect picocom. +```bash +picocom -b 115200 /dev/ttyUSB1 # user runs this to see boot log +``` +Expected secure boot log lines: `secure-boot`, `rsa-verify pass (0x0)`, then U-Boot. + +## Secure Boot — Provision (burn OTP) ```bash update-pieeprom.sh -k private.pem && rpiboot -d secure-boot-recovery ``` diff --git a/board/beacon-cm4/genbootfs.cfg b/board/beacon-cm4/genbootfs.cfg index fcd659f..13f991f 100644 --- a/board/beacon-cm4/genbootfs.cfg +++ b/board/beacon-cm4/genbootfs.cfg @@ -1,4 +1,4 @@ -image boot.vfat { +image boot.img { vfat { files = { "bcm2711-rpi-cm4.dtb", @@ -12,6 +12,6 @@ image boot.vfat { } } - size = 256M + size = 64M } diff --git a/board/beacon-cm4/genouterfs.cfg b/board/beacon-cm4/genouterfs.cfg new file mode 100644 index 0000000..7a022d0 --- /dev/null +++ b/board/beacon-cm4/genouterfs.cfg @@ -0,0 +1,12 @@ +image boot.vfat { + vfat { + files = { + "config.txt", + "boot.img", + "boot.sig", + "boot.scr" + } + } + + size = 256M +} diff --git a/board/beacon-cm4/post-image.sh b/board/beacon-cm4/post-image.sh index 1020e78..5ea9ce5 100755 --- a/board/beacon-cm4/post-image.sh +++ b/board/beacon-cm4/post-image.sh @@ -7,6 +7,9 @@ BOARD_NAME="$(basename ${BOARD_DIR})" GENIMAGE_CFG="${BOARD_DIR}/genimage.cfg" GENIMAGE_TMP="${BUILD_DIR}/genimage.tmp" GENBOOTFS_CFG="${BOARD_DIR}/genbootfs.cfg" +GENOUTERFS_CFG="${BOARD_DIR}/genouterfs.cfg" +PRIVATE_KEY="${BR2_EXTERNAL_BEACON_PATH}/../private.pem" +EEPROM_DIGEST="${BR2_EXTERNAL_BEACON_PATH}/../usbboot/tools/rpi-eeprom-digest" RAUC_COMPATIBLE="${2:-beacon-cm4}" # Pass VERSION as an environment variable (eg: export from a top-level Makefile) @@ -23,7 +26,7 @@ ROOTPATH_TMP="$(mktemp -d)" rm -rf "${GENIMAGE_TMP}" -# Generate the boot filesystem image +# Generate the inner boot filesystem image (boot.img) genimage \ --rootpath "${ROOTPATH_TMP}" \ @@ -32,6 +35,29 @@ genimage \ --outputpath "${BINARIES_DIR}" \ --config "${GENBOOTFS_CFG}" +# Sign boot.img for secure boot (SIGNED_BOOT=1 EEPROM) +if [ -f "${PRIVATE_KEY}" ] && [ -f "${EEPROM_DIGEST}" ]; then + echo "==> Signing boot.img with ${PRIVATE_KEY}" + "${EEPROM_DIGEST}" -i "${BINARIES_DIR}/boot.img" -o "${BINARIES_DIR}/boot.sig" -k "${PRIVATE_KEY}" +else + echo "WARNING: private.pem or rpi-eeprom-digest not found — boot.img unsigned (will not boot on secure-boot locked CM4)" + sha256sum "${BINARIES_DIR}/boot.img" | awk '{print $1}' > "${BINARIES_DIR}/boot.sig" +fi + +# Create outer boot.vfat: config.txt (boot_ramdisk=1) + boot.img + boot.sig +cat > "${BINARIES_DIR}/config.txt" << 'OUTER_CONFIG' +boot_ramdisk=1 +uart_2ndstage=1 +OUTER_CONFIG + +rm -rf "${GENIMAGE_TMP}" +genimage \ + --rootpath "${ROOTPATH_TMP}" \ + --tmppath "${GENIMAGE_TMP}" \ + --inputpath "${BINARIES_DIR}" \ + --outputpath "${BINARIES_DIR}" \ + --config "${GENOUTERFS_CFG}" + # Generate a RAUC update bundle for the full system (bootfs + rootfs) [ -e ${BINARIES_DIR}/update.raucb ] && rm -rf ${BINARIES_DIR}/update.raucb [ -e ${BINARIES_DIR}/temp-update ] && rm -rf ${BINARIES_DIR}/temp-update