0x0026a Custom AES-128-CMAC Secure Bootloader
This project builds a custom secure-boot chain for the Pico 2 (RP2350) that sits entirely above the ROM bootloader. A first-stage bootloader in XIP flash authenticates a signed application with AES-128-CMAC (RFC 4493) before jumping to it, and the signed application decrypts and prints a secret banner using the SDK Mbed TLS AES API.
What You'll Learn
- Why a bootloader-only CRC/manifest is insufficient and what a MAC adds
- How AES-128-CMAC works (K1/K2 subkeys) and the RFC 4493 test vectors
- Custom linker-script editing (
pico_flash_region.ld,memmap_app.ld) to relocate the app - Flashing three images (bootloader, manifest, app) with OpenOCD
- Reverse engineering both images with GDB and Ghidra (find the key, IV, ciphertext, banner)
See the full tutorial: WEEK11a.md / WEEK11a.pdf
Flash Map
| Region | Address | Content |
|---|---|---|
| Bootloader | 0x10000000 |
0x0026a bootloader (27772 B) |
| Manifest | 0x1001F000 |
header + AES-128-CMAC tag |
| App | 0x10020000 |
0x0026a signed app (21656 B) |
The CMSIS-RM9 flash-safe range starts at 0x10000000 on the RP2350, so adding 2 MB relocates the app to 0x10020000.
Artifacts
| File | Description |
|---|---|
0x0026a_bootloader.bin |
Bootloader image (flash at 0x10000000) |
0x0026a_bootloader.uf2 |
Bootloader for the BOOTSEL drag-and-drop |
0x0026a_app.bin |
Signed app image (flash at 0x10020000) |
manifest.bin |
Manifest (flash at 0x1001F000) |
WEEK11a.md / WEEK11a.pdf |
Full lab notebook |
Build
cmake -B build -DPICO_SDK_PATH=~/.pico-sdk/sdk/2.2.0
cmake --build build
python3 tools/sign_firmware.py build/0x0026a_app.bin --out manifest.bin --key "IronNetBootKey!!" --app-base 0x10020000
This produces 0x0026a_bootloader.bin/.uf2 and 0x0026a_app.bin; the signer writes manifest.bin.
Flash
openocd -f interface/picoprobe.cfg -f target/rp2350.cfg -c \
"program 0x0026a_bootloader.bin 0x10000000 verify; \
program manifest.bin 0x1001F000 verify; \
program 0x0026a_app.bin 0x10020000 verify; reset run; shutdown"
Verify at Runtime
Halt the core after boot and read the program counter. A valid signed image leaves PC inside the app (0x100201xx); a tampered or unsigned image leaves PC in the bootloader boot_halt idle loop near 0x10000eb2.
Disclaimers
This is an educational project for the Embedded-Hacking course. The key IronNetBootKey!! ships in the repo and is intentionally embedded in both images so it can be recovered with GDB/Ghidra. Do not use this scheme to protect real products.