Split out of the flash-geometry v7 engagement (#752) because it binds the current geometry, not just v7. Record: docs/security/adversarial-review/findings/flash-geometry-v7-2026-09-24.md.
The ordering is mandatory and irreversible
RM0456 §7.4.2: SECBOOTADD0 and SWAP_BANK must be set before BOOT_LOCK. SWD verification comes after. Getting this wrong is permanent per die.
This matters because RDP-2 freezes the option bytes but excepts SWAP_BANK (§7.6.2); only TZEN + BOOT_LOCK closes that hole (§7.4.2). So BOOT_LOCK is what makes the boot address actually immutable — and it has to be last.
What already landed
shared/src/lockdown.rs can now verify all of it (808c42f5, 12b99eec), after round 2 found that nothing proved the intended protection profile before RDP-2 made every omission permanent:
| was missing |
now |
BOOT_LOCK ignored |
boot_lock_set() + ShipProfile::require_boot_lock + ObField::BootLock |
| WRP accepted coverage ending at page 3, not 4 |
wrp_covers_fsbl_bits() + FSBL_LAST_PAGE_{LEGACY,FROZEN} |
| no WRP2 register passed at all |
wrp2ar parameter + ObField::Wrp2a + flash::wrp2ar_raw() (0x68, §7.9.23) |
SWAP_BANK ignored |
OPTR_SWAP_BANK (bit 20) + swap_bank_clear() + ObField::SwapBank |
require_boot_lock is false in both shipped profiles, deliberately. BOOT_LOCK is now representable and checkable, not required — because requiring it decides the question below, which has not been decided.
The decision this issue is for
A factory BOOT_LOCK ends the sealed-EVT ROM-DFU route. tools/flash-evt-dfu.sh is currently how an enclosed unit gets firmware (BOOT0 via the SBU bridge). Once BOOT_LOCK is set, that path is gone for that die, forever.
Needed:
- Decide whether shipping units get
BOOT_LOCK at the factory, and if so at exactly which step relative to SECBOOTADD0/SWAP_BANK/RDP-2.
- A separate
BOOT_LOCK=0 bench profile so bench and EVT units keep the DFU route, with a compile/CI fence that stops it reaching a shipping image.
- State the DFU cutoff in the factory runbook — the point after which a unit can only be updated through
CMD_FW_*.
Related: #696 (with BOOT0 strapped + RDP-2, CMD_FW_* is the only field-update path — prove it on silicon), #695 (EVT DFU flashing), #707 (BHK-rooted SE050 is unrecoverable after the mass erase a DFU reflash performs).
Split out of the flash-geometry v7 engagement (#752) because it binds the current geometry, not just v7. Record:
docs/security/adversarial-review/findings/flash-geometry-v7-2026-09-24.md.The ordering is mandatory and irreversible
RM0456 §7.4.2:
SECBOOTADD0andSWAP_BANKmust be set beforeBOOT_LOCK. SWD verification comes after. Getting this wrong is permanent per die.This matters because RDP-2 freezes the option bytes but excepts
SWAP_BANK(§7.6.2); only TZEN +BOOT_LOCKcloses that hole (§7.4.2). SoBOOT_LOCKis what makes the boot address actually immutable — and it has to be last.What already landed
shared/src/lockdown.rscan now verify all of it (808c42f5,12b99eec), after round 2 found that nothing proved the intended protection profile before RDP-2 made every omission permanent:BOOT_LOCKignoredboot_lock_set()+ShipProfile::require_boot_lock+ObField::BootLockwrp_covers_fsbl_bits()+FSBL_LAST_PAGE_{LEGACY,FROZEN}wrp2arparameter +ObField::Wrp2a+flash::wrp2ar_raw()(0x68, §7.9.23)SWAP_BANKignoredOPTR_SWAP_BANK(bit 20) +swap_bank_clear()+ObField::SwapBankrequire_boot_lockisfalsein both shipped profiles, deliberately. BOOT_LOCK is now representable and checkable, not required — because requiring it decides the question below, which has not been decided.The decision this issue is for
A factory
BOOT_LOCKends the sealed-EVT ROM-DFU route.tools/flash-evt-dfu.shis currently how an enclosed unit gets firmware (BOOT0 via the SBU bridge). OnceBOOT_LOCKis set, that path is gone for that die, forever.Needed:
BOOT_LOCKat the factory, and if so at exactly which step relative toSECBOOTADD0/SWAP_BANK/RDP-2.BOOT_LOCK=0bench profile so bench and EVT units keep the DFU route, with a compile/CI fence that stops it reaching a shipping image.CMD_FW_*.Related: #696 (with BOOT0 strapped + RDP-2,
CMD_FW_*is the only field-update path — prove it on silicon), #695 (EVT DFU flashing), #707 (BHK-rooted SE050 is unrecoverable after the mass erase a DFU reflash performs).