diff options
| author | Gerhard de Clercq <[email protected]> | 2025-04-15 20:16:09 +0200 |
|---|---|---|
| committer | Gerhard de Clercq <[email protected]> | 2025-05-23 12:40:19 +0200 |
| commit | 68a45490fc1675f2171131ccbf01f690c4123f01 (patch) | |
| tree | 42606d9fa51bf50e6d7d84623123616600a70cce /examples/boot/bootloader | |
| parent | f7405493c184ce453ac3f7ba97f7f2689f978194 (diff) | |
[embassy-usb-dfu] support ed25519 verification
This commit adds the ability to verify that USB DFU updates are correctly signed using ed25519.
This required adding support to embassy-boot for reading from the DFU partition.
Diffstat (limited to 'examples/boot/bootloader')
| -rw-r--r-- | examples/boot/bootloader/stm32wb-dfu/Cargo.toml | 1 | ||||
| -rw-r--r-- | examples/boot/bootloader/stm32wb-dfu/README.md | 26 | ||||
| -rw-r--r-- | examples/boot/bootloader/stm32wb-dfu/memory.x | 8 | ||||
| -rw-r--r-- | examples/boot/bootloader/stm32wb-dfu/secrets/key.pub.short | 1 | ||||
| -rw-r--r-- | examples/boot/bootloader/stm32wb-dfu/src/main.rs | 12 |
5 files changed, 44 insertions, 4 deletions
diff --git a/examples/boot/bootloader/stm32wb-dfu/Cargo.toml b/examples/boot/bootloader/stm32wb-dfu/Cargo.toml index 738afb6ec..0bb93b12e 100644 --- a/examples/boot/bootloader/stm32wb-dfu/Cargo.toml +++ b/examples/boot/bootloader/stm32wb-dfu/Cargo.toml | |||
| @@ -30,6 +30,7 @@ defmt = [ | |||
| 30 | "embassy-usb/defmt", | 30 | "embassy-usb/defmt", |
| 31 | "embassy-usb-dfu/defmt" | 31 | "embassy-usb-dfu/defmt" |
| 32 | ] | 32 | ] |
| 33 | verify = ["embassy-usb-dfu/ed25519-salty"] | ||
| 33 | 34 | ||
| 34 | [profile.dev] | 35 | [profile.dev] |
| 35 | debug = 2 | 36 | debug = 2 |
diff --git a/examples/boot/bootloader/stm32wb-dfu/README.md b/examples/boot/bootloader/stm32wb-dfu/README.md index 3c5f268a0..99a7002c4 100644 --- a/examples/boot/bootloader/stm32wb-dfu/README.md +++ b/examples/boot/bootloader/stm32wb-dfu/README.md | |||
| @@ -28,6 +28,32 @@ cargo objcopy --release -- -O binary fw.bin | |||
| 28 | dfu-util -d c0de:cafe -w -D fw.bin | 28 | dfu-util -d c0de:cafe -w -D fw.bin |
| 29 | ``` | 29 | ``` |
| 30 | 30 | ||
| 31 | ### 3. Sign Updates Before Flashing (Optional) | ||
| 32 | |||
| 33 | Currently, embassy-usb-dfu only supports a limited implementation of the generic support for ed25519-based update verfication in embassy-boot. This implementation assumes that a signature is simply concatenated to the end of an update binary. For more details, please see https://embassy.dev/book/#_verification and/or refer to the documentation for embassy-boot-dfu. | ||
| 34 | |||
| 35 | To sign (and then verify) application updates, you will first need to generate a key pair: | ||
| 36 | |||
| 37 | ``` | ||
| 38 | signify-openbsd -G -n -p secrets/key.pub -s secrets/key.sec | ||
| 39 | tail -n1 secrets/key.pub | base64 -d -i - | dd ibs=10 skip=1 > secrets/key.pub.short | ||
| 40 | ``` | ||
| 41 | |||
| 42 | Then you will need to sign all you binaries with the private key: | ||
| 43 | |||
| 44 | ``` | ||
| 45 | cargo objcopy --release -- -O binary fw.bin | ||
| 46 | shasum -a 512 -b fw.bin | head -c128 | xxd -p -r > target/fw-hash.txt | ||
| 47 | signify-openbsd -S -s secrets/key.sec -m target/fw-hash.txt -x target/fw-hash.sig | ||
| 48 | cp fw.bin fw-signed.bin | ||
| 49 | tail -n1 target/fw-hash.sig | base64 -d -i - | dd ibs=10 skip=1 >> fw-signed.bin | ||
| 50 | dfu-util -d c0de:cafe -w -D fw-signed.bin | ||
| 51 | ``` | ||
| 52 | |||
| 53 | Finally, as shown in this example with the `verify` feature flag enabled, you then need to embed the public key into your bootloader so that it can verify update signatures. | ||
| 54 | |||
| 55 | N.B. Please note that the exact steps above are NOT a good example of how to manage your keys securely. In a production environment, you should take great care to ensure that (at least the private key) is protected and not leaked into your version control system. | ||
| 56 | |||
| 31 | ## Troubleshooting | 57 | ## Troubleshooting |
| 32 | 58 | ||
| 33 | - Make sure your device is in DFU mode before flashing | 59 | - Make sure your device is in DFU mode before flashing |
diff --git a/examples/boot/bootloader/stm32wb-dfu/memory.x b/examples/boot/bootloader/stm32wb-dfu/memory.x index 858062631..77c4d2ee2 100644 --- a/examples/boot/bootloader/stm32wb-dfu/memory.x +++ b/examples/boot/bootloader/stm32wb-dfu/memory.x | |||
| @@ -1,10 +1,10 @@ | |||
| 1 | MEMORY | 1 | MEMORY |
| 2 | { | 2 | { |
| 3 | /* NOTE 1 K = 1 KiBi = 1024 bytes */ | 3 | /* NOTE 1 K = 1 KiBi = 1024 bytes */ |
| 4 | FLASH : ORIGIN = 0x08000000, LENGTH = 24K | 4 | FLASH : ORIGIN = 0x08000000, LENGTH = 48K |
| 5 | BOOTLOADER_STATE : ORIGIN = 0x08006000, LENGTH = 4K | 5 | BOOTLOADER_STATE : ORIGIN = 0x0800C000, LENGTH = 4K |
| 6 | ACTIVE : ORIGIN = 0x08008000, LENGTH = 128K | 6 | ACTIVE : ORIGIN = 0x0800D000, LENGTH = 120K |
| 7 | DFU : ORIGIN = 0x08028000, LENGTH = 132K | 7 | DFU : ORIGIN = 0x0802B000, LENGTH = 120K |
| 8 | RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 16K | 8 | RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 16K |
| 9 | } | 9 | } |
| 10 | 10 | ||
diff --git a/examples/boot/bootloader/stm32wb-dfu/secrets/key.pub.short b/examples/boot/bootloader/stm32wb-dfu/secrets/key.pub.short new file mode 100644 index 000000000..7a4de8585 --- /dev/null +++ b/examples/boot/bootloader/stm32wb-dfu/secrets/key.pub.short | |||
| @@ -0,0 +1 @@ | |||
| gB��p�M�S��z��Kg��!�F���!4�r \ No newline at end of file | |||
diff --git a/examples/boot/bootloader/stm32wb-dfu/src/main.rs b/examples/boot/bootloader/stm32wb-dfu/src/main.rs index 0b643079f..107f243fd 100644 --- a/examples/boot/bootloader/stm32wb-dfu/src/main.rs +++ b/examples/boot/bootloader/stm32wb-dfu/src/main.rs | |||
| @@ -25,6 +25,12 @@ bind_interrupts!(struct Irqs { | |||
| 25 | // N.B. update to a custom GUID for your own device! | 25 | // N.B. update to a custom GUID for your own device! |
| 26 | const DEVICE_INTERFACE_GUIDS: &[&str] = &["{EAA9A5DC-30BA-44BC-9232-606CDC875321}"]; | 26 | const DEVICE_INTERFACE_GUIDS: &[&str] = &["{EAA9A5DC-30BA-44BC-9232-606CDC875321}"]; |
| 27 | 27 | ||
| 28 | // This is a randomly generated example key. | ||
| 29 | // | ||
| 30 | // N.B. Please replace with your own! | ||
| 31 | #[cfg(feature = "verify")] | ||
| 32 | static PUBLIC_SIGNING_KEY: &[u8; 32] = include_bytes!("../secrets/key.pub.short"); | ||
| 33 | |||
| 28 | #[entry] | 34 | #[entry] |
| 29 | fn main() -> ! { | 35 | fn main() -> ! { |
| 30 | let mut config = embassy_stm32::Config::default(); | 36 | let mut config = embassy_stm32::Config::default(); |
| @@ -57,7 +63,13 @@ fn main() -> ! { | |||
| 57 | let mut config_descriptor = [0; 256]; | 63 | let mut config_descriptor = [0; 256]; |
| 58 | let mut bos_descriptor = [0; 256]; | 64 | let mut bos_descriptor = [0; 256]; |
| 59 | let mut control_buf = [0; 4096]; | 65 | let mut control_buf = [0; 4096]; |
| 66 | |||
| 67 | #[cfg(not(feature = "verify"))] | ||
| 60 | let mut state = Control::new(updater, DfuAttributes::CAN_DOWNLOAD, ResetImmediate); | 68 | let mut state = Control::new(updater, DfuAttributes::CAN_DOWNLOAD, ResetImmediate); |
| 69 | |||
| 70 | #[cfg(feature = "verify")] | ||
| 71 | let mut state = Control::new(updater, DfuAttributes::CAN_DOWNLOAD, ResetImmediate, PUBLIC_SIGNING_KEY); | ||
| 72 | |||
| 61 | let mut builder = Builder::new( | 73 | let mut builder = Builder::new( |
| 62 | driver, | 74 | driver, |
| 63 | config, | 75 | config, |
