Skip to content

SHA-224 on x86-64, x86, AArch64 and ARMv7: vg_sha224_init and the Rust API - #454

Merged
alex merged 9 commits into
mainfrom
claude/gifted-cannon-gdzq6w
Oct 1, 2026
Merged

alex merged 9 commits into
mainfrom
claude/gifted-cannon-gdzq6w

Conversation

@alex

@alex alex commented Oct 1, 2026 •

Copy link
Copy Markdown
Member

Third of the SHA-224 PRs: the implementation. The vectors (#446) and the spec (#452) are merged, and main is merged into this branch. It changes no files under Spec/ or TCB/.

SHA-224 only needs an init of its own. vg_sha224_init stores SHA-224's initial hash value, and SHA-256's update and finalize do the rest (as of #452, their contracts hold for any initial hash value). Every existing implementation of those is reused: SHA-NI and AVX2 on x86-64, and the SHA2 extension on AArch64.

Lean

  • Impl: on each target, init becomes initWith iv, with init := initWith H0 and init224 := initWith H0_224. The emitted vg_sha256_init is byte-identical; the only change to src/asm/ is the new vg_sha224_init, one per target.
  • Proofs: each target's init proof now holds for any iv.
    • The x86-64 proof needed one new lemma (setWidth 32 (setWidth 64 x) = x); on the other targets the proof was already written over word x off.
    • Some checks can only be evaluated by the kernel on literal code: the taint analysis on every target, and on x86-64 that the code never loads MXCSR. These are passed in as hypotheses and discharged for each of the two instances.
    • The per-target init contracts take iv.
  • Registration: new files Artifacts/Sha224/{X86_64,X86,AArch64,Arm}.lean, each made from Spec.Sha256.init224Api.
  • Test: VerifiedGarbageTest/Sha224.lean checks Spec.Sha256.sha224 against two of the CAVP short-message vectors at build time, like the SHA-256 test. I checked that it fails if one word of H0_224 is wrong.

Rust

  • hashes::sha224::Sha224: a new module with its own #[cfg], built with streaming_hash! and its own Sha224Backend.
    • The backend has SHA-256's variants and dispatches to SHA-256's update and finalize.
    • Its select test checks, for every feature set, that it picks the same implementation as Sha256Backend (matching exhaustively).
    • There are also unit tests for incremental updates and HashFunction.
  • tests/cavp/sha224.rs: all 65 short and 64 long messages, plus the Monte Carlo test.
  • bench/benches/primitives/sha224.rs: compared against OpenSSL's SHA-224; USES is sha224 and sha256.
  • The README table is regenerated: SHA-224 is ✅ on all four architectures, with the same CPU-feature notes as SHA-256.

Checks run locally (after merging main)

  • lake build (5648 jobs) and lake env lean --run Emit.lean --check
  • ci/check_lean_imports.py, check_lean_speed.py, check_vectors.py, check_arch_gates.py, check_variants.py, check_mcdt.py, algorithms_table.py --check
  • cargo fmt --check and cargo clippy --all-targets -- -D warnings, on x86-64 and for the i686, aarch64 and armv7 targets
  • cargo test on x86-64. Before this merge I also ran it with VG_CPU_FEATURES=avx,avx2,bmi1,bmi2 and with VG_CPU_FEATURES=none; after it, the full suite and the SHA-224 vectors pass.
  • cargo check --benches in bench/ (before this merge)

I couldn't run the Rust tests on the other architectures locally; CI covers them.

🤖 Generated with Claude Code

https://claude.ai/code/session_01HDRg9k22FbCYq3TnciKvwG

claude added 5 commits October 1, 2026 11:33
…ance

SHA224ShortMsg.rsp, SHA224LongMsg.rsp and SHA224Monte.rsp, byte for byte
from the same shabytetestvectors.zip as the other SHA vectors (same
SHA-256), in a directory and source file of their own.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HDRg9k22FbCYq3TnciKvwG
…HA source

They come from the same download, so they belong to its source file
rather than a second one with the same URL and hash.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HDRg9k22FbCYq3TnciKvwG
… value

FIPS 180-4's SHA-224 is SHA-256 from another initial hash value (§5.3.2),
truncated to 28 bytes (§6.3). As for the SHA-512 family, it shares the
streaming state and vg_sha256_update/vg_sha256_finalize, and only needs an
init of its own:

* Spec/Sha256.lean: H0_224; finalHash iv (the 32-byte H⁽ᴺ⁾ from iv),
  with hash := finalHash H0 and sha224 := (finalHash H0_224 ·).take 28;
  ReprFrom iv, with Repr := ReprFrom H0 (so HMAC and PBKDF2's contracts,
  which use Repr and hash, are unchanged).
* Spec/Sha256/Contract.lean: updateContract and finalizeContract hold for
  a state hashed from any initial hash value (finalize writes
  finalHash iv msg, which is hash msg for H0); init224Contract and
  init224Api for vg_sha224_init.

The existing implementations are unchanged: their update and finalize are
the generic Merkle-Damgard code, whose proofs already hold for any
initial hash value, so the per-target contracts quantify over it too and
the few callers that relied on H0 instantiate it.

docs/algorithms/sha224.toml adds the row (spec landed, no architecture
yet).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HDRg9k22FbCYq3TnciKvwG
…t API

vg_sha224_init stores SHA-224's initial hash value, then SHA-256's update
and finalize (whose contracts hold for any initial hash value) do the rest,
with every one of their implementations (SHA-NI and AVX2 on x86-64, the
SHA2 extension on AArch64).

* Impl: each target's init is now initWith iv, with init := initWith H0
  (the emitted vg_sha256_init is unchanged) and init224 := initWith H0_224.
* Proof: each target's init proof holds for any iv; the checks the kernel
  can only run on literal code (the taint analysis, and on x86-64 that it
  never loads MXCSR) are done for each of the two instances. The per-target
  init contracts take iv.
* Artifacts/Sha224/<Target>.lean registers vg_sha224_init from
  Spec.Sha256.init224Api.
* hashes::sha224::Sha224, over streaming_hash! with its own backend enum
  (the same variants as SHA-256's); unit tests, the CAVP short, long and
  Monte Carlo vectors, a Lean known-answer test of the spec, and a
  benchmark against OpenSSL. README table regenerated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HDRg9k22FbCYq3TnciKvwG

alex commented Oct 1, 2026

Copy link
Copy Markdown
Member Author

Two CI failures on 43c4fc2 are not from this PR: rust (ubuntu-24.04-arm, …cryptography-runner-ubuntu-rolling:armv7l…) and Rust (Thumb, stable).

Both died in setup, before any build or test ran. rustup toolchain install stable inside the armv7l container fails while upgrading to the 1.99.0 stable published today:

info: latest update on 2026-10-01 for version 1.99.0 (b940084d7 2026-09-28)
info: removing previous version of component cargo
error: failure removing component 'cargo-armv7-unknown-linux-gnueabihf', directory does not exist: 'share/man/man1/cargo.1'

An armv7l container job in the unrelated #453 failed at the same time. I don't know of a fix yet; it is in the runner image's preinstalled toolchain, not in this repository. I'll re-run the failed jobs once when the run finishes.


Generated by Claude Code

claude added 4 commits October 1, 2026 13:37
…-256 streaming glue

Main's x86 SHA-256 streaming proofs moved to Proof/Sha256/X86/Stream/Variant.lean
(for any compression backend); its update_of/finalize_of now pass iv through
instead of H0, as the other targets' do. src/asm/x86/sha256.rs regenerated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HDRg9k22FbCYq3TnciKvwG
src/asm/x86/sha256.rs regenerated (main's #460 reworked the x86 SHA-256
artifacts; vg_sha224_init is re-emitted).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HDRg9k22FbCYq3TnciKvwG
@alex
alex marked this pull request as ready for review October 1, 2026 15:17
@alex
alex added this pull request to the merge queue Oct 1, 2026
Merged via the queue into main with commit b684a4a Oct 1, 2026
42 of 44 checks passed
@alex
alex deleted the claude/gifted-cannon-gdzq6w branch October 1, 2026 21:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants