bootloader: reject DFU images longer than signed firmware_length
What changed, and why it matters
This fix closes a serious bug in the COLDCARD Mk4 and Q1 bootloader. Previously, when installing a firmware update from a microSD card in recovery mode, the bootloader verified only the portion of the file that the firmware header said was signed. Any extra bytes appended after that signed portion were still written to the device's flash memory, even though they were not signed. An attacker who could get a victim to install a legitimate-looking signed firmware file with malicious data tacked onto the end could overwrite parts of the device's internal storage without needing COLDCARD's signing key. The patch now rejects any update whose total length does not exactly match the signed length, and adds a hard upper-size limit as a backup safeguard.
Treat this as a security fix and ship it promptly. Users should upgrade their bootloader/firmware through normal signed channels. Avoid installing firmware images from untrusted sources or recovery-mode SD cards whose provenance is uncertain. Consider issuing a security advisory noting that recovery-mode SD upgrades of already-installed images could have been abused before this fix.
Security signals we found
Bypass of cryptographic signature verification for appended data
Arbitrary unsigned flash write during firmware upgrade
Potential overwrite of internal flash filesystem
Fail-closed length validation added
Defense-in-depth upper bound added
Evidence from the diff
In verify_firmware_in_ram(), the bootloader authenticated hdr->firmware_length bytes but did not compare that value to the actual DFU element length passed in. The untrusted length was then forwarded to psram_do_upgrade(), which flashed size bytes. Because FW_MAX_LENGTH_MK4 extends to the top of flash and covers the internal /flash filesystem, an attacker could append unsigned data (up to the maximum) to a valid signed firmware image and have it written to arbitrary flash regions during a recovery-mode SD upgrade of the currently installed image. The patch adds an exact-length check (len == hdr->firmware_length) with fail-closed behavior, plus an ASSERT(size <= FW_MAX_LENGTH_MK4) defense-in-depth check in psram_do_upgrade().
Changed components
stm32/mk4-bootloader/verify.cstm32/mk4-bootloader/psram.cCOLDCARD Mk4 bootloaderCOLDCARD Q1 bootloaderInspect captured patch +5 / −0
### stm32/mk4-bootloader/psram.c
@@ -308,6 +308,7 @@ psram_recover_firmware(void)
psram_do_upgrade(const uint8_t *start, uint32_t size)
{
ASSERT(size >= FW_MIN_LENGTH);
+ ASSERT(size <= FW_MAX_LENGTH_MK4);
// In case of reset/crash, we can recover, so save
// what we need for that -- yes, we will re-verify signatures
### stm32/mk4-bootloader/verify.c
@@ -253,6 +253,10 @@ verify_firmware_in_ram(const uint8_t *start, uint32_t len, uint8_t world_check[3
// check basics like verison, hw compat, etc
if(!verify_header(hdr)) goto fail;
+ // Length of data to be flashed must equal the signed length exactly:
+ // anything more is unsigned, attacker-controlled bytes (fail closed).
+ if(len != hdr->firmware_length) goto fail;
+
if(check_is_downgrade(hdr->timestamp, (const char *)hdr->version_string)) {
puts("downgrade");
goto fail;Why this scored 81/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.