feat(tropic01-driver): add the firmware-update bootloader API#12
Merged
Conversation
Wire the last block of the chip command surface, the mutable firmware update. After this the whole command surface is wired. The host is a pure transport. The chip verifies the EdDSA firmware signature with a vendor key burned in its own memory, so the driver relays the signed image byte for byte and adds no crypto dependency. The update primitives live on a new Bootloader type-state, reachable only from NoSession through enter_bootloader, which sends a maintenance-mode Startup_Req, and left through exit_to_application, which reboots into the application firmware. The type-state proves at compile time that an update command cannot run outside maintenance mode. mutable_fw_update sends a Mutable_FW_Update_Req 0xB0 carrying the 104-byte signed header. mutable_fw_update_data sends a Mutable_FW_Update_Data_Req 0xB1 carrying one image chunk. Both validate only the framing length and relay the rest verbatim, since the chip validates the payload. FwImageChunks decodes a signed image into its on-wire chunks. It is a bounded, panic-free, length-prefixed splitter that reads only through the checked parse combinators, fuses on a truncated chunk, and caps the image at the documented maximum. It is exposed to a new libFuzzer target and stays crash free. update_firmware is the one-call orchestrator with parity to libtropic lt_do_mutable_fw_update. It updates both bank pairs with the crucial anti-downgrade reboot between them, never leaving maintenance mode until both pairs are written. It then verifies every bank and the running firmware against the supplied image versions. The bank header version is a little-endian word at a fixed offset of the 52-byte boot-v2 header, the image version is a little-endian word inside the signed chunk-0 header, and the two are compared for exact equality, exactly as the reference SDK does. A wrong installed version reports a distinct FwVersionMismatch, separate from the structural FwUpdateIncomplete that flags a bank that was never written. Validation is weaker than the model-backed command tranches and is documented as such. The official emulator models none of the bootloader, so the request frames are pinned byte-exact as golden frames, the blob decoder is fuzzed, the version checks are driven through match and mismatch cases with a recording chip mock, and the orchestration sequence is asserted command for command. A hardware power-fault and signature-rejection test remains a hard gate before any production firmware update, which the module documents. 407 host tests and 39 model tests pass. clippy is clean on host all targets, all features, the fuzz seam, thumbv8m, and the model integration build, cargo doc is warning free, hermetic coverage holds above the floor, the new firmware-image fuzz target runs crash free, and the five existing targets stay crash free.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Wire the last block of the chip command surface, the mutable firmware update. After this the whole command surface is wired.
The host is a pure transport. The chip verifies the EdDSA firmware signature with a vendor key burned in its own memory, so the driver relays the signed image byte for byte and adds no crypto dependency. The update primitives live on a new Bootloader type-state, reachable only from NoSession through enter_bootloader, which sends a maintenance-mode Startup_Req, and left through exit_to_application, which reboots into the application firmware. The type-state proves at compile time that an update command cannot run outside maintenance mode.
mutable_fw_update sends a Mutable_FW_Update_Req 0xB0 carrying the 104-byte signed header. mutable_fw_update_data sends a Mutable_FW_Update_Data_Req 0xB1 carrying one image chunk. Both validate only the framing length and relay the rest verbatim, since the chip validates the payload. FwImageChunks decodes a signed image into its on-wire chunks. It is a bounded, panic-free, length-prefixed splitter that reads only through the checked parse combinators, fuses on a truncated chunk, and caps the image at the documented maximum. It is exposed to a new libFuzzer target and stays crash free.
update_firmware is the one-call orchestrator with parity to libtropic lt_do_mutable_fw_update. It updates both bank pairs with the crucial anti-downgrade reboot between them, never leaving maintenance mode until both pairs are written. It then verifies every bank and the running firmware against the supplied image versions. The bank header version is a little-endian word at a fixed offset of the 52-byte boot-v2 header, the image version is a little-endian word inside the signed chunk-0 header, and the two are compared for exact equality, exactly as the reference SDK does. A wrong installed version reports a distinct FwVersionMismatch, separate from the structural FwUpdateIncomplete that flags a bank that was never written.
Validation is weaker than the model-backed command tranches and is documented as such. The official emulator models none of the bootloader, so the request frames are pinned byte-exact as golden frames, the blob decoder is fuzzed, the version checks are driven through match and mismatch cases with a recording chip mock, and the orchestration sequence is asserted command for command. A hardware power-fault and signature-rejection test remains a hard gate before any production firmware update, which the module documents.
407 host tests and 39 model tests pass. clippy is clean on host all targets, all features, the fuzz seam, thumbv8m, and the model integration build, cargo doc is warning free, hermetic coverage holds above the floor, the new firmware-image fuzz target runs crash free, and the five existing targets stay crash free.