2026-07-22 19:00:57 +00:00
|
|
|
|
# fips205-slhdsa-verified
|
|
|
|
|
|
|
|
|
|
|
|
Machine-checked verification campaign for the **SLH-DSA (FIPS 205) verify
|
|
|
|
|
|
path**, extracted from a pure-Rust implementation into Lean 4 via
|
|
|
|
|
|
Charon/Aeneas — the same pipeline, discipline, and honesty rules as the
|
|
|
|
|
|
four ed25519 campaigns (`dalek/anza/risc0/betrusted-ed25519-verified`).
|
|
|
|
|
|
|
phase 2: FIRST CERTIFICATE — chain (Algorithm 5) proven, button green
verification/check.sh is green (exit 0): 3 phases — model compiles,
proofs compile, axiom audit passes.
fips205.chain_free_loop_eq (Proofs/ChainSpec.lean): the extracted
chain_free loop = the explicit s-fold hash chain, hash address i..i+s-1.
Machine-checked, for the deployed monomorphic SHA2-128s verify path, that
there is no off-by-one loop bound, no wrong address field, no wrong
threading. #print axioms cone = EXACTLY [propext, Classical.choice,
Quot.sound, verify_mono.oracle.f] — kernel three + the one hash oracle,
zero transpiler plumbing (the u32 Step machinery was discharged earlier
with real defs). check.sh Phase 3 enforces cone subset of kernel-3 + the
five SHA-2 oracles, failing the build otherwise.
Proof structure (all lemmas axiom-clean, no sorry): u32_succ + fwd_succ
(the monadic u32 increment, checked against pinned rustc semantics);
loop_unfold_bind (one turn of the Aeneas loop fixpoint, closed by cases
because a hand-written match compiles to a non-defeq matcher);
hnext + hbody (iterator step and loop body as clean equations);
chain_step (one loop step = one fold step); chain_free_loop_eq
(induction, IH threaded under the opaque binds with bind_congr).
Both prior sorries closed. Certificate lives in Proofs/ (not drafts/);
the WIP draft is retired. check.sh committed as -F stdin per the
no-backticks-in-commit-messages rule.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 09:34:59 +00:00
|
|
|
|
## STATUS: FIRST CERTIFICATE PROVEN — Algorithm 5 (chain)
|
|
|
|
|
|
|
|
|
|
|
|
`verification/check.sh` is **green** (exit 0): the model compiles, the
|
|
|
|
|
|
proofs compile, and the axiom audit passes. **One certificate proven so
|
|
|
|
|
|
far:**
|
|
|
|
|
|
|
|
|
|
|
|
- **`fips205.chain_free_loop_eq`** (Algorithm 5, WOTS+ chaining): the
|
|
|
|
|
|
extracted `chain_free` loop equals the explicit s-fold hash chain, with
|
|
|
|
|
|
the hash address set to i, i+1, …, i+s−1 in turn. This rules out —
|
|
|
|
|
|
machine-checked, for the deployed monomorphic SHA2-128s verify path — an
|
|
|
|
|
|
off-by-one loop bound, a wrong address field, and wrong threading. Its
|
|
|
|
|
|
`#print axioms` cone is **exactly** `[propext, Classical.choice,
|
|
|
|
|
|
Quot.sound, verify_mono.oracle.f]` — the three kernel axioms plus the one
|
|
|
|
|
|
hash oracle it touches, and nothing else (no transpiler plumbing; the u32
|
|
|
|
|
|
range machinery was discharged with real definitions). check.sh Phase 3
|
|
|
|
|
|
fails the build if any certificate cone contains anything outside the
|
|
|
|
|
|
kernel three + the five documented SHA-2 oracles.
|
|
|
|
|
|
|
|
|
|
|
|
Foundations behind this (2026-07-22/23): the Aeneas-compat patch (additive
|
|
|
|
|
|
monomorphic verify module through a named oracle boundary; charon + aeneas
|
|
|
|
|
|
exit 0); the u32 range-loop de-plumbing (faithful `Step` defs vs pinned
|
|
|
|
|
|
rustc, axiom-clean); fidelity pinned by a differential test in the snapshot
|
|
|
|
|
|
(valid / corrupted / wrong-message).
|
|
|
|
|
|
|
|
|
|
|
|
The remaining layers (WOTS+ pk, XMSS path, hypertree, FORS, apex) are not
|
|
|
|
|
|
yet proven — the pyramid rises one certificate at a time, each audited to
|
|
|
|
|
|
the same boundary.
|
2026-07-22 19:00:57 +00:00
|
|
|
|
|
|
|
|
|
|
## Subject
|
|
|
|
|
|
|
|
|
|
|
|
- Upstream: `integritychain/fips205` — pure-Rust FIPS 205 (final standard,
|
|
|
|
|
|
2024-08-13), zero `unsafe`, `no_std`, const-generic parameterization,
|
|
|
|
|
|
modules mirroring the FIPS 205 algorithm structure.
|
|
|
|
|
|
- Pinned at upstream commit `30bac08580aa61f653e5436d1bbacb5ffac446c4`
|
|
|
|
|
|
(2025-09-01), snapshotted with full history at
|
|
|
|
|
|
`saymrwulf/fips205-source` (snapshot head `5dca0db`, whose single
|
|
|
|
|
|
deviation from verbatim is the removal of upstream CI workflows,
|
|
|
|
|
|
documented in that commit). Aeneas-compat patches will land in the
|
|
|
|
|
|
snapshot repo as transparent, individually-justified commits — never
|
|
|
|
|
|
upstream. **No affiliation with, and no changes proposed to, the
|
|
|
|
|
|
upstream project.**
|
|
|
|
|
|
- Parameter set: **SLH-DSA-SHA2-128s** first (the small-signature profile
|
|
|
|
|
|
deployed in the firmware/code-signing lane). The architecture
|
|
|
|
|
|
generalizes; each further parameter set is a separate claim (rigor
|
|
|
|
|
|
invariant R2).
|
|
|
|
|
|
|
|
|
|
|
|
## Scope
|
|
|
|
|
|
|
|
|
|
|
|
**Verify path only.** The extraction cone, mirroring FIPS 205's own
|
|
|
|
|
|
algorithm tree:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
slh_verify -> slh_verify_internal
|
|
|
|
|
|
-> fors_pk_from_sig
|
|
|
|
|
|
-> ht_verify -> xmss_pk_from_sig -> wots_pk_from_sig -> chain
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Key generation and signing are out of scope (trusted base), exactly as
|
2026-07-22 21:02:40 +00:00
|
|
|
|
ed25519 signing was. The five verify-path hash oracles (`h_msg, f, h,
|
|
|
|
|
|
t_l, t_len` — SHA-2 instantiations; `prf`/`prf_msg` are sign-side only
|
|
|
|
|
|
and never enter the cone) are opaque external models with written
|
2026-07-22 19:00:57 +00:00
|
|
|
|
justifications, kept outside every certificate's dependency cone
|
|
|
|
|
|
(honesty invariant H4); their semantics are the standing SHA-2 oracle
|
|
|
|
|
|
boundary documented in [TRUSTED-BASE.md](TRUSTED-BASE.md).
|
|
|
|
|
|
|
|
|
|
|
|
## Gate-0 record (2026-07-22)
|
|
|
|
|
|
|
|
|
|
|
|
Per TARGETS.md ("re-verify before use"), the subject was probed before
|
|
|
|
|
|
this repository was created:
|
|
|
|
|
|
|
|
|
|
|
|
- **Charon**: clean (`charon cargo --preset=aeneas`, roots at the verify
|
|
|
|
|
|
cone, `sha2/sha3/zeroize/rand_core` opaque, features
|
|
|
|
|
|
`slh_dsa_sha2_128s`) — LLBC produced, exit 0.
|
|
|
|
|
|
- **Aeneas**: translated the entire const-generic verify cone to Lean
|
|
|
|
|
|
definitions (`wots.chain` … `slh.slh_verify_internal` all generated),
|
|
|
|
|
|
with exactly **one obstruction class** (3 unique errors): the
|
|
|
|
|
|
`crate::hashers::Hashers` struct of plain **function pointers** cannot
|
|
|
|
|
|
be translated.
|
2026-07-22 20:21:19 +00:00
|
|
|
|
- **Phase 1 — DONE (2026-07-22)**: the Aeneas-compat patch landed in
|
|
|
|
|
|
`fips205-source` (snapshot `2d89ee3`): an additive monomorphic SHA2-128s
|
|
|
|
|
|
verify module (`src/verify_mono.rs`) whose hash suite is reached through
|
|
|
|
|
|
named free functions in `verify_mono::oracle` (marked opaque at the
|
|
|
|
|
|
Charon boundary) — the `sha512_*`-shim pattern. Two further compat
|
|
|
|
|
|
refinements: the message-digest input M' passes as a single `&[u8]`
|
|
|
|
|
|
(nested `&[&[u8]]` is untranslatable), and one `let-else` became the
|
|
|
|
|
|
`is_err`/`unwrap` idiom. `verification/extract.sh` now re-derives the
|
|
|
|
|
|
model from the mono root; charon + aeneas both exit 0, and
|
|
|
|
|
|
`verification/check.sh` compiles the result. The generic paths and all
|
|
|
|
|
|
twelve parameter sets are untouched (the only change to existing code is
|
|
|
|
|
|
two lines wiring the module).
|
2026-07-22 19:00:57 +00:00
|
|
|
|
|
|
|
|
|
|
## What will be claimed (when the button is green, not before)
|
|
|
|
|
|
|
|
|
|
|
|
One theorem per layer, each a statement about the **extracted** functions
|
2026-07-22 21:03:33 +00:00
|
|
|
|
(H3), compiled by `verification/check.sh` with a per-certificate
|
|
|
|
|
|
`#print axioms` audit (H1): chain semantics, WOTS+ pk recomputation,
|
|
|
|
|
|
XMSS path recomputation, hypertree acceptance, FORS pk recomputation,
|
|
|
|
|
|
and the apex — `slh_verify_internal` accepts iff the recomputed
|
|
|
|
|
|
hypertree root equals the pinned public-key root.
|
|
|
|
|
|
|
|
|
|
|
|
**The allowed axiom set, stated precisely:** unlike the ed25519 field and
|
|
|
|
|
|
scalar layers (whose cones are exactly `[propext, Classical.choice,
|
|
|
|
|
|
Quot.sound]`), the hash oracles permeate *every* SLH-DSA layer — `chain`
|
|
|
|
|
|
already calls `F`. So each certificate's cone may contain the three
|
|
|
|
|
|
kernel axioms **plus at most the five named oracles**
|
|
|
|
|
|
(`verify_mono.oracle.{h_msg, f, h, t_l, t_len}`) — and nothing else: the
|
|
|
|
|
|
transpiler-plumbing axioms currently in `FunsExternal.lean` must be
|
|
|
|
|
|
discharged before any certificate ships, and the audit fails the button
|
|
|
|
|
|
if any of them (or anything unlisted) appears in a cone.
|
2026-07-22 19:00:57 +00:00
|
|
|
|
|
|
|
|
|
|
## Discipline
|
|
|
|
|
|
|
|
|
|
|
|
Every Lean compile in this repository runs under `verification/lean-guard`
|
|
|
|
|
|
(memory-capped, machine-wide serialized). Extraction is reproducible from
|
|
|
|
|
|
the committed `extract.sh` against the pinned snapshot (R1). What cannot
|
|
|
|
|
|
be proven is named in [TRUSTED-BASE.md](TRUSTED-BASE.md), not hidden (H5).
|