Intuition What this page is
The parent note parent topic gave you the ideas . This page makes them concrete by grinding through every kind of question these ideas can produce — from "count the bytes" to "the attacker just broke your fuse". By the end, no exam variant should feel new.
Before any calculation, let's list every distinct case-class this topic contains. Each worked example below is tagged with the cell it fills.
#
Case class
What makes it different
Example
A
Fixed-width code size (normal)
plain 4 N byte count
Ex 1
B
Code size — zero / degenerate
N = 0 , or one instruction
Ex 2
C
Address ↔ count inversion
given last address, find N
Ex 3
D
Hash security — birthday bound
collision effort 2 n /2
Ex 4
E
Hash — preimage vs collision (which attack?)
2 n vs 2 n /2 , the trap
Ex 5
F
Signature vs hash — authenticity gap
word problem, attacker swaps both
Ex 6
G
Chain of trust — broken link (limiting/failure case)
one stage fails verify
Ex 7
H
Fuse / OTP — irreversibility edge case
can't un-burn a bit
Ex 8
I
"Open" layers — exam twist
which layer is actually open?
Ex 9
A vector angle problem has four quadrants; this topic has these nine cells. We hit all nine .
Worked example Ex 1 — bytes for a routine
An OpenRISC-style routine has N = 10 fixed-width 32 -bit instructions. How many bytes does it occupy, and what is the address of the first free byte after it?
Forecast: guess the byte count before reading on. (Multiple of 4? Bigger or smaller than 40?)
Each instruction is 32 bits. Why this step? Fixed width is the whole point of RISC — width w = 32 bits, and 1 byte = 8 bits, so each instruction is w /8 = 32/8 = 4 bytes.
Multiply by count. Why this step? N back-to-back instructions with no gaps (load/store design packs them tight): Bytes = 4 N = 4 × 10 = 40 .
First free byte address. Why this step? The routine starts at address 0 and fills bytes 0 … 39 , so the next unused address is 40 = 0x28 .
Verify: the last instruction sits at byte 4 ( N − 1 ) = 36 = 0x24 ; it occupies 0x24 … 0x27 ; next free = 0x28 = 40 . ✔ Units: bytes. ✔
N = 0 and N = 1
What does the formula Bytes = 4 N say for an empty routine, and for a single-instruction routine? Do those answers make physical sense?
Forecast: is "0 bytes" a valid answer? Is "4 bytes" the smallest non-empty program?
Plug N = 0 . Why? Degenerate inputs are where formulas silently lie — always test them. 4 × 0 = 0 bytes. An empty routine really does occupy nothing; the formula is honest.
Plug N = 1 . Why? The smallest non-empty case. 4 × 1 = 4 bytes — one instruction at 0x00 … 0x03 , next free byte 0x04 .
Sanity on P C next . Why? Confirm the "no decode needed" claim holds even at the edge: after the single instruction, P C next = 0 + 4 = 4 . Correct.
Verify: 4 N is linear and passes through the origin, so N = 0 ⇒ 0 and each extra instruction adds exactly 4 . No off-by-one lurks. ✔
Worked example Ex 3 — from last address to instruction count
A disassembly shows the last instruction at address 0x1C . The code starts at 0x00 . How many instructions N are there?
Forecast: 0x1C in decimal is 28 — so is N = 28/4 = 7 ? Careful.
Convert the address. Why? We work in decimal to divide cleanly: 0x1C = 1 × 16 + 12 = 28 .
Address of instruction k (0-indexed) is 4 k . Why this step? Instruction 0 at byte 0 , instruction 1 at byte 4 , ..., instruction k at 4 k . So 4 k = 28 ⇒ k = 7 .
Turn index into count. Why? If the last index is 7 and we started at index 0 , the total number of instructions is N = 7 + 1 = 8 . The off-by-one is the whole trap.
Verify: 8 instructions occupy bytes 0 … 31 ; last one starts at 4 ( 8 − 1 ) = 28 = 0x1C . ✔ Forward and back agree.
Worked example Ex 4 — collision effort for a 128-bit hash
Secure boot uses a hash H producing n = 128 -bit digests. Roughly how many random images must an attacker try before two of them collide (same digest)?
Forecast: is it about 2 128 , or much smaller? Look at the red curve in the figure first.
Name the tool: the birthday bound. Why this tool and not brute force? We're asking "when do any two of my tries match", not "when do I match one fixed target". Among k random n -bit values, the expected first collision appears at k ≈ 1.18 2 n — this is collision resistance , and it's the weakest wall, so an attacker aims here.
Simplify the exponent. Why? 2 n = 2 n /2 , so effort ≈ 2 n /2 . Drop the 1.18 constant — it doesn't change the order of magnitude.
Plug n = 128 . 2 128/2 = 2 64 ≈ 1.8 × 1 0 19 .
Verify: 2 64 = 18 , 446 , 744 , 073 , 709 , 551 , 616 ≈ 1.8 × 1 0 19 . Enormous but far below 2 128 ≈ 3.4 × 1 0 38 — exactly why the birthday bound is the attack of choice, and why we pick hash widths twice the security level we want. ✔
Worked example Ex 5 — which effort applies?
An attacker already has the exact digest m i = H ( I i ) of the legitimate boot image and wants a different image I i ′ with H ( I i ′ ) = m i (so the fused check still passes). For n = 256 , is this 2 128 work or 2 256 work?
Forecast: it's tempting to reuse "2 n /2 = 2 128 " from Ex 4. Is that right here?
Classify the attack. Why this step? The target digest is fixed (it's the real image's hash). Matching a pre-chosen target is a second-preimage attack, not a free-for-all collision. Different question ⟹ different wall.
Effort for a fixed target. Why? With no birthday shortcut, each guess independently hits the target with probability 2 − n , so expected tries ≈ 2 n = 2 256 .
Contrast with Ex 4. Why include this? Collision (2 128 ) is easier than second-preimage (2 256 ) because in a collision the attacker controls both images. A secure boot design that pins the exact expected hash forces the harder 2 256 problem.
Verify: 2 256 ≈ 1.16 × 1 0 77 vs the collision 2 128 ≈ 3.4 × 1 0 38 — the preimage wall is astronomically higher. The trap ("just reuse 2 n /2 ") gives the wrong, far-too-optimistic-for-the-attacker number. ✔
Worked example Ex 6 — why a hash alone loses
A vendor ships firmware and stores m = H ( I ) next to it in normal flash. On boot the chip recomputes H ( I ) and compares to the stored m . An attacker with write access to flash wants to boot their image I ′ . Can they, and what fixes it?
Forecast: does collision-resistance save us here? Guess yes/no before step 1.
Attacker's move. Why this step? If m lives in ordinary rewritable flash, the attacker writes both I ′ and m ′ = H ( I ′ ) . On boot the chip recomputes H ( I ′ ) = m ′ — match! No collision needed at all.
Diagnose the missing property. Why? The hash proves integrity ("the image wasn't corrupted") but not authenticity ("the image came from the vendor"). Integrity ≠ authenticity — that gap is the whole vulnerability.
Apply the fix: a signature. Why this tool? A digital signature σ = Sign s k ( m ) can only be produced with the vendor's private key s k . The chip verifies with the public key p k burned into fuses it cannot rewrite. The attacker has I ′ and can compute m ′ , but cannot produce a valid σ ′ without s k .
Verify: trace it — attacker writes I ′ , m ′ , σ ′ ; chip runs Verify p k ( σ ′ , m ′ ) ; without s k this returns false , boot halts. The forgery is stopped exactly at the layer the hash-only scheme left open. ✔ (This is Kerckhoffs in action: security in the key, not the design.)
Worked example Ex 7 — one stage fails to verify
The chain of trust has stages: ROM → bootloader → OS → app. Suppose the bootloader image was tampered so its signature fails. What runs, and what does not ?
Forecast: does the OS still boot because "the ROM was fine"? Guess before reading.
ROM stage runs. Why? The ROM is the immutable root; it always executes and its job is to measure the next stage (bootloader).
Verification of stage 2 fails. Why this step? Verify p k ( σ boot , H ( I boot )) = false because the tamper changed I boot , so its hash no longer matches the signed value. Look at the figure: the broken link is coloured — everything above it is grey (never reached) .
Chain halts — nothing downstream loads. Why? The core rule is verify-before-execute : control is only handed off on a true. Since stage 2 is rejected, the OS and app are never even loaded , let alone run. A single broken link severs the whole upper chain.
Verify: count what executed = 1 stage (ROM only). What was verified-and-run = 0 later stages. The limiting behaviour ("one failure ⟹ full stop") is the designed safe state — fail closed, not fail open. ✔
Worked example Ex 8 — you can't un-burn a bit
A one-time-programmable (eFuse ) field is 4 bits, all starting at 0 . Manufacturing burns it to 101 1 2 to store a key-version number. Later someone wants version 010 0 2 . Is that possible without replacing the chip ?
Forecast: can you rewrite a fuse from 1 back to 0 ? Guess yes/no.
Model the physical operation. Why this step? An eFuse burn is one-way: it can turn a 0 into a 1 (blow the fuse) but never a 1 back to a 0 . So from any state you can only ever set more bits , never clear them.
Compare bit-by-bit. Why? Current 1011 , target 0100 . Bit 3: 1 → 0 — needs clearing. Impossible. Bit 2: 0 → 1 (OK), bit 1: 1 → 0 (impossible), bit 0: 1 → 0 (impossible).
Conclude. Why? Because at least one bit must go 1 → 0 , the target is unreachable on this chip. Fuse-based version counters exploit exactly this: an attacker can never roll back the stored version to re-enable old, vulnerable firmware.
Verify: reachable states from 1011 are exactly those ≥ 1011 bitwise (every 1 stays a 1 ): 1011 , 1111 . Target 0100 is not in that set, since 0100 AND 1011 = 0000 = 1011 . ✔ The anti-rollback guarantee holds.
Worked example Ex 9 — spot the actually-open layer
A company ships a phone with a RISC-V CPU. They publish the ISA compliance docs but keep the RTL and physical layout secret and licensed. A student claims "so this chip is open hardware." Is it?
Forecast: open ISA — does that make the chip open? Guess.
Separate the three layers. Why this step? Recall openness can live independently at ISA (spec), microarchitecture/RTL (implementation), toolchain. We must check each, not lump them.
Check each layer. Why? ISA = RISC-V = open (it's a public spec, like the rules of chess). RTL = secret/licensed = closed . Toolchain = GCC exists but the silicon build flow is private = effectively closed. Only 1 of 3 layers is open.
Verdict. Why? "Open hardware" means the silicon design (RTL/layout) is inspectable and fabricable. An open ISA is a contract , not a design ; you can implement it in a fully proprietary core. So the claim is false — this is a closed chip that speaks an open ISA.
Verify: contrast with OpenTitan, which is open at all three layers (RISC-V ISA + published Ibex RTL + open toolchain). The phone SoC is open at exactly one . Different count ⟹ different verdict. ✔
Recall Quick self-test
Bytes for N = 10 32-bit instructions ::: 40 bytes (next free = 0x28 ).
Instructions if last is at 0x1C ::: 8 (index 7 , plus one for 0-indexing).
Collision effort for a 128-bit hash ::: ≈ 2 64 ≈ 1.8 × 1 0 19 .
Second-preimage effort for SHA-256 ::: ≈ 2 256 , not 2 128 .
Why does a hash alone fail secure boot ::: integrity but no authenticity — attacker rewrites image and its stored hash.
Can an eFuse go 1 → 0 ::: No — burns are one-way; only 0 → 1 is possible, giving anti-rollback.
Does an open ISA make a chip open hardware ::: No — the RTL/layout must be open; ISA is only a spec.
C ollision uses the C heaper wall 2 n /2 (attacker picks both images). Fixed-target preimage is the pricier 2 n . Pick n double the security you want.
Parent: Open hardware ecosystem (OpenRISC, OpenTitan) (index 6.5.12)