Trust in Silicon
If the foundation is unsound, what is the watchman worth?
Chapter 7 — Trust in Silicon
“A root of trust is the one thing you are not allowed to be wrong about.” — an industry adage
“Unless the LORD builds the house, those who labor to build it labor in vain.” — Psalm 127:1 (ESV)
Why This Matters
Last week you finished wiring the system together, and you left Chapter 6 with a promise: the cellular modem’s independence is an architecture fact and a security fact, and this week we collect on it.
Here is why this is its own week. Every other computer you have studied sits in a rack, in a room, behind a door, behind a badge reader. This one goes in a pocket, and the pocket goes everywhere. It gets left in a taxi. It gets taken at a border. It gets decapped, glitched, and probed by an adversary with unlimited time and physical possession of the board. Server threat modeling gets to assume the attacker is remote. Mobile threat modeling does not, and that single change in assumption reorganizes the entire hardware design.
So the mobile architect faces a question a server architect is mostly spared: what can you still guarantee when the attacker owns the device? Not “encrypt everything” — encryption is arithmetic, arithmetic needs a key, a key has to live somewhere, and wherever it lives the attacker is standing next to it. The answer has to be structural: silicon that behaves differently from the software running on it, because software is what the attacker got to first. That structure is an immutable first instruction, fused keys that cannot be rewritten, a chain in which every stage verifies the next before it runs, and domains — normal world, secure world, separate coprocessor — with different assets in each. All of it derives from one anchor nothing else can vouch for. Get the anchor wrong and everything above it is theater: signatures that validate, boot states that say green, attestations a server accepts, all perfectly consistent and all meaningless.
The Four Questions do not go away this week; security re-prices every one of them. Verified boot costs launch latency (performance). Constant-time crypto and always-on secure subsystems cost joules (energy). A tamper-resistant element spends die area and standby power forever (thermals and budget). And the security domain a workload runs in is a placement decision — the most consequential one in the book, because putting the biometric matcher in the wrong domain is not slow, it is broken. Security is not a fifth question bolted onto the four. It is the four, asked again, by someone hostile.
The Christian question this week is the sharpest in the course, and it is not decorative. Psalm 127 opens: “Unless the LORD builds the house, those who labor to build it labor in vain” (ESV). The next line is about a watchman staying awake in vain. That is not a poem about laziness. It is a claim about foundations you did not lay and cannot inspect, and about what vigilance is worth when the base is unsound. A hardware security engineer meets that claim professionally, every day, and owes it a technical answer. We will give one.
7.1 — The Threat Model Changes When the Device Leaves the Building
Start where every honest security document starts: name the adversary. Not “hackers” — specific adversaries with specific capabilities, because a mechanism that stops one may be irrelevant to another.
| Adversary | What they have | What they can attempt |
|---|---|---|
| Remote software attacker | A network path to the device | Exploit a service, the browser, the media parser, the radio stack |
| Malicious application | Sandboxed code execution, user-granted permissions | Escape the sandbox, abuse permissions, attack other apps through shared hardware |
| Network attacker | A position between the device and the world | Intercept, modify, downgrade, or record traffic for later |
| Physical possession | The device in hand, for minutes or months | Boot modified firmware, probe buses, glitch the power rail, decap the die |
| Supply-chain attacker | Access before the device reaches the user | Substitute components, install firmware, provision their own keys |
The fourth row is what changes mobile architecture. A physically seized server is generally considered lost, and its mitigations are procedural — a locked cage, a guard, a disk encrypted with a key held elsewhere. A phone is expected to be seized and is nevertheless expected to keep its secrets. That expectation is what hardware security in this course is for.
Students underrate the second row. A malicious application is neither remote nor physical. It is inside, running on your cores, sharing your caches, your memory controller, your prefetchers. Every resource the architect shared to save area or energy in Chapters 2 through 6 is a channel between that application and everything else on the device. Sharing is an efficiency decision and an isolation decision at once, and you cannot make one without making the other. The last row is worse still: the supply-chain attacker reaches the device before the root of trust is established — a polite way of saying they get to be the root of trust.
Coach’s Note — Write your threat model before you write your mechanism list. Every engineer can recite “secure boot, TEE, hardware keys.” Very few can say which adversary each one stops and which it does nothing about. Verified boot is superb against persistence and useless against a live exploit in a running browser. A secure element protects a payment credential and not the screenshot of your bank balance in the photo library. A mechanism without a named adversary is a feature, not a defense.
7.2 — Root of Trust: Trust Is Derived, Never Asserted
Every security claim a device makes reduces, eventually, to one question: who says so, and why do you believe them?
Run it backwards. The app trusts the OS. The OS was verified by the bootloader, which was verified by an earlier bootloader, which was verified by code in the boot ROM. And the boot ROM is not verified by anything. It is the root of trust, trusted for a physical reason rather than a cryptographic one — two of them:
- The first stage is immutable. It is mask ROM, fixed when the die was fabricated. No update path, no write command. If it contains a bug, that bug is in every unit of that silicon forever — which is why the boot ROM is the smallest, most-reviewed, most-boring code in the system, and why “an unpatchable boot ROM bug” is the phrase that ends careers.
- The keys are fused. A root key — more commonly the hash of an authorized public key — is burned into one-time-programmable fuses (eFuses/OTP) during manufacture. Blown fuses do not un-blow, and software cannot rewrite them because no mechanism to rewrite them exists.
Everything else in the chain is trusted because something above it checked a signature. That is what “derived” means, and it is the most important idea in this chapter. Immutability at the top is a fact about physics. Immutability everywhere below is a fact about a check that ran a few milliseconds ago. Remove the check and the property evaporates — the code is exactly as writable as it always was; you simply stopped looking. Open code/boot-chain.csv and read the key_source column top to bottom: the first row says the anchor is the anchor, and every row after it names the stage above as the source of its authority. That column is the chain, written out.
So when someone tells you a device is secure, ask one question — “derived from what?” — and keep asking until you reach a fuse or catch the loop. Circular trust is astonishingly common and it always sounds fine on the first pass.
7.3 — The Chain: Secure Boot, Verified Boot, and Rollback
Secure boot is the mechanism: each stage cryptographically verifies the next stage’s image before transferring control to it. Boot ROM verifies the first bootloader; that one verifies the next; that one verifies the trusted OS and the kernel. The kernel verifies the system image — typically block by block against a signed root hash as blocks are read, so a multi-gigabyte partition is authenticated without reading all of it at boot.
Verified boot on Android adds two things worth knowing by name. First, a boot state — green, yellow, orange, or red — describing whether the chain verified against the device’s own keys, against a user-installed key, or not at all. Second, rollback protection: the device records a minimum acceptable version and refuses to boot an older image, even a correctly signed one.
That second mechanism is the one students forget and attackers love. Signature verification answers “did the vendor produce this image?” It does not answer “is this image still safe?” Last year’s firmware was signed by the vendor — and it is also the firmware with the vulnerability that got patched. Without rollback protection, an attacker with write access installs a genuine, correctly signed, publicly known-vulnerable image; every check passes, the boot state is green, and the device is owned. Rollback protection is the difference between authenticating the author and authenticating the version.
Now make it concrete. code/chain_check.py prints the nominal chain and ends with VERDICT: chain intact. Break exactly one link and read what it buys the attacker:
python3 code/chain_check.py --fault noverify:kernel
python3 code/chain_check.py --fault rollback:bootloader_stage_2
python3 code/chain_check.py --fault mutable:bootloader_stage_1
python3 code/chain_check.py --all # the single-fault sweep
The tool reports the first untrusted stage and then, separately, what a software-only attacker and a physical-possession attacker can each do from there. Those are different answers, and the difference is the lesson. mutable:boot_rom is not exploitable by software at all — nothing rewrites mask ROM from a shell — but for an adversary with the board on a bench it is total and permanent. Meanwhile noverify:kernel is reachable remotely and hands the attacker a silently modified system image while the user’s screen still shows a good boot state. Read the sweep table as an architect: a fault high in the chain costs more to reach and buys more when reached. Two injections have no effect at all, because they remove a guarantee about a stage with nothing after it. Find those two — a mechanism with no downstream consumer is one you are paying for and not using.
Coach’s Note — Notice what the chain does not do. It says nothing about a device that boots perfectly and is then exploited at runtime through the browser. Verified boot defends against persistence, not against compromise. Its real promise is: “however badly today went, a reboot returns you to code the vendor signed.” That is enormously valuable, and much narrower than “this device is secure.” Say the narrow thing in your report. Precision about what a mechanism covers is most of what separates a threat model from a brochure.
7.4 — TrustZone: Isolation by Mode, Enforced by the System
You met exception levels in Chapter 1 as a privilege structure: EL0 for applications, EL1 for the OS kernel, EL2 for a hypervisor, EL3 for secure monitor firmware. Higher number, more privilege. Now meet the second axis.
Arm TrustZone partitions the system into a Secure world and a Non-secure (Normal) world. Those are not privilege levels; they are two worlds, each with its own EL0 and EL1. A rich OS and its applications run in the Normal world. A small trusted OS with a handful of trusted applications — key handling, DRM, biometric matching — runs in the Secure world. EL3 firmware sits above both and mediates the transition.
Here is the part most write-ups miss. The Secure/Non-secure distinction is carried on the interconnect. An NS (non-secure) bit propagates with transactions out of the core and across the fabric you studied in Chapter 6. Memory regions can be marked secure. Peripherals can be marked secure. A DMA-capable master can be marked secure or not. So when a Normal-world driver issues a read to a secure memory region, the fabric refuses it — not the kernel, not a software permission check, the wires.
That is why TrustZone is a system partition and not merely a CPU mode. A CPU mode protects you from code on that CPU. A system partition protects you from every master on the interconnect, including DMA engines that never execute an instruction of yours at all.
Armv9-A introduces the newer direction: the Confidential Compute Architecture (CCA), whose Realm Management Extension adds a third world — the Realm world — alongside Secure and Non-secure. The motivating problem is different: TrustZone protects the platform’s secrets from the rich OS, while Realms protect a workload’s secrets from the platform — from a hypervisor or host OS the workload’s owner does not control. Adoption is generational; treat it as the direction of travel, not as something present on a given part.
| Normal world | Secure world | Realm world (Armv9 CCA) | |
|---|---|---|---|
| Typical occupant | The rich OS and its apps | A small trusted OS, trusted apps | A confidential workload |
| Protects whom, from whom | Nothing, by itself | Platform secrets, from the rich OS | The workload, from the host/hypervisor |
| Enforced by | Normal MMU/privilege rules | NS bit propagated system-wide | Realm management, granule protection |
One more thing about the boundary. Crossing from Normal to Secure is not a function call; it is a controlled, narrow, expensive transition through monitor firmware, and its narrowness is the point. Every extra call the Normal world can make into the Secure world is another line of trusted code that has to be perfect. The attack surface of a TEE is exactly the size of its interface.
7.5 — Isolation by Silicon: Secure Enclaves and Secure Elements
TrustZone isolates by mode: the same cores, the same caches, the same memory controller, in a different state. That buys enormous reach — the whole system honors the partition — and inherits one structural weakness. The two worlds share microarchitecture: branch predictors, cache levels, prefetchers, the memory bus. Everything Chapters 2 and 3 taught you about sharing resources for efficiency is, from a security standpoint, a list of things two mutually distrusting worlds now share. §7.9 is about what leaks through them.
The alternative is isolation by silicon: do not share the microarchitecture at all. Put the sensitive work on a separate processor with its own boot ROM, its own memory, and its own path outward. Apple’s Secure Enclave is the widely cited example; a secure element — a distinct tamper-resistant chip descended from the smart card, used for payment credentials — takes the idea onto its own die and often its own package. Google’s Titan M-class chip is another commonly cited security processor.
Do not read this as a ranking. Read it as a table of costs:
| Isolation by mode (TrustZone) | Isolation by silicon (enclave / SE) | |
|---|---|---|
| Reach across the system | System-wide: the NS bit governs memory, peripherals, DMA masters | Local: it protects what it holds |
| Shared microarchitecture with the attacker | Yes — caches, predictors, prefetchers, memory bus | No, or very little |
| Silicon cost | Low; reuses the application cores | Real: another core, another ROM, its own memory |
| Performance and flexibility | Application-core speed; a trusted OS can host many trusted apps | Deliberately modest; narrow, purpose-built functions |
| Best at | Enforcing a system-wide policy | Holding a small secret against a determined adversary |
These answer different questions. If you need the whole system to agree that a memory region is off-limits to every master on the fabric, you need something like TrustZone; a coprocessor cannot enforce that. If you need a small secret to survive an adversary who owns the application cores and will sit in your cache measuring timings for a week, a separate die with its own memory is stronger — paid for in area, in standby power, and in the fact that everything it does must fit through a narrow mailbox.
Most shipping devices use both, and the interesting engineering is the assignment: which asset lives in which domain. That is a placement question — the same kind you have answered since Chapter 4, except the cost function now includes an adversary. A biometric template on the application cores is fast and wrong. A payment credential in a secure element is slow and right. Model weights? Genuinely contested as of 2026, and I want you to argue it rather than look it up.
7.6 — Memory Protection as a Class, Not a Patch
The MMU you met in Chapter 3 as a performance and virtualization structure is also the primary memory-safety mechanism on the device. Page tables enforce read/write/execute permissions and the separation of address spaces; the SMMU/IOMMU extends that to devices, so a compromised camera or modem DMA engine sees only its own translated address space rather than all of physical memory. In Chapter 6 the SMMU was a convenience. Here it stands between a compromised peripheral and your kernel’s memory.
Above that sit three architectural mitigations you should be able to name, date, and characterize:
- Pointer Authentication (PAC), from Armv8.3-A. A pointer is signed with a keyed MAC stored in its unused upper bits, and authenticated before use. A return address or function pointer that an attacker overwrote will not authenticate. This attacks the reuse half of memory-corruption exploitation: you can still corrupt the pointer, you just cannot forge a valid one.
- Branch Target Identification (BTI), from Armv8.5-A. Indirect branches may only land on instructions explicitly marked as legal landing pads, constraining where control flow can go at all.
- Memory Tagging Extension (MTE), from Armv8.5-A. A 4-bit tag per 16-byte granule of memory, with a matching tag carried in the top byte of the pointer (relying on top-byte-ignore). Access with a mismatched tag faults. This catches use-after-free and buffer overflow in hardware, at the moment of the bad access, rather than by luck at some later crash.
These belong in an architecture course because each is a class of mitigation rather than a patch for a bug. A patch fixes one defect; a class of mitigation makes an entire exploitation technique unreliable, including against defects nobody has found yet. That investment is bought in silicon — tag storage, tag-checking logic, signing hardware in the pipeline — so somebody spent area and energy on it, forever, for every unit, against attacks not yet written. MTE’s tags occupy memory and its checks occupy cycles; the cost depends on the implementation and the mode you run, which makes it precisely the sort of figure you measure rather than quote. A mitigation whose cost you have not measured is a mitigation whose deployment you cannot defend. Chapter 8 teaches you to measure it honestly; this week you learn why the number matters.
7.7 — Keys You Cannot Read, Attestation, and Biometrics That Never Leave
Here is the design pattern that runs through the whole secure subsystem, and once you see it you will see it everywhere:
The application never receives the key. It requests an operation.
Android’s Keystore, with StrongBox for keys backed by dedicated secure hardware, and Apple’s Secure Enclave both work this way. Your code calls “sign this challenge with key handle 7,” never “give me key 7.” The key material was generated inside the secure subsystem, has never been outside it, and cannot be exported. Compromise the app and you get the ability to ask, for as long as you have the app, under whatever policy the key was created with — user authentication required, rate-limited, valid only while unlocked. You do not get the key. There is nothing to exfiltrate, no file to steal, no memory dump that yields it.
Key attestation closes the loop from the other end. A server must decide whether the key it is talking to really lives in hardware or is a software key some emulator made up. Attestation is a certificate chain, rooted in a key provisioned at manufacture, asserting the generated key’s properties: that it lives in hardware, at what security level, under what policy. The server verifies the chain against the vendor’s root and now knows something about silicon, not just about a protocol message.
Biometrics apply the pattern to a different asset. The fingerprint or face template does not leave the secure subsystem; the sensor path, the matcher, and the template store are all inside. What crosses into the rich OS is not biometric data but a yes/no result and a signed assertion that a match happened. The rich OS learns that the user authenticated; it never learns what the user’s finger looks like. If the entire userspace were compromised tomorrow, the template would still be on the wrong side of a boundary the compromise did not cross.
That is the architecture in one sentence: move the secret behind a boundary and export only decisions. It applies to disk keys, payment credentials, DRM keys, attestation keys, and — increasingly — to on-device model weights someone paid to train.
7.8 — Crypto Acceleration and the Policy It Bought
Armv8 added cryptographic extension instructions — AES, SHA, and PMULL among them — implementing the expensive inner rounds of common primitives in hardware. Small section, large consequence, and the consequence is not technical.
When encryption is expensive it is a feature, features are optional, and optional security gets negotiated away under schedule pressure. When encryption becomes nearly free, the argument for leaving it off collapses and it becomes a default. Full-disk encryption on by default, transport encryption on by default, encrypted backups by default — those are policy outcomes that arrived on the back of an instruction-set decision about throughput in a block cipher round. Architectural decisions have policy consequences, and the causality runs from the silicon outward. Nobody voted to encrypt every phone; somebody made it cheap, and then not doing it stopped being defensible.
Free is not free, of course. Those instructions occupy die area and consume energy, and encrypting a sustained multi-gigabyte write to storage shows up in the power budget and eventually in Chapter 5’s thermal budget. It is simply so much cheaper than the software alternative that the comparison stopped being interesting — Chapter 4’s fixed-function argument, applied to a security primitive instead of a video codec.
7.9 — Side Channels: When an Optimization Becomes an Oracle
Every mechanism so far controls what an attacker can read. Side channels are about what an attacker can infer — from time, from cache state, from power draw, from anything the system does differently depending on a secret. Start with the simplest case, and measure it yourself.
g++ -O2 -std=c++17 -o timing_leak code/timing_leak.cpp && ./timing_leak
code/timing_leak.cpp compares a secret buffer against a guess two ways. The naive version is the one everyone writes: walk the bytes, return false the moment they differ. The constant-time version accumulates differences with XOR and OR and always touches every byte. It times both against guesses sharing a longer and longer prefix with the secret. On my machine, at 4096 bytes:
matching prefix naive (early exit) constant time (rows abridged)
0 bytes 1.0 44.9
1024 bytes 362.7 41.7
2048 bytes 716.7 41.7
3072 bytes 1074.9 41.7
4096 bytes 1445.5 42.2
Read the naive column. It is a ruler. An attacker who can submit guesses and time the check never searches the space of all buffers; they recover the secret one byte at a time, because the machine tells them how many leading bytes are right. The constant-time column is flat, within noise. It refuses to answer the question.
Now read the cost. The naive compare’s best case is about a nanosecond — the first byte differs and it goes home. The constant-time compare always pays about forty. You did not make the comparison slower on average by a few percent. You gave up the best case entirely, forever, so that the worst case would never be distinguishable from it. That is the shape of every side-channel mitigation you will ever deploy.
Scale the idea up and you get the speculative-execution family. Meltdown (CVE-2017-5754) and Spectre (v1, CVE-2017-5753; v2, CVE-2017-5715) were disclosed in January 2018 and affected many out-of-order cores across multiple vendors, including some Arm Cortex-A designs — Arm published a list of which of its cores were affected. The mechanism, stripped to its bones: a core speculates past a check, performs work it should not have performed, then discards the architectural result when the misprediction resolves. Architectural state is correctly rolled back; microarchitectural state — which cache lines are now resident — is not. An attacker measures the cache with Flush+Reload or Prime+Probe and reads out what the speculation touched. Notice what was attacked: not somebody writing the wrong line of code, but a performance feature working exactly as designed, doing the thing that made it valuable in Chapter 1 — running ahead of certainty.
The mobile-specific modern example lands on a mechanism this course spent a week praising. A data memory-dependent prefetcher (DMP) looks at values being loaded, notices that some look like pointers, and prefetches what they point to — a clever answer to Chapter 3’s pointer-chasing problem, the one case where prefetching normally fails. It is also a machine that dereferences data. Augury (2022) and GoFetch (2024), both targeting Apple silicon’s DMP, showed that this breaks a foundational assumption of constant-time cryptography: that data-independent code produces data-independent memory behavior. If the hardware may decide on its own to dereference your secret because it looks pointer-shaped, constant-time software is no longer sufficient. The abstraction the cryptographers relied on was never in their contract.
Hence the law of this chapter:
Any optimization that makes behavior depend on data is a potential side channel, and mitigating it costs performance. That tradeoff cannot be engineered away. It can only be decided — by a person, for a named product, against a named adversary.
Disable the DMP for a cryptographic process and you lose the prefetching. Flush predictors across a security boundary and you lose the prediction. Every one is a real, measurable cost, paid by every user, to defeat an attacker most users will never face. That is a judgment — the one your Hard tier asks you to make and defend with your own numbers, using Chapter 8’s methodology.
Coach’s Note — The most dangerous sentence in security engineering is “that’s just a performance optimization.” Branch prediction was just a performance optimization. So was caching. So was prefetching data that looks like a pointer. Every one turned into an oracle. When you review an architecture, ask of each clever mechanism: does its behavior depend on data it is not supposed to know? If yes, you have found the next paper.
7.10 — Physical Attacks and the Adversary Who Owns the Board
Everything above assumes the attacker interacts with the device through its intended interfaces. The physical adversary does not.
- Debug port abuse. JTAG and vendor debug interfaces exist because silicon must be brought up and diagnosed. Left enabled in production they are a supervisor console. The countermeasure is a fuse that disables debug or gates it behind an authenticated challenge — and the interesting failure is a production run where that fuse was left unblown.
- Fault injection. Glitch the supply voltage or the clock at exactly the right moment, or hit the die with a laser, and an instruction fetches the wrong value or a comparison returns the wrong answer. The classic target is the signature check itself: you need not forge a signature if you can make the branch testing it go the other way. Countermeasures include on-die voltage and clock sensors, redundant checks, and randomized timing so the attacker cannot aim.
- Decapping, probing, and cold boot. Remove the package, image the die, probe internal buses, read fuse states; or tap an inter-package bus; or recover DRAM contents that persist briefly after power loss. Countermeasures include shields and sensors and — the architectural one — assuming everything outside the die is hostile: keep keys on-die in the secure subsystem, and authenticate and encrypt memory that leaves it.
Two conclusions matter more than the list. First, physical attacks are a cost curve, not a binary. Nothing here says “impossible”; everything says “this requires equipment, expertise, time, and destroyed units.” The goal is to move the attacker’s cost above the value of the asset for the population you are defending — so state explicitly which attackers you have decided not to defend against. A threat model that claims to stop everyone is a threat model nobody reviewed. Second, this is why isolation-by-silicon exists: a tamper-resistant element with its own die, its own memory, and sensors watching its own power rail is a far harder physical target than shared DRAM protected by a bit on the interconnect. That is §7.5’s cost table paying off.
7.11 — The Modem Is a Second Computer
Now collect on Chapter 6’s promise.
The cellular modem is not a peripheral the way a temperature sensor is. It is a large subsystem with its own DSPs, its own real-time software stack, and its own update lifecycle, integrated onto the SoC or sitting beside it. Architecturally it is a computer running its own operating system next to yours. The Wi-Fi/Bluetooth combo subsystem is the same story at smaller scale. Three consequences follow, all of them hardware-architecture consequences rather than software ones:
- It has an enormous, permanently exposed attack surface. The modem parses attacker-influenced input — protocol messages from a network you do not control — continuously, in real time, whether or not the screen is on. It is the one part of the device listening while the user believes the device is idle.
- Your OS’s security model does not apply to it. Your verified boot chain, your MMU, your PAC and BTI and MTE, your Keystore policy — none of that governs code executing on the modem’s own processors. It runs its own firmware, verified (if at all) by its own chain.
- So the only defense that matters is architectural isolation. The question is not “is the modem firmware bug-free” — it is a large real-time software stack and you may assume it is not. The question is if the modem is fully compromised, what can it reach? That is an SMMU question, a memory-map question, and an interconnect-permissions question, all from Chapter 6. A modem confined by an SMMU to its own translated address space is a contained problem. A modem with unrestricted DMA into system memory is an unbounded one.
This is the book’s cleanest illustration of why integration is a security discipline. The modem’s isolation is not a property of the modem; it is a property of the fabric and the SMMU configuration — the joints, not the members.
Coach’s Note — When you assess a device, list every processor running firmware you did not verify: modem, Wi-Fi/BT, sensor hub, ISP, display microcontrollers, storage controller, power-management IC. Then answer for each: what can it reach on the interconnect? You will find more independent computers inside a phone than most engineers assume, and that “the phone” as a single trust domain was always a simplification the block diagram encouraged.
7.12 — Post-Quantum Cryptography as an Emerging Mobile Workload
This last section is where AI-as-untrustworthy-research-assistant will try hardest to lie to you.
In August 2024, NIST published the first post-quantum cryptography standards:
| Standard | Algorithm | From | Purpose |
|---|---|---|---|
| FIPS 203 | ML-KEM | CRYSTALS-Kyber | Key encapsulation |
| FIPS 204 | ML-DSA | CRYSTALS-Dilithium | Digital signatures |
| FIPS 205 | SLH-DSA | SPHINCS+ | Hash-based digital signatures |
Why a mobile architect cares, when large quantum computers do not exist: “harvest now, decrypt later.” An adversary who records encrypted traffic today can decrypt it whenever the capability arrives. Any secret whose value outlives that gap — health records, source identities, long-lived credentials, sealed archives — is already exposed if it is protected with today’s public-key cryptography over a channel someone is recording. A present engineering problem about future capability. I will not tell you when such computers will exist, and nobody who does should be believed.
The architecture consequences land squarely on this course’s four questions:
- Sizes. Post-quantum keys, ciphertexts, and signatures are substantially larger than elliptic-curve ones — storage pressure inside a small, expensive, tamper-resistant secure element sized years ago for much smaller objects, and secure-element storage is some of the costliest memory on the device.
- Wire bytes. Every handshake carries more bytes. Chapter 6 gives the consequence exactly: radio energy is dominated by time spent awake, so extra handshake bytes cost energy twice — the bytes, and the awake time to move them.
- Compute and placement. The operations cost more than their classical counterparts, which pushes toward acceleration — silicon, area, standby power someone must justify against every other block competing for the same die. And which processor performs the operation is a placement decision with a security constraint attached: the fast answer and the trustworthy answer are not always the same processor.
And now the part I care about most. This book will not give you the sizes. Not because they are secret — they are in the standards above — but because a key size is exactly the kind of specific, confident, checkable number a language model fabricates without hesitation and a reviewer verifies. You will look them up in the primary source and cite where you found them.
code/pqc_budget.py enforces that. It knows no sizes. It reads them from code/pqc-sizes-example.csv, which ships with every byte count 0 and every verified flag no, so running it as shipped gives you a table of zeros, a wall of NO <-- unverified, and a banner saying everything below is meaningless. That is the tool working correctly. Copy the CSV, look each size up in FIPS 203, 204, and 205, enter the value, set verified=yes, record the document and table you read it in, and run it again:
python3 code/pqc_budget.py --sizes my-pqc-sizes.csv --handshakes-per-day 400 --se-bytes 65536
Now it reports the per-handshake wire cost of a classical exchange versus two post-quantum ones, the daily and monthly radio bytes at your handshake rate, and whether the private material fits a stated secure-element budget — every number traceable to a document you read. That is the standard for this course and for your Week 8 capstone.
Coach’s Note — Ask a chatbot for a post-quantum key size right now, before you look it up. Write down what it says, then read the standard. Sometimes the model is right; that is not the point. The point is that you cannot tell which time it is without checking, and the confidence is identical either way. Use AI to explain lattice-based key encapsulation — it is genuinely good at that. Never use it to source a number that will appear in a document with your name on it.
7.13 — Interactive Lab: The Chain of Trust Inspector
Below this chapter on the website you will find The Chain of Trust Inspector. It is part of the chapter, not an extra.
Panel 1 — walk the chain. Step through the boot chain stage by stage, toggling each stage’s properties: is it immutable, does it verify the next stage, is rollback protection on, where does its key live. At every break the inspector reports two verdicts — what an attacker with software access can now do, and what an attacker with physical possession can now do. Before you toggle anything, predict which stage’s compromise buys the attacker the most. Then hunt for a break that costs the software attacker nothing and the physical attacker everything, and one that does the reverse. Both exist.
Panel 2 — place the assets. You are handed a biometric template, the disk encryption key, a payment credential, ordinary application data, and a set of on-device model weights, plus four domains: normal world, TEE, secure element, or nowhere on this device. Assign each and the inspector grades you with reasons rather than a score. That fourth option is the one students skip: sometimes the correct decision is that an asset should not be on the device at all, and an engineer who cannot reach that conclusion will over-trust every enclave they are handed.
What it teaches: that a chain of trust is a structure with load paths, so breaking a link has a specific, predictable blast radius rather than a vague “it’s insecure”; and that asset placement is a design activity in which the fast answer and the safe answer usually differ. Panel 2 is this week’s threat-model asset table in miniature.
7.14 — Unless the LORD Builds the House
Psalm 127 opens with a sentence about foundations: “Unless the LORD builds the house, those who labor to build it labor in vain” (Psalm 127:1, ESV). The verse continues to a watchman who stays awake in vain. It is not a poem against work; it is a claim about what work rests on — that labor and vigilance are real and good and also derivative, and that their worth depends on a foundation the laborer did not lay and cannot inspect. That is, with almost no translation required, the structure of this entire chapter.
Everything in a secure device is derived. The app’s trust from the OS, the OS’s from the bootloader, the bootloader’s from the boot ROM, and the boot ROM’s from a fused key and a fabrication process you were not present for, in a facility you have never seen, under a supply chain you cannot personally audit. You did not lay that foundation, and you cannot really inspect it — not without equipment you do not have and a destructive process that consumes the device you were trying to verify. You accept it, and everything you build stands on that acceptance. A security engineer is a person who has thought carefully about exactly where their own verification stops and their trust begins. Most people never locate that line. It is the professional’s job to know precisely where it is.
Now the harder edge, from the second half of the verse. A watchman on an unsound foundation is not merely useless. He is actively misleading, because he generates confidence. The house looks guarded; someone sleeps soundly because a light is on. Name that failure mode and carry it: a mechanism that fails silently while continuing to report success is worse than no mechanism at all. Verified boot with a compromised root key does not merely fail to protect; it displays a green boot state. Attestation rooted in a key an attacker provisioned convinces a remote server. A secure element holding a key derived from a broken chain still produces valid signatures. In every case the user is worse off than if the feature had never existed, because they made decisions — carried the device across a border, entered the credential, trusted the assertion — they would not have made without the light on. This is why §7.3 insisted you say the narrow thing: verified boot defends against persistence, not a live exploit; a TEE protects the assets you put in it, not the ones you left outside. Every marketing sentence that rounds those up to “secure” is a watchman posted on someone else’s floor.
There is a vocational point underneath, and the Lutheran tradition would press it. You are working inside a house you did not build. That is not a defect in your position; it is the ordinary condition of every creature who has ever done useful work, and it is what Chapter 1 named when it said limits are the precondition of craft rather than its enemy. The response to derived trust is neither paralysis nor the pretense of self-sufficiency. It is fidelity within your reach: verify what you can actually verify, state plainly what you take on trust, and refuse to generate confidence you have not earned. The engineer who writes “we assume the fused root key was provisioned correctly at manufacture, and we have no means to confirm it” has done something better than the engineer who writes “the device is secure.” He has told the truth about the foundation — keep the watch you are able to keep, and say clearly what lies beneath it.
7.15 — Common Pitfalls
Pitfall: Treating “it’s signed” as the end of the argument.
Example: A design review concludes the firmware is safe because every image is signed, with nobody asking who checks the signature or where the checking key came from.
Fix: Ask “derived from what?” at every stage until you reach a fuse or catch a loop. Run python3 code/chain_check.py --all and count how many single faults leave every signature perfectly valid.
Pitfall: Forgetting rollback protection, so an old signed image is a valid image.
Example: An attacker installs last year’s genuine, vendor-signed firmware containing a patched vulnerability. Every signature validates; the boot state is green.
Fix: Authenticate the version, not only the author. Record a minimum acceptable version and refuse older ones. Try --fault rollback:bootloader_stage_2 and read what it buys.
Pitfall: Believing a TEE protects an asset you never put inside it. Example: A team says “we have a TEE, so credentials are safe,” while the credential is cached in a normal-world process for convenience. Fix: Enumerate assets first, then say for each which domain it lives in and where it is copied to. An asset is protected by the boundary it is behind at the moment of the attack, not the one it was born behind.
Pitfall: Dismissing side channels as academic and unquantified.
Example: “Nobody’s really going to time our comparison loop” — said about code that compares a MAC with an early-exit byte loop.
Fix: Measure it. ./timing_leak --bytes 32 --reps 200000 shows a monotonic rise in seconds. Then price the mitigation: the constant-time version gives up the best case permanently, and that cost is the decision you are actually making.
Pitfall: Quoting a cryptographic key or signature size you did not read in the primary standard.
Example: A migration memo cites post-quantum sizes a chatbot supplied; two of the five are wrong and the storage conclusion inverts.
Fix: Fill in code/pqc-sizes-example.csv from FIPS 203/204/205 yourself, set verified=yes, and record the document and table in source. pqc_budget.py shouts at you until you do — that is the feature.
Pitfall: Ignoring the processors that are not the CPU. Example: A threat model covers the application processor in detail and never mentions the modem, the Wi-Fi/BT subsystem, or the sensor hub. Fix: List every firmware-running processor, then answer for each: what can it reach on the interconnect?
7.16 — Reps
Open the exercises and do all of them. They build the reflexes the project grades: reading a chain of trust before you break it, injecting single faults and naming the attacker capability each buys, assigning assets to domains, measuring a real timing side channel, and sourcing post-quantum sizes from the standard rather than from a confident stranger.
This week’s AI policy. Use AI to explain; do not use it to source. Every number, date, CVE identifier, attack name, and key size in your work must come from a primary document you personally opened, and your ai-usage.txt says so. Per Appendix D, a fabricated figure is an integrity failure, not a deduction — and this is the week that rule stops being administrative, because a wrong key size in a migration memo becomes a wrong procurement decision.
A preview:
- Rep 2 — Break the chain with one injected fault and name what the attacker can now do.
- Rep 4 — Place every asset — biometric template, disk key, payment credential, model weights — in the right domain.
- Rep 7 — Measure the timing leak in an early-exit comparison, predicting the shape before you run it.
- Rep 10 — Fill in the post-quantum size table from a primary source and cite every byte you enter.
- Done? One Last Thing — the threat model in miniature: one device, one scenario, one residual risk you cannot close.
A short “Check Your Reps” quiz is embedded on this page, below the lab. It is an ungraded self-check; take it before you move on. Then sit this week’s graded knowledge check in Canvas — worth 1.5%, same material, larger pool, randomized draw, so retaking it is real practice rather than memorization.
7.17 — This Week’s Project
You are ready for P7 — The Silicon Threat Model, in Project 7 — one of the six weekly labs, worth 7% of your course grade.
Pick one device in one named scenario — a clinician’s tablet, a journalist’s phone crossing a border, a warehouse wearable, or a consumer headset — and produce threat-model-report.docx: the assets, the adversaries with their actual capabilities, the hardware mechanism defending each asset, and the graded core, the residual risk each mechanism does not cover. You will run chain_check.py and timing_leak.cpp for real and report per Appendix C. Medium adds the post-quantum migration budget. Hard asks for the memo on a mitigation you would decline to enable, defended with the performance cost you measured — the judgment call no tool makes for you.
The residual-risk column is where the grade lives. Anyone can list mechanisms; the list is in this chapter and on every vendor’s marketing page. What distinguishes an engineer is saying, of each mechanism, exactly what it does not cover — and deciding whether the remainder is acceptable for this user, in this scenario, against this adversary. That is the watchman knowing where his floor stops.
7.18 — Coach’s Final Word
You came into this week able to describe a phone. You leave it able to say what a phone can still promise when someone else is holding it.
You can trace a chain of trust to its anchor and name what the anchor rests on. You can inject a fault and state precisely what a software attacker and a physical attacker each gain — two different answers to what looked like one question. You can explain why TrustZone is a system partition rather than a CPU mode, and why a separate coprocessor answers a different question rather than answering the same one better. You measured a timing side channel with your own hands and priced the fix. And you know why post-quantum cryptography is a mobile architecture problem: storage in a secure element, bytes on a radio whose energy is dominated by awake time, and cycles somebody has to place.
Hold on to the law: an optimization that makes behavior depend on data is a potential side channel, and mitigating it costs performance. Not a bug awaiting a smarter engineer — a permanent tension between two of The Four Questions, decided by a person, for a product, against a named adversary. Next week you learn to measure the cost of that decision honestly, so that when you make it you can show your work.
Unless the LORD builds the house, those who labor to build it labor in vain. The engineering translation is not despair; it is precision. Verify what you can verify. Say plainly what you take on trust. And never generate confidence you have not earned — because a watchman on an unsound foundation does not merely fail to protect the house. He convinces everyone inside that it is safe to sleep.
See you next week.
Up next: Read the exercises and do every rep — they are the conditioning. Then open Project 7 and build the threat model. Workbench setup is in Appendix A; the datasets in code/ are documented in Appendix B; methodology in Appendix C; grading and the AI policy in Appendix D; terms in Appendix E. Then Chapter 8 — measure, compare, decide.
Previously: Chapter 6 — wiring the system together.
Week 7 Knowledge Check
matching prefix naive (early exit) constant time (rows abridged)
0 bytes 1.0 44.9
2048 bytes 716.7 41.7
4096 bytes 1445.5 42.2 — none (no effect). What do those two have in common, and why is that architecturally correct rather than a bug in the tool? noverify:kernel system_image
noverify:system_image — none (no effect)
rollback:kernel system_image
rollback:system_image — none (no effect)