Skip to content

clazel-p384: field arithmetic over fiat-crypto behind six axioms (3.5h, PR2), tier 0 - #23

Merged
atiernan merged 4 commits into
phase3/p384-specfrom
phase3/p384-field
Oct 27, 2026
Merged

atiernan merged 4 commits into
phase3/p384-specfrom
phase3/p384-field

Conversation

@atiernan

Copy link
Copy Markdown
Member

PR2 of P-384 ECDSA verification (3.5h): the field arithmetic for clazel-p384, built on fiat-crypto =0.3.0 behind six axioms. It is stacked on #22, and the crate stays at tier 0.

Commits

  • dcd344b spec: the field contracts (field/spec.rs, field/contract.rs), committed before any code.

  • 26c4e5e: src/axioms.rs, holding p_mul, p_add, p_sub, n_mul, n_add and n_sub, one per fiat call. Also the fiat-crypto dependency, its DEPENDENCIES.md row (shipped) and the VERIFICATION.md TCB entry.

  • 8b1d2d1: field/fe.rs and field/lemmas.rs, proven against the contracts over the axioms:

    • an Fe type whose invariant keeps each value below its modulus;
    • our own big-endian octet conversion with its range check;
    • Montgomery conversion as mul by R² and by 1;
    • square-and-multiply pow;
    • inv, proven equal to the spec's checked inv.

    Plus tests/field.rs, which uses known answers computed in Python.

  • A merge of clazel-p384: ECDSA P-384 verification spec (3.5h, PR1), tier 0 #22, bringing in the spec's mutations.json, plus the TCB wording below.

Axioms

Each axiom's requires is fiat's printed precondition, 0 ≤ eval arg < m. Each ensures is fiat's printed postcondition, quoted verbatim in its doc comment.

Independent review. A fresh session reviewed axioms.rs at SHA-256 e9ee88f170b0f0565a44a016c66b9b94fe7371ca50acd1efe61ea6289dbfa4e3. Verdict: all six are sound.

  • The calls: each calls the right function, with the arguments in the right order and p and n never mixed.
  • The contracts: each requires and ensures matches fiat exactly. Both inverse literals and both R² literals were checked against the moduli.
  • No panics: none is possible, including with overflow checks on. Every fiat operation was checked.
  • Call sites: the Fe invariant discharges every one.

The review found one gap in the TCB text. It now also names:

  • the printed pre/postcondition comments, which the axioms copy;
  • rustc's i128, u64 and i8 arithmetic;
  • that the published crate is the synthesizer's output.

It also no longer says the unwritten ECDSA code is proven.

Checks done

  • Verus: 84 verified, 0 errors, from a clean cache.
  • Mutations: cargo xtask mutate clazel-p384 gives 26 of 26 killed with certificates.
  • Tests and lints: cargo test passes 7 tests, and clippy and fmt are clean.
  • cargo xtask check: passes, with 18 documented axioms (12 in clazel-crypto, 6 here).

Not yet

  • No point code and no verify.
  • No mutations of the field code.
  • No conformance suite or independent transcription.

CI has not run yet.

🤖 Generated with Claude Code

atiernan and others added 4 commits October 27, 2026 12:19
The meaning of a field element (six Montgomery-domain limbs; fiat's eval and
from_montgomery; mont(x) = x R mod m) and the ensures of every executable
field function: add, sub, mul, one, equals, from_octets, to_octets, pow and
inv, where inv refines spec::inv. Spec and contracts only; no code.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…d mod n)

fiat-crypto =0.3.0 becomes a shipped dependency (default features off).
Six external_body wrappers, one per fiat function, each with a // AXIOM:
and an ensures that copies the postcondition printed above the function.
DEPENDENCIES.md gains the row; the crypto line of the VERIFICATION.md TCB
gains fiat-crypto.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… contracts

Fe is a residue mod p or n as six Montgomery-domain limbs with a type
invariant (value below the modulus). Proven over the six axioms: conversion
into the Montgomery domain (mul by R^2) and out of it (mul by 1), our own
big-endian octet-string conversions with the range check, equality, pow by
square-and-multiply over a 48-octet exponent, and inv (pow m-2 with the
check a w = 1) against spec::inv. tests/field.rs checks add, sub, mul, inv,
pow and the octet conversions against Python-computed known answers for both
moduli. The crate stays at tier 0.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Brings in the spec's mutations.json. The README keeps both status notes.
VERIFICATION.md's fiat-crypto TCB entry now also names the printed
pre/postcondition comments, rustc's i128/u64/i8 arithmetic and the
published crate being the synthesizer's output (the axiom review's one
finding), and no longer says the unwritten ECDSA code is proven.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@atiernan
atiernan added this pull request to stack #26 October 27, 2026 15:57
@atiernan
atiernan marked this pull request as ready for review October 27, 2026 15:58
@atiernan
atiernan merged commit 7ceed35 into phase3/tls-handover Oct 27, 2026
29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant