mirror of
https://github.com/saymrwulf/fips205-slhdsa-verified.git
synced 2026-09-03 19:53:49 +00:00
Addresses the round-2 reviewer punch-list. No theorem statement, proof term,
or fold definition changed; the eleven cones are unchanged (independent
collectAxioms dump in verification/RECORDED-RUN.md).
AUDIT GATE (both reviewers, the critical one)
- Retire the bash #print-axioms text parser (fail-open on empty/truncated
reports, and only a SUBSET check). Replace with verification/Proofs/Audit.lean:
reads each certificate's cone from the kernel via collectAxioms and asserts
EXACT set equality against its expected boundary. Extra axiom, dropped
oracle, renamed/deleted cert, or an axiom/opaque sham each throw -> non-zero
Lean exit. No text to misparse; nothing fails open. check.sh Phase 3 now just
compiles it (and still requires the explicit PASSED line).
- check-selftest.sh rewritten to attack the new gate: dead-file, smuggled extra
axiom (named), dropped-oracle (subset would pass, exact must not), and a
vanished certificate (the collectAxioms-returns-[] trap). All four rejected.
REPRODUCIBILITY (GPT B1.4 / B1.5)
- extract.sh refuses a wrong-commit or dirty source tree (fail-closed), takes
an optional source-path arg, and pins the source commit.
- verification/PROVENANCE.json: single machine-readable pin set (source +
charon + aeneas commits/channel + lean + ocaml) with generated-file sha256.
- Re-running extract.sh reproduces gen/SlhVerify/{Types,Funs}.lean
byte-identically (companion fips205-source commit adds Cargo.lock +
rust-toolchain.toml; verified not to perturb the model).
DOC HONESTY (both reviewers)
- README: fix the self-contradiction (apex "not yet proven" trailer vs the
proven apex), the false "oracles kept OUTSIDE every cone" (they are INSIDE,
by design), "deployed monomorphic path" and "semantics-identical for every
parameter set" overclaims, "only two lines changed", stale snapshot head;
retitle the stale future-tense "what will be claimed" section.
- TRUSTED-BASE: drop "nothing proven yet"; add base_2b-inner and deployment-
bridge non-claims explicitly; current pin.
- ChainSpec header: "deployed monomorphic path" -> private verify_mono facade
(comment only).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
97 lines
5.3 KiB
Text
97 lines
5.3 KiB
Text
/- ──────────────────────────────────────────────────────────────────────────────
|
||
Proofs/Audit.lean — the axiom-cone audit, performed INSIDE Lean.
|
||
|
||
Round-2 external review (2026-07-24) showed the bash `#print axioms` text
|
||
parser was still fragile: it fail-OPENED on an empty `[]` or a truncated
|
||
(missing-`]`) report, and it only subset-checked (a *removed* oracle
|
||
dependency would pass unnoticed). This file removes text parsing entirely.
|
||
|
||
`collectAxioms` reads the kernel's own axiom set for each certificate. We
|
||
assert, for every one of the eleven:
|
||
|
||
· the certificate EXISTS and is a `theorem` (not an axiom/opaque sham,
|
||
not a renamed/deleted name — `collectAxioms` returns `#[]` for a
|
||
missing name, so existence is checked explicitly, fail-closed);
|
||
· its cone equals its EXPECTED set EXACTLY — extras (a smuggled axiom)
|
||
AND missing (a silently dropped oracle dependency) both fail.
|
||
|
||
Any mismatch is a `throwError`, i.e. a Lean elaboration error → non-zero
|
||
`lean` exit. There is no text to misparse and nothing fails open. This is
|
||
the single source of the axiom claim; check.sh Phase 3 just compiles it.
|
||
────────────────────────────────────────────────────────────────────────────── -/
|
||
import Proofs.ChainSpec
|
||
import Proofs.WotsSpec
|
||
import Proofs.XmssSpec
|
||
import Proofs.HtSpec
|
||
import Proofs.ForsInnerSpec
|
||
import Proofs.ForsOuterSpec
|
||
import Proofs.InputPrepSpec
|
||
import Proofs.ApexSpec
|
||
open Lean Elab Command
|
||
|
||
namespace SlhVerify.Audit
|
||
|
||
/-- Lean's three kernel axioms — permitted in every cone. -/
|
||
def kernel3 : List Name := [`propext, `Classical.choice, `Quot.sound]
|
||
|
||
/-- The five SHA-2 verify-path hash oracles — the documented cryptographic
|
||
boundary (TRUSTED-BASE.md). No other axiom may appear anywhere. -/
|
||
def oracleF : Name := `verify_mono.oracle.f
|
||
def oracleH : Name := `verify_mono.oracle.h
|
||
def oracleTL : Name := `verify_mono.oracle.t_l
|
||
def oracleTLen : Name := `verify_mono.oracle.t_len
|
||
def oracleHMsg : Name := `verify_mono.oracle.h_msg
|
||
|
||
/-- The entire allowed boundary: nothing outside this set is permitted in any
|
||
certificate cone, and the expected table below may reference nothing else. -/
|
||
def allowedBoundary : List Name :=
|
||
kernel3 ++ [oracleF, oracleH, oracleTL, oracleTLen, oracleHMsg]
|
||
|
||
/-- EXACT expected cone per certificate. Ground truth captured 2026-07-24 via
|
||
`collectAxioms` (Probe.lean) and cross-checked against both round-1
|
||
reviewers' independent reconstructions. Each entry is asserted for SET
|
||
EQUALITY, so this table is a load-bearing specification of the boundary:
|
||
changing a proof so it drops an oracle, or adds one, breaks the audit. -/
|
||
def expectedCones : List (Name × List Name) :=
|
||
[ (`fips205.chain_free_loop_eq, kernel3 ++ [oracleF]),
|
||
(`fips205.wots_loop1_eq, kernel3 ++ [oracleF]),
|
||
(`fips205.xmss_loop_eq, kernel3 ++ [oracleH]),
|
||
(`fips205.ht_loop_eq, kernel3 ++ [oracleF, oracleH, oracleTL]),
|
||
(`fips205.fors_inner_loop_eq, kernel3 ++ [oracleH]),
|
||
(`fips205.fors_outer_loop_eq, kernel3 ++ [oracleF, oracleH]),
|
||
(`fips205.to_int_loop_eq, kernel3),
|
||
(`fips205.to_byte_loop_eq, kernel3),
|
||
(`fips205.wots_csum_loop_eq, kernel3),
|
||
(`fips205.base2b_outer_loop_eq, kernel3),
|
||
(`fips205.slh_verify_128s_accepts_iff, kernel3 ++ [oracleF, oracleH, oracleTL, oracleTLen, oracleHMsg]) ]
|
||
|
||
elab "auditCones" : command => do
|
||
let env ← getEnv
|
||
-- (0) the expected table itself must stay within the boundary — guards a typo
|
||
-- in this file from silently widening what "allowed" means.
|
||
for (cert, expected) in expectedCones do
|
||
for a in expected do
|
||
unless allowedBoundary.contains a do
|
||
throwError "audit table references non-boundary axiom {a} for {cert}"
|
||
-- (1) per certificate: exists ∧ is a theorem ∧ cone == expected set exactly.
|
||
let mut errs : Array String := #[]
|
||
for (cert, expected) in expectedCones do
|
||
match env.find? cert with
|
||
| none => errs := errs.push s!"{cert}: NOT FOUND (renamed/deleted?)"
|
||
| some (.thmInfo _) =>
|
||
let got := (← collectAxioms cert).toList
|
||
let extras := got.filter (fun a => !expected.contains a)
|
||
let missing := expected.filter (fun a => !got.contains a)
|
||
unless extras.isEmpty && missing.isEmpty do
|
||
errs := errs.push s!"{cert}: extra={extras} missing={missing}"
|
||
| some (.axiomInfo _) => errs := errs.push s!"{cert}: is an AXIOM, not a proven theorem"
|
||
| some (.opaqueInfo _) => errs := errs.push s!"{cert}: is OPAQUE, not a proven theorem"
|
||
| some _ => errs := errs.push s!"{cert}: not a theorem"
|
||
unless errs.isEmpty do
|
||
throwError "EXACT-CONE AUDIT FAILED (fail-closed):\n{String.intercalate "\n" errs.toList}"
|
||
logInfo s!"exact-cone audit PASSED: {expectedCones.length} certificates, each cone == its expected boundary set (kernel-3 + only the named SHA-2 oracles)"
|
||
|
||
end SlhVerify.Audit
|
||
|
||
open SlhVerify.Audit in
|
||
auditCones
|