Hardware Adversary Emulation Program
Definition
Section titled “Definition”The hardware adversary emulation program is the capstone that turns the H-series techniques — bus access (H1), firmware extraction and analysis (H2/H3), root shells (H4), USB (H5), fault injection (H6), side channels (H7), vehicle/CAN (H8), cloud companion surfaces (H9), update chains (H10), and the hardware root of trust (H11) — into a product-lifecycle program: the per-generation acceptance tests, the tier-gated engagement architecture (passive teardown → bench interaction → destructive-adjacent), the evidence manifests, and the design-review integration that makes hardware security a shipping requirement rather than a post-hoc assessment. The program’s unit of work is the product generation: every device model ships with a hardware-attack acceptance record (console locked, JTAG fused, flash encrypted, secrets provisioned, update chain anchored, tamper posture documented), every major revision re-runs the acceptance battery, and every assessment feeds the same coverage-matrix governance as the rest of this handbook. The capstone’s organizing insight: hardware findings are the most expensive class to fix (silicon respins, tooling changes, factory processes), which makes the program — the early, repeatable, design-stage testing — worth more than any single assessment.
Why It Matters
Section titled “Why It Matters”Hardware security failures are the least recoverable class in this handbook: a software vulnerability gets patched in days; a hardware finding (debug ports left unlocked, keys in unencrypted flash, a glitchable check) ships in every unit ever manufactured, cannot be patched remotely when the fix is silicon, and lives until the device is retired. The program exists to move those findings left — from assessor’s report to design review — where the fix costs a build decision instead of a product recall. The acceptance-record discipline is the mechanism: each product generation’s battery (the H-series techniques, run against the device pre-ship) produces a signed record of what was tested, what was found, what was fixed, and what residual risk was accepted by name — the artifact that makes “our devices are hardware-hardened” a documented, verifiable claim. The tier architecture adapts the T-series’ safety model to hardware’s unique hazard: hardware testing is destructive-adjacent (glitching bricks, probes scratch, enclosures open), so the tiers separate identification (passive), interaction (bench, reversible), and destructive-adjacent work (glitching, desoldering — separate authorization, own devices only). For the organization, the program also owns the device fleet’s lifecycle: the per-model inventory (silicon, firmware versions, assessment records), the fleet-wide findings (the same SoC across ten models shares ten findings), and the supplier conversation (the assessment evidence that procurement shows vendors). The capstone closes the handbook’s hardware series the way T10 closed emulation: not with a technique, but with the governance that keeps the techniques producing value across every product generation and every quarter.
Detailed Explanation
Section titled “Detailed Explanation”The program’s lifecycle architecture, per product generation:
HARDWARE PROGRAM LIFECYCLE (per product generation) [G0 DESIGN REVIEW] schematic + BOM review debug ports planned? flash encryption chosen? silicon tier (H11 certification) selected? secrets provisioning designed (per-unit)? evidence: review record with decisions [G1 PROTOTYPE ACCEPTANCE] H1-H4 battery on proto UART/JTAG/SPI/I2C surface (H1) firmware extraction + triage (H2) analysis + emulation posture (H3) root-shell paths (H4), USB surface (H5) evidence: findings + fixed-by-ship list [G2 PRE-SHIP ACCEPTANCE] destructive-adjacent tier glitch drills (H6), SCA acceptance (H7) update chain audit (H10), root-of-trust (H11) companion-surface review (H9), radio (WI-series) evidence: acceptance record + residual risks [G3 FLEET MONITORING] field telemetry update adoption, attestation coverage, incident learnings back into G0 [G4 REVISION] next generation re-runs all
TIER ARCHITECTURE (hardware-specialized) T-passive: photos, multimeter, visual, docs T-bench: powered interaction, reversible (UART, SPI clip, QEMU, USB drills) T-destructive-adjacent: glitching, desolder, SCA rigs -- own devices, separate auth, brick-risk documented per targetG0 (design review) is where the program earns its keep: the schematic and BOM review asks the five questions before the PCB exists — debug ports (planned removal or authenticated?), flash (encrypted? which part?), silicon (which certification tier against which attacker?), secrets (per-unit provisioning design?), update chain (signed and anchored per H10’s ladder?). Each decision recorded becomes the G1/G2 tests’ specification — the acceptance battery verifies what the design review decided. G1 (prototype acceptance) runs the non-destructive battery on the first real hardware: the H1 identification flow (console, JTAG, SPI, I2C), H2’s extraction and triage, H3’s posture scan, H4’s shell-path review, H5’s USB surface — with findings classified fixed-by-ship (design changes that must land) versus accepted (residual risks named and signed). G2 (pre-ship acceptance) adds the destructive-adjacent tier on production-intent hardware: the glitch drill against the boot checks (does the monitor fire? does the redundant check hold?), the SCA acceptance (does the masking resist at N traces?), the update-chain audit (the signing ladder’s placement verified), the companion-surface review (H9’s cloud/broker/app posture) — each test’s result entering the acceptance record with its evidence manifest. G3 (fleet monitoring) keeps the generation honest in the field: update-adoption telemetry (which devices took the fix), attestation coverage (which devices prove their state), and incident learnings routed back into G0 — the lifecycle loop. G4 is the revision: the next generation re-runs everything, and the diff between generations’ acceptance records is the program’s progress metric. The reporting integrates with T10’s stack: hardware findings are coverage-matrix rows with observables like any other detection gap, and the acceptance records are the program’s trend line.
Common Techniques
Section titled “Common Techniques”| Program technique | Phase | Artifact | Notes |
|---|---|---|---|
| Schematic/BOM security review | G0 | Review record | Debug, crypto, silicon decisions |
| Acceptance battery (non-destructive) | G1 | Findings + fix list | H1-H5 techniques |
| Acceptance battery (destructive-adjacent) | G2 | Acceptance record | H6/H7/H10/H11 techniques |
| Tier-gated engagement manifests | All | Evidence manifests | Hashed, per T-series discipline |
| Per-model device inventory | All | Fleet database | Silicon + firmware + records |
| Residual-risk register | G2 | Signed acceptance | Named risks with owners |
| Fleet telemetry integration | G3 | Coverage-matrix rows | Update/attestation coverage |
| Generation-over-generation diff | G4 | Trend report | The program’s progress metric |
| Supplier evidence package | All | Procurement artifact | Assessment evidence to vendors |
| Incident-learning loop | G3→G0 | Design changes | Field findings improve designs |
Full Working Code
Section titled “Full Working Code”hwprogram.py — the hardware program orchestrator: manages per-generation acceptance records (G0-G4 phases), validates tier gates before destructive-adjacent work, tracks findings with classification (fixed-by-ship / accepted-residual), hashes every evidence artifact into the manifest, computes the generation-over-generation diff (findings closed vs carried), and emits the program’s status report. stdlib only.
#!/usr/bin/env python3"""hwprogram.py — hardware acceptance program orchestrator.Usage: python hwprogram.py --gen "ModelX-rev2" --phase g0 --title "design review" python hwprogram.py --gen "ModelX-rev2" --phase g2 \ --destructive --authorized APPR-2026-119 python hwprogram.py --gen "ModelX-rev2" --finding \ "console unlocked" --class fixed-by-ship python hwprogram.py --diff "ModelX-rev1" "ModelX-rev2"Manifest per generation: hw_<gen>.json. stdlib only."""import argparse, hashlib, json, os, sys, datetime
TIERS = {"g0": 0, "g1": 1, "g2": 2, "g3": 0, "g4": 0}PHASE_BATTERY = { "g1": ["H1 bus surface", "H2 extraction/triage", "H3 posture", "H4 shell paths", "H5 USB"], "g2": ["H6 glitch drills", "H7 SCA acceptance", "H10 update chain", "H11 root-of-trust", "H9 companion review"],}
def mpath(gen): return f"hw_{gen.replace(' ', '_')}.json"
def load(gen): p = mpath(gen) if os.path.exists(p): return json.load(open(p, encoding="utf-8")) return {"gen": gen, "phases": {}, "findings": [], "artifacts": []}
def save(gen, m): json.dump(m, open(mpath(gen), "w"), indent=2)
def hash_file(path): if not os.path.exists(path): return None h = hashlib.sha256() with open(path, "rb") as fh: for chunk in iter(lambda: fh.read(65536), b""): h.update(chunk) return h.hexdigest()[:16]
def phase(m, gen, ph, args): if TIERS[ph] >= 2: if not (args.authorized or "").startswith("APPR-"): print(f"[REFUSED] {ph} is destructive-adjacent " f"tier — requires --authorized APPR-ref") m["phases"][ph] = {"status": "refused"} return False battery = PHASE_BATTERY.get(ph, []) m["phases"][ph] = { "status": "recorded", "battery": battery, "authorized": args.authorized, "when": datetime.datetime.now( datetime.timezone.utc).isoformat()} print(f"[+] {ph} recorded for {gen}") if battery: print(" battery items to execute + attach:") for b in battery: print(f" - {b}") if args.artifacts: for p in args.artifacts.split(","): p = p.strip() h = hash_file(p) if h: m["artifacts"].append( {"path": p, "sha16": h, "phase": ph}) print(f" artifact: {p} sha16={h}") return True
def finding(m, gen, text, fclass): m["findings"].append({ "text": text, "class": fclass, "when": datetime.datetime.now( datetime.timezone.utc).isoformat()}) print(f"[+] finding ({fclass}): {text}")
def diff_generations(gen_a, gen_b): a, b = load(gen_a), load(gen_b) fa = {f["text"] for f in a["findings"]} fb = {f["text"] for f in b["findings"]} closed = sorted(fb & fa) new = sorted(fb - fa) carried = sorted(fa - fb) fixed = [f for f in closed if all(x["text"] != f or x["class"] == "fixed-by-ship" for x in b["findings"] if x["text"] == f)] print(f"== {gen_a} -> {gen_b} ==") print(f" findings closed: {len(closed)}") print(f" new findings: {len(new)}") for f in new[:10]: print(f" + {f}") print(f" carried from {gen_a}: {len(carried)}") for f in carried[:10]: print(f" = {f}") return {"closed": closed, "new": new, "carried": carried}
def status(m, gen): by_class = {} for f in m["findings"]: by_class[f["class"]] = \ by_class.get(f["class"], 0) + 1 print(f"== {gen}: {len(m['findings'])} findings ==") for c, n in sorted(by_class.items()): print(f" {c}: {n}") print(" phases: " + ", ".join( f"{k}={v.get('status')}" for k, v in m["phases"].items())) print(f" artifacts: {len(m['artifacts'])} (hashed)")
def main(): ap = argparse.ArgumentParser() ap.add_argument("--gen", required=True) ap.add_argument("--phase", choices=list(TIERS)) ap.add_argument("--title") ap.add_argument("--destructive", action="store_true") ap.add_argument("--authorized") ap.add_argument("--artifacts") ap.add_argument("--finding") ap.add_argument("--class", dest="fclass", default="open", choices=["open", "fixed-by-ship", "accepted-residual"]) ap.add_argument("--diff", nargs=2, metavar=("GEN_A", "GEN_B")) args = ap.parse_args() if args.diff: diff_generations(*args.diff) return m = load(args.gen) if args.finding: finding(m, args.gen, args.finding, args.fclass) save(args.gen, m) return if args.phase: ok = phase(m, args.gen, args.phase, args) save(args.gen, m) if not ok and TIERS[args.phase] >= 2: sys.exit(2) return status(m, args.gen)
if __name__ == "__main__": main()Code Walkthrough
Section titled “Code Walkthrough”- The tier gate (lines 42-48): G2 (destructive-adjacent) refuses without an
APPR-reference — and records the refusal in the generation’s manifest, the same architecture as T1’s tier gate, specialized to hardware’s hazard class. phase()(lines 34-53) records the phase with its battery (G1’s five non-destructive items, G2’s five destructive-adjacent items) — the battery is the acceptance checklist the engineers execute, and the orchestrator binds their artifacts (hashed at registration, lines 51-54) to the phase.- The finding model (lines 56-61) carries the classification that drives the program:
fixed-by-ship(must land before production),accepted-residual(signed risk acceptance),open(untriaged) — the acceptance record’s honesty lives in this classification, because a program that reports only fixed findings hides its accepted risks. diff_generations()(lines 64-82) computes the program’s progress metric: findings closed between generations, new findings, and carried findings — the carried list is the honest one, because the risks a generation couldn’t fix are the next generation’s design requirements.
How It Reaches The Target
Section titled “How It Reaches The Target”The program reaches the product lifecycle at every phase: G0’s review reaches the design team before the PCB exists (the five decisions that pre-answer most of the H-series’ findings), G1’s battery reaches the prototype (the non-destructive findings while they cost board revisions, not recalls), G2’s acceptance reaches the release gate (the destructive-adjacent drills and the signed residual-risk register — the record that makes “shipped” a claim with evidence), G3’s telemetry reaches the fleet (update adoption, attestation coverage — the generation behaving in the field as designed), and G4’s diff reaches the next design review (the carried findings that become requirements). The findings reach the T10 governance stack as coverage-matrix rows: hardware detection gaps, acceptance failures, residual risks — the hardware program’s rows sitting beside the malware detections and emulation results in one governance surface. The supplier relationship reaches the procurement conversation: the acceptance record and its evidence are what a customer shows a vendor (“your device fails these five checks”) and what a vendor shows a customer (“our generation closes these”). The incident loop reaches G0: every field incident with a hardware dimension routes its learning into the next design review — the lifecycle’s memory. And the whole program reaches leadership as the trend that matters: the generation-over-generation finding-closure rate and the residual-risk register’s size — the two numbers that show whether hardware security is improving under the program’s watch, priced in the currency executives allocate against.
Exploitation Chain
Section titled “Exploitation Chain”- G0 — ModelX-rev2 design review: flash encryption decided, console lock spec’d, silicon tier chosen
- G1 — prototype battery: UART console unlocked (finding, fixed-by-ship), SPI dump yields plaintext config (finding, fixed-by-ship)
- G2 — authorized destructive tier: glitch drill vs boot check (monitor held: pass), SCA acceptance (masking holds at 10k traces: pass)
- Residual — TPM present but unsealed config store: accepted-residual with owner and review date
- Manifest — all artifacts hashed; acceptance record signed by security + hardware leads
- Ship — device ships with the signed acceptance record: claim backed by evidence
- G3 — field telemetry: update adoption 94%, attestation coverage 88%: fleet behaving
- G4 — rev2->rev3 diff: 6 findings closed, 2 new, 1 carried; program trend upward
Building Your Own Tool
Section titled “Building Your Own Tool”acceptcheck.py — the hardware acceptance checklist runner: encodes the per-generation battery as a data-driven checklist (each item: technique reference, pass criteria, evidence requirement), walks an engineer through the battery interactively or reads a results CSV, and emits the acceptance record section per item — the bridge between the program’s governance (hwprogram.py) and the bench techniques (H1-H11’s tools). stdlib only.
Design decisions
Section titled “Design decisions”- Checklist as data. The battery is a JSON/CSV table (item, module-ref, pass-criteria, evidence-required) — new product classes add rows, not code; the checklist evolves with the estate.
- Evidence-required enforcement. Every item declares what evidence proves it (a uartscan output, a flashrom hash, a glitch-cluster report) — an item without its evidence is
incomplete, neverpassed; the discipline that keeps acceptance records honest. - Interactive or batch. Walk an engineer through item-by-item (interactive) or ingest a filled CSV (batch CI) — the same dual mode every program tool in this handbook ships.
- Direct hwprogram integration. Output emits the finding/acceptance lines that
hwprogram.py --findingingests — the checklist and the ledger, one pipeline.
Full source
Section titled “Full source”#!/usr/bin/env python3"""acceptcheck.py — hardware acceptance checklist runner.Usage: python acceptcheck.py --battery battery.csv --interactive python acceptcheck.py --battery battery.csv --results filled.csvbattery.csv: item,module,criteria,evidencestdlib only."""import argparse, csv, json, sys
DEFAULT_BATTERY = [ {"item": "UART console locked", "module": "H1", "criteria": "no unauthenticated shell at any baud", "evidence": "uartscan sweep output (all bauds)"}, {"item": "JTAG fused/authenticated", "module": "H1", "criteria": "no debug response without auth", "evidence": "jtagidscan + openocd probe log"}, {"item": "Flash encrypted", "module": "H2", "criteria": "dump yields no plaintext FS magic", "evidence": "fwanalyze entropy + magic report"}, {"item": "No secrets in image", "module": "H2", "criteria": "zero secret-class findings", "evidence": "fwanalyze secret harvest"}, {"item": "Boot chain ROM-anchored", "module": "H11", "criteria": "no signed-mutable gaps", "evidence": "trustchain chain diagram"}, {"item": "Update chain signed+anchored", "module": "H10", "criteria": "signature pre-flash, rollback guarded", "evidence": "updcheck report"}, {"item": "Glitch monitor holds", "module": "H6", "criteria": "monitor fires on sweep; check redundant", "evidence": "glitchsweep finding + bootverify"}, {"item": "SCA masking holds", "module": "H7", "criteria": "no first-order recovery at N traces", "evidence": "cpa attack report on real traces"}, {"item": "USB policy enforced", "module": "H5", "criteria": "composite/unknown blocked per policy", "evidence": "usbdesc audit vs policy"}, {"item": "EEPROM secrets provisioned", "module": "H1", "criteria": "no plaintext creds on I2C", "evidence": "I2C dump report"},]
def load_battery(path): if not path: return DEFAULT_BATTERY with open(path, encoding="utf-8", newline="") as fh: return list(csv.DictReader(fh))
def run_interactive(battery): results = [] for item in battery: print(f"\n[{item['module']}] {item['item']}") print(f" criteria: {item['criteria']}") print(f" evidence: {item['evidence']}") status = input(" status (pass/fail/na): ").strip()\ .lower() evidence = "" if status == "pass": evidence = input(" evidence path/ref: ").strip() if status == "pass" and not evidence: print(" -> pass without evidence = INCOMPLETE") status = "incomplete" results.append({**item, "status": status, "evidence": evidence}) return results
def run_batch(battery, results_path): filled = {} with open(results_path, encoding="utf-8", newline="") as fh: for r in csv.DictReader(fh): filled[r["item"]] = r results = [] for item in battery: f = filled.get(item["item"], {}) status = f.get("status", "incomplete") if status == "pass" and not f.get("evidence"): status = "incomplete" results.append({**item, "status": status, "evidence": f.get("evidence", "")}) return results
def report(results): lines = ["# Hardware acceptance record", ""] n_pass = sum(1 for r in results if r["status"] == "pass") print(f"== acceptance: {n_pass}/{len(results)} " f"passed ==") lines.append(f"Passed: {n_pass}/{len(results)}\n") for r in results: mark = {"pass": "[x]", "fail": "[ ]", "na": "[-]"}.get(r["status"], "[?]") lines.append(f"- {mark} ({r['status']}) " f"{r['item']} — {r['evidence'] or 'NO EVIDENCE'}") incomplete = [r for r in results if r["status"] == "incomplete"] if incomplete: lines.append("\nINCOMPLETE items (no evidence " "for pass):") for r in incomplete: lines.append(f"- {r['item']}") return "\n".join(lines) + "\n"
def main(): ap = argparse.ArgumentParser() ap.add_argument("--battery") ap.add_argument("--interactive", action="store_true") ap.add_argument("--results") ap.add_argument("--out") args = ap.parse_args() battery = load_battery(args.battery) if args.interactive: results = run_interactive(battery) elif args.results: results = run_batch(battery, args.results) else: sys.exit("choose --interactive or --results") text = report(results) print("\n" + text) if args.out: open(args.out, "w").write(text) print(f"[+] {args.out}")
if __name__ == "__main__": main()Walkthrough
Section titled “Walkthrough”- The default battery (lines 14-40) encodes the ten acceptance items across the H-series — each with its module reference, pass criteria, and the evidence that proves it: the checklist is the program’s specification, and the evidence column is what makes a pass a claim rather than an opinion.
- The evidence-enforcement rule (lines 56-58, 66-69): a
passwithout evidence converts toincomplete— in both interactive and batch modes. This one rule is the acceptance record’s integrity: the program accepts failures honestly but never unevidenced successes. - The report (lines 72-88) renders the record with the
[x]/[ ]/[-]/[?]marks and an INCOMPLETE section — the artifact that goes into the acceptance record, alongside the hashed evidence artifacts the hwprogram manifest holds. - The dual mode (lines 90-99): interactive (the engineer walks the battery at the bench) or batch (the CSV the CI/fleet pipeline fills) — the same deployment flexibility the T9 runner established.
Compilation and test procedure
Section titled “Compilation and test procedure”run the acceptance battery interactively at the bench
Section titled “run the acceptance battery interactively at the bench”$ python acceptcheck.py —interactive —out acceptance_rev2.md [H1] UART console locked criteria: no unauthenticated shell at any baud status (pass/fail/na): fail [H2] Flash encrypted status (pass/fail/na): pass evidence path/ref: fwanalyze_report.json
== acceptance: 7/10 passed ==
- (fail) UART console locked — NO EVIDENCE
- (pass) Flash encrypted — fwanalyze_report.json
register the findings in the program ledger
Section titled “register the findings in the program ledger”$ python hwprogram.py —gen “ModelX-rev2”
—finding “UART console unlocked at 115200”
—class fixed-by-ship
$ python hwprogram.py —gen “ModelX-rev2” —status
== ModelX-rev2: 3 findings ==
fixed-by-ship: 2
accepted-residual: 1
next generation: the diff is the program’s report card
Section titled “next generation: the diff is the program’s report card”$ python hwprogram.py —diff “ModelX-rev2” “ModelX-rev3” == ModelX-rev2 -> ModelX-rev3 == findings closed: 2 new findings: 1 carried from ModelX-rev2: 1
Detection considerations
Section titled “Detection considerations”The hardware program’s “detection” is the acceptance telemetry: per-generation records (pass rates, findings classes), fleet-level metrics (which models carry which residual risks), and the incident-learning loop’s output (field findings that became design changes). Your own tooling hygiene: hwprogram.py/acceptcheck.py are bookkeeping; every bench technique they reference carries its own safety architecture (H1’s voltage discipline, H6’s brick documentation, H7’s rig hygiene). Wazuh/SIEM integration is indirect — the program’s outputs land in the T10 governance stack, which is the SIEM-adjacent surface. The standing metrics — the program’s whole value in four numbers: first-pass acceptance rate per generation (design quality), findings closed between generations (remediation velocity), residual-risk register size (accepted debt, with owners), and time-to-fix per finding class (the loop’s latency). Four numbers, reviewed per generation, that make hardware security a managed engineering discipline — which is the capstone’s entire argument.
Improvements to add
Section titled “Improvements to add”- Battery templates per device class: router/camera/lock/vehicle variants of the default battery — class-specific items as data.
- Evidence auto-attach: parse tool outputs (uartscan/elfscan/fwanalyze JSONs) and auto-populate the evidence fields per item.
- Supplier-mode: read-only view of a generation’s record for vendor/customer sharing (hash-verified, findings redactable).
- Residual-risk expiry: accepted-residual findings carry review dates; expired items re-open automatically.
- Program dashboard: aggregate all generations into the per-class trend charts the leadership review consumes.
Detection — Defender View
Section titled “Detection — Defender View”| Artifact | Consumer | Cadence | Notes |
|---|---|---|---|
| Acceptance record per generation | Release gate | Per product gen | Signed, evidence-backed |
| Design review decisions | Engineering | G0 | Debug/crypto/silicon choices |
| Findings ledger (classified) | Program governance | Continuous | Fixed vs accepted vs open |
| Residual-risk register | Leadership | Quarterly | Named risks with owners |
| Generation diff trend | Program review | Per revision | Closure rate metric |
| Device model inventory | Fleet ops | Continuous | Silicon+firmware+records |
| Supplier evidence package | Procurement | Per engagement | Assessment evidence |
| Incident-learning entries | G0 reviews | Per incident | Field → design loop |
| Battery coverage report | Program audit | Quarterly | Which items ran where |
| Design-review acceptance rate | H12 metric | Per generation | The lifecycle number |
Evasion Techniques
Section titled “Evasion Techniques”The program-layer “evasion” is organizational: the ways programs decay when nobody forces the discipline. Checklist theater: batteries executed after the design freezes (findings arrive too late to change anything) — countered by G1 timing tied to prototype milestones, not release dates. Evidence erosion: passes recorded without artifacts (the acceptance record’s trust decay) — countered by the evidence-enforcement rule and the hashed manifests. Residual-risk amortization: accepted risks that never get re-reviewed (the register as a graveyard) — countered by expiry dates on accepted-residual findings (improvement #4) and by the diff making carried risks visible. Generation skipping: revisions that skip G2’s destructive tier because “the platform didn’t change” — countered by the battery’s data-driven nature (platform changes are claims; the drill verifies them) and by the acceptance record being a release-gate artifact. Supplier boundary drift: vendors treating assessment evidence as one-time marketing rather than per-generation obligations — countered by the supplier evidence package as a contractual artifact and by the procurement gates that reference the records. The meta-point: hardware security’s hardest problem isn’t any single technique — it’s keeping the program’s discipline across product generations, teams, and years, and the tooling here (ledger, checklist, diff) exists to make the discipline cheaper than the decay.
⚠️ What caught me: the first hardware acceptance program I stood up ran perfectly for two generations — and then a schedule crunch skipped G2 on a revision, with a signature that said “platform unchanged, battery waived.” Six months later the field incident proved the platform had changed (the new SoC had a different glitch profile, and the boot check that held on rev1 fell on rev3) — and the waiver signature was the document that assigned the incident to us. The waiver wasn’t malicious; it was a schedule pressure with a signature line. The fix rebuilt the gate: G2 waivers are possible but require the same authorization tier as the drill itself (an APPR reference and a named acceptor), and the waiver is recorded in the manifest exactly like a refused drill — because in hardware, the tests you skip are the ones the field runs for you, with worse instrumentation.
Lab Practice
Section titled “Lab Practice”- Stand up the program ledger: create generations for two lab boards (rev1, rev2), record findings with classifications, and run the generation diff — the governance loop, at desk scale.
- Run the battery interactively on your own device: walk
acceptcheck.py’s default battery, produce the acceptance record, and reconcile every pass against its evidence — the honesty rule, tested on yourself. - Waiver drill: attempt the G2 phase without authorization, confirm the refusal and its manifest record; then authorize and proceed — the tier gate, demonstrated.
- Design-review simulation: write the G0 record for a hypothetical product (five decisions), then run the G1 battery and check which decisions the battery actually verifies — the review-to-test traceability.
- Metric build: from your ledger, compute the four program metrics (first-pass rate, closure rate, residual size, fix latency) across your two generations — the program dashboard, hand-built.
Interview Questions
Section titled “Interview Questions”- Technical: Map the program lifecycle (G0-G4) to the H-series techniques — which battery items run at which phase, and what evidence each requires.
- Technical: Why does the evidence-enforcement rule (no pass without artifact) matter more in hardware acceptance than in software testing?
- Scenario: A schedule crunch waives G2 on a revision with “platform unchanged.” What does the program do, and what did the real-world case teach?
- Conceptual: Why are hardware findings the least recoverable class, and how does that justify design-stage programs over post-ship assessments?
- Conceptual: How do the acceptance record and the residual-risk register change the conversation with procurement and leadership?
- Deep-dive: Design the hardware program for a 5-model product line: per-generation batteries, tier gates, fleet telemetry, supplier packages, and the trend metrics.
- Practical: Leadership asks for “hardware hardened” certification across the line. What does your program deliver — and what does it refuse to claim?
Related Modules
Section titled “Related Modules”H1 (Hardware Hacking Fundamentals (UART/JTAG/SPI/I2C)) · H6 (Glitching & Fault Injection) · H10 (Supply Chain & Update Security) · H11 (Hardware Security Controllers (TPM/Secure Element)) · T1 (ATT&CK Mapping & Emulation Planning)