Skip to content

Factory lockdown sequencing: SECBOOTADD0/SWAP_BANK before BOOT_LOCK, and a BOOT_LOCK=0 bench profile before DFU dies #753

Description

@Nicola-Ceornea

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:

  1. Decide whether shipping units get BOOT_LOCK at the factory, and if so at exactly which step relative to SECBOOTADD0/SWAP_BANK/RDP-2.
  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.
  3. 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).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions