A safe-cracker in an old film presses an ear to the dial and listens for the tumblers. She never reads the
combination off a label — she infers it from a physical side effect of the lock doing its job. That
is a side channel, and modern processors are riddled with them.
The unifying idea: isolation is a software abstraction, but the hardware underneath is shared, and shared hardware carries whispers between its users. We will look at timing side channels, at Rowhammer (where the leak becomes an active attack on memory), at how to write code that keeps its mouth shut, and at the deep tension this all reveals between speed and secrecy.
The most productive side channel is the cache, because a hit and a miss differ by an order of magnitude in latency, and that timing is measurable from another program. If a victim's memory access pattern depends on a secret — say, an AES table lookup indexed by a key byte — then which cache lines it touches is the secret, exposed to anyone who can watch the cache. Three classic techniques harvest it:
| Technique | Attacker's move | What the timing reveals |
|---|---|---|
| Flush+Reload | flush a shared line, later time reloading it | the victim accessed that exact line (fast reload) |
| Prime+Probe | fill a cache set with your own data, later re-time it | the victim evicted one of your lines (a slot they used) |
| Evict+Time | evict a line, then time the victim as a whole | whether the victim needed that line this run |
Flush+Reload needs shared memory (e.g. a shared library, or deduplicated cloud pages) and is precise; Prime+Probe needs no sharing and works across virtual-machine boundaries, which is what makes it a cloud-tenant's nightmare. Both have been used to lift full cryptographic keys from a co-located victim.
The defence at the software layer is a discipline called constant-time programming. The name is slightly misleading — it is not about being fast, but about making execution independent of secret data. Two rules: a secret must never decide which way a branch goes (branch timing and predictor state leak it), and a secret must never decide which memory address is touched (cache state leaks it). Consider the archetypal bug — a password check that bails out at the first wrong byte:
The early-exit version leaks the secret one byte at a time: guess the first byte until the check takes a
touch longer, lock it in, move to the second. This is exactly how naive
Side channels leak information; Rowhammer goes further and corrupts it. As DRAM
cells shrank, adjacent rows became so tightly coupled that repeatedly activating one row — "hammering" it
thousands of times before the memory's periodic refresh — leaks enough charge to flip a bit in a
neighbouring row you never had permission to touch. It is a
The consequences are startling: by hammering carefully chosen rows an attacker can flip a bit in a page-table
entry and hand themselves kernel privileges, or flip a bit in another tenant's data — all without any
software bug in the victim. Defences include Target Row Refresh (TRR), doubling the refresh
rate, and — coming full circle —
Step back and a pattern emerges that will outlive any single vulnerability. Every performance optimisation in this course is a form of sharing or prediction, and every act of sharing or prediction is a potential side channel. Caches share fast memory between contexts — cache-timing attacks. Speculation predicts the future and acts early — Spectre. Simultaneous multithreading shares execution ports between two threads — port-contention attacks. Shrinking DRAM shares charge between rows — Rowhammer. Shared page deduplication saves RAM — and enables Flush+Reload.
Perfect isolation would mean partitioning every resource so no two security domains ever share state — which throws away most of the speed those shared resources bought. So architects live on a spectrum: partition the most sensitive resources (per-domain cache ways, flushing predictors on context switch, disabling deduplication for secrets) and accept a measured performance cost, rather than chase an unattainable absolute. Security, like reliability, is not a feature you bolt on — it is a budget you spend against performance, deliberately.
Long before Spectre, in 2005, cryptographer Daniel J. Bernstein demonstrated a full AES key
recovery from cache timing on a real server, exploiting the fact that AES's software implementation
used secret-key-dependent table lookups. Around the same time Osvik, Shamir and Tromer formalised
Prime+Probe. The response reshaped cryptography: modern ciphers are designed to be
implemented constant-time, AES got hardware instructions (
Two misconceptions sink beginners. First, constant-time is not about speed: a constant-time routine may be slower than a branchy one — the point is that its timing (and memory-access pattern) does not vary with the secret. Making code faster can make it less secure if the speed-up adds a secret-dependent shortcut. Second, you cannot fix a cache side channel by "flushing the cache now and then": the leak is in the difference between a hit and a miss during the sensitive operation, and an attacker sets the timing of their own probes. The real remedies are architectural (partitioning) or algorithmic (data-oblivious code), not a periodic cache wipe.