hw‑verify

Open tools that prove security properties of hardware — and refuse rather than guess.

Constant-time RTL, masking gadgets, and bounds-check patches. Three checkers, one discipline: a verdict is earned or it is not given.

▶ Try it in your browser Install The tools

220 tests in ctbench alone two independent verifier implementations Apache-2.0 nothing uploaded

The thesis

Every tool here answers one question in a different domain:

Does a secret reach something an attacker can observe?

For RTL that observable is completion timing. For a masking gadget it is a probed wire. For a bounds check it is whether any violating input still gets through. Same shape, three domains — which is why these are one body of work rather than three coincidences.

The part that makes it worth using

Most analysis tools have two answers. These have three, and the third is the one that matters:

VerdictMeaningExit
CONSTANT_TIME No declared secret reaches the observable, within the analysable subset.0
LEAKY One does — and the reaching signals are named, so you can check.1
UNKNOWN No verdict. The analysis could not read the design and says so.2

A checker that skips what it cannot parse does not become vaguer — it deletes dependency edges, and a signal with no edges has an empty cone, and an empty cone contains no secrets, and no secrets reads as safe. That is a confident wrong answer in the dangerous direction, and it is the specific failure everything here is built to prevent.

UNKNOWN exits 2 rather than 1 so a CI job guarding only against "leaky" cannot be satisfied by "we could not tell".

Sixty seconds

pip install git+https://github.com/nickharris808/hw-verify@main

hw-verify ct check rtl/*.v --secret key        # timing leaks in RTL
hw-verify ct explain rtl/cmp.v --secret key    # ...and HOW the secret reaches it
hw-verify mask check dom_and                   # a masked gadget, probe by probe
hw-verify patch check                          # bounds-check patches, proved complete

A leak is not just flagged, it is traced:

$ hw-verify ct explain cmp_leaky.v
LEAKY — 'done' depends on x, y.

How each secret reaches it (shortest path first):

  x
  ├─ xr
  └─ done

That matters because the analysis over-approximates: it follows every dependency edge whether or not the path can be taken at run time. Without the path you cannot tell a real finding from a dead one, and you learn to distrust the tool. With it you read four signal names and decide.

The tools

ctbench

Constant-time RTL. A matched-pair benchmark — every safe design ships beside a leaky twin with an identical interface — plus a leaderboard that ranks soundness first. Reads Verilog, or a synthesised Yosys netlist for hierarchical designs.

ct-mask

First-order masking, by two certificates. Adds a uniformity certificate that certifies gadgets a dependence-only tool reports as leaky — and is honest that a first-order verdict is a statement about the first moment only.

patchproof

Does your bounds-check fix eliminate every violating input, or just the one you found? Emits a Farkas certificate a third party replays with integer arithmetic — no solver required.

patchproof-verify

That certificate, re-checked in Rust, sharing no code with the prover. Both implementations run the same 30 test vectors and a disagreement fails both builds. This is what makes "verify without trusting us" a property.

ct-audit-action

The RTL check on every pull request, as diff annotations and a job summary. Files that reach no verdict are counted separately and never rendered as a pass.

hw-verify-mcp

All three checkers as MCP tools, so an AI agent writing RTL gets a checker it cannot argue with. Every refusal carries a next_step, and the agent cannot set the verdict itself.

Datasets

hw-verify Verdicts: RTL fixtures, masking probes, patch certificates. What each design is.
hw-verify-paths Dependency graphs and witness paths. Why — reasoning traces, not labels.

What this does not do

Each tool ships a SCOPE.md stating its limits precisely. In summary: verdicts cover the modelled channel only — not power, EM, cache, or microarchitectural leakage. Secrets are a specification choice and are never inferred: guessing which inputs are sensitive would produce confident verdicts about the wrong property.

The commercial boundary. Everything here analyses a design you disclose in full. Proving a property to a third party who never receives the design — a verdict bound to a commitment of a design that stays hidden — is a different problem, and a commercial one. Nothing in these packages implements it.

Start here

Live demo Paste Verilog, get a verdict. No install, nothing uploaded.
Tutorial Find a leak, fix it, put the check in CI. Ten minutes.
Honest scope What a verdict proves, and the constructs the analysis refuses.
FAQ The objections people actually raise.
Install One package, three checkers.