Repository navigation
clazel-crypto: libcrux providers for TLS hashing, key schedule, records and X25519 (3.5f, part 1) - #19
Merged
Conversation
New crate clazel-crypto (Phase 3 item 3.5f), contracts only: - src/spec.rs: SHA-256, HMAC-SHA256, HKDF-SHA256, ChaCha20-Poly1305 and X25519 as uninterpreted spec functions. - src/axioms.rs: one external_body wrapper per libcrux call, each an `// AXIOM:` stating only libcrux's documented input/output types, plus the 16-octet tag length. Inputs over u32::MAX abort instead of returning unaxiomatised values. - docs/DEPENDENCIES.md: shipped rows for the 15 compiled libcrux packages (verified-hacl crates, their pre-verification support crates, rand) and the 50 locked under cfg(hax)/cfg(valgrind_ct_test) only; 19 existing rows raised to shipped since libcrux now reaches them. libcrux-hmac 0.0.9 requires libcrux-sha3 (pre-verification) and so libcrux-intrinsics and -platform: compiled, never called. Chosen on 2026-10-26 over writing HMAC/HKDF ourselves. The adapters implementing clazel-tls's provider traits follow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
src/provider.rs implements clazel-tls's provider traits with the axiom wrappers, checked by Verus against each trait's contract (13 verified, 0 errors): - Sha256Suite: schedule::crypto::Crypto (SHA-256, HKDF, HMAC); - ChaCha20Poly1305Factory / ChaCha20Poly1305: traffic::provider::Factory, KeyedAead and record::Aead, the 32-octet key a type invariant; - X25519: hello::key_exchange::KeyExchange. tests/known_answers.rs: the standards' own vectors through the traits (FIPS 180-2 B.1, RFC 4231 §4.2-4.3, RFC 5869 A.1/A.3, RFC 8439 §2.8.2 with tampering, RFC 7748 §6.1 and the all-zero shared secret). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
From the independent review of src/axioms.rs (sha256 f6f7249e…d508): - hkdf_expand could unwind: libcrux-hkdf's expand sizes a buffer with a wrapping u32 sum, so an info within 33 octets of u32::MAX slices out of range. The wrapper now aborts above MAX_INPUT first. - MAX_INPUT is 2^32 - 256, below every HACL* precondition (the tightest is HKDF-Expand's inner HMAC), and every wrapper checks each variable-length input against it explicitly, so the module doc's "every wrapper checks first" is now true. AXIOM lines updated, and open's notes the < 16-octet ciphertext case. - DEPENDENCIES: libcrux-hacl-rs has no compiled unsafe; its memzero is a no-op. - VERIFICATION.md TCB: names the translation toolchain, libcrux's unverified glue and its pre-verification support crates. axioms.rs changed, so it needs a fresh review. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Wording findings from the re-review of src/axioms.rs (sha256 c05d4642…42e3, all 9 axioms sound): spec.rs and the README now give MAX_INPUT (2^32 - 256) as the abort bound instead of u32::MAX, and the VERIFICATION.md TCB entry says the axioms state output lengths and failure cases as well as types. axioms.rs is unchanged, so the review still applies to it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Module doc (modelling choices: Verus proves the result, not the timing), signature, requires and ensures. The body is a stub returning false, so the postcondition deliberately does not verify in this commit (the contract is the part to review); the implementation and proof follow in the next commit. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
One pass over every index, ORing the XOR of each byte pair, returning acc == 0. Invariant: acc == 0 iff the first i bytes are equal; the bitwise facts (x ^ y == 0 iff x == y, p | q == 0 iff both zero) are by (bit_vector). No axioms. Tests: equal values, every single-byte difference, the empty pair, and a last-byte-only difference. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…tem 3.0) The xtask-checked sentence and unsafe count are unchanged; a sentence on the shipped dependencies (libc, libcrux) is appended. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
"100% safe Rust except clazel-sys" followed by "safe Rust throughout" contradicted itself; keep the checked sentence and state only the shipped dependencies. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
atiernan
added a commit
that referenced
this pull request
Oct 27, 2026
CI's mutation step fails a Verus crate with no mutations.json, and clazel-crypto had none (since #19). signature/examples.rs proves known answers about the spec's parsing and profile functions by evaluation: the key OIDs, the secp256r1 parameter decoded by clazel-der, pad32, the uncompressed point, Ecdsa-Sig-Value, the RSA moduli, the hash lengths and the small-order table against encodings computed from the curve. 31 mutations: 25 killed with certificates, 6 killed incidentally. Those six remove guards around the uninterpreted verifications, which no concrete example can evaluate; the exec proof and tests/signature.rs catch them, and they are not counted as coverage. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
atiernan
marked this pull request as ready for review
October 27, 2026 07:12
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #13. This is the first shipped cryptography: a new crate,
clazel-crypto, that instantiatesclazel-tls's provider traits with libcrux.clazel-tlsitself stays parameterised and free of axioms.Commits
329172bcontracts:src/spec.rsholds uninterpreted spec functions for SHA-256, HMAC-SHA256, HKDF-SHA256, ChaCha20-Poly1305 and X25519.src/axioms.rsis the trust boundary: oneexternal_bodywrapper per libcrux call, each with an// AXIOM:that states only libcrux's documented input and output types, plus one proof axiom for the 16-octet tag length. That makes 9 axioms. Inputs overu32::MAX, which libcrux refuses or panics on, abort the process instead of returning a value no axiom covers. The commit also adds thedocs/DEPENDENCIES.mdrows.ba1a820adapters and tests:src/provider.rsimplementsschedule::crypto::Crypto,traffic::provider::{Factory, KeyedAead}withrecord::Aead, andhello::key_exchange::KeyExchange, all checked by Verus against the traits' contracts. The 32-octet AEAD key is a type invariant.tests/known_answers.rsruns the standards' own vectors through the traits:Dependencies (decided 2026-10-26)
verified-haclcrates with nounsafe:libcrux-sha2,-hmac,-hkdf,-chacha20poly1305,-poly1305and-curve25519, all at exact0.0.xversions;pre-verificationsupport crates:libcrux-hacl-rs,-traits,-secretsand-macros, the last compile-time only;randandrand_core, whichlibcrux-traitsrequires but we never call.libcrux-hmac0.0.9 has a mandatory dependency onlibcrux-sha3(pre-verification) for its HMAC-SHA3 types. That brings inlibcrux-intrinsics(193unsafementions) andlibcrux-platform. Our HMAC-SHA256 path calls onlylibcrux-sha2. Alex chose libcrux's verified HMAC and HKDF over writing our own, since HACL* proves the timing independence that our own code would lack. Their rows say so.cfg(hax)orcfg(valgrind_ct_test), which our builds never set.shipped, because libcrux now reaches them through normal dependency edges; each row says whether that use is compiled. Thelibcrow also noteslibcrux-platform.Local results
clazel-crypto: 13 verified, 0 errors, fresh run.cargo test -p clazel-crypto: 8 passed, 0 failed.cargo fmt --checkare clean.cargo xtask checkreported STATIC CHECKS PASSED with 9 documented axioms.tier = 0andtarget-tier = 0, since it parses nothing.Needs, before it lands
A review ofDone, twice. Neither reviewer wrote the code, and both read it against the pinned libcrux sources.src/axioms.rsby a different sessionf6f7249e…d508, found thathkdf_expandcould panic on aninfowithin 33 octets ofu32::MAX, and that the input cap sat past HACL*'s preconditions. Both are fixed ina335ece.c05d4642…42e3(the current file), found all 9 axioms sound and every finding fixed. Its wording notes are fixed in51e67fd, which leavesaxioms.rsunchanged.MAX_INPUTwere recalled, not read, because the pinned crates ship only the extracted Rust.clazel-pkcs1), which comes with path validation;a335eceand51e67fd);finished_equal.🤖 Generated with Claude Code