This lesson has one job: anchor trust in something an attacker cannot rewrite. On NanoSoC that anchor is the boot ROM plus the fused secrets: the ROM code is fixed at manufacture, the device keys live in fuse shadow registers with no bus read path, and every later stage is verified before it runs. If any link runs before verification, the chain is decoration: execution precedes trust, and the attacker only needs the weakest early link.
The chain has four links. The ROM is immutable and implicitly trusted; it is the root. The fused keys authenticate the next stage, so the keys must be present before the first verification and readable only by the verification engine. Each loaded image carries a manifest describing its version and where it may run, and the ROM checks the manifest against policy before jumping. Control passes only after verification succeeds, which means the jump instruction is gated on a pass flag, not merely sequenced after the check. The NanoSoC chain is short, ROM to one SRAM0 image, but the shape generalises: every longer chain repeats verify-then-run per stage. Two things can quietly bend the root. A ROM patch table is mutable state that redirects the root, so its entries must come from an authenticated image or from fuses and be locked once written (see the handoff lesson). And the wake shortcut jumps into the retained SRAM0 image without running any check: the design must say whether retention is trusted (the array stays powered in the always-on domain) or whether the wake path re-verifies before the jump, which adds the verification time to the 14.073 microsecond wake.
Link | What verifies | Key or anchor | Stored in | Handoff rule |
|---|---|---|---|---|
ROM | Itself, by immutability | Manufactured contents | Mask ROM | Starts at the reset vector |
Keys | Loaded by the fuse read-out | Fuse programming | Fuse shadows, engine only | Ready before first verification |
Image manifest | Verified by the ROM | Fused key | Image header in SRAM0 | Checked before the jump |
Application | Verified per its manifest | Manifest policy | SRAM0 image | Runs only on pass flag |
# not-run: trust-chain sizes, NanoSoC teaching values
ROM: 16 KB immutable at 0x0000_0000. Image: 8 KB loaded to SRAM0.
Manifest (illustrative): one 64-byte header per image, covered by the check.
Keys (illustrative allocation, not a recommended key size): 64 bits of device identity in fuse shadows.
Cost of the chain on boot: one verification pass over 8 KB before the jump.
The 12.581 ms boot total includes only the 192 us checksum read, which proves the bytes
arrived. Real authentication adds hashing and signature work that is NOT in that total:
add the verifier's time (a hardware engine's figure is an input, not a NanoSoC number).The trust diagram names each link, its verifier, its key store and the flag that gates handoff.
No link executes before its verification completes; the gate is a hardware flag, not a software convention.
Key storage has no read path except into the verification engine, confirmed by connectivity review.
Tamper with each link in simulation: flip one image bit and confirm the jump never happens; delay the key shadows and confirm verification waits rather than defaulting to pass; force the pass flag and confirm an assertion fires when execution precedes it. A chain that reports failure but jumps anyway is the standard broken implementation.
The gate is convention, not enforcement: a bug or an attack that skips the call still jumps. The pass flag must enable the jump path in hardware so a skipped check cannot proceed.