Skip to content

SHA-384/512/512-224/512-256 on PPC64LE: verified compress/init/update/finalize - #117

Draft
alex wants to merge 3 commits into
claude/cool-hamilton-crn96s-sha256from
claude/cool-hamilton-crn96s-sha512
Draft

alex wants to merge 3 commits into
claude/cool-hamilton-crn96s-sha256from
claude/cool-hamilton-crn96s-sha512

Conversation

@alex

@alex alex commented Sep 28, 2026 •

Copy link
Copy Markdown
Member

Part of #55. Stacked on #110 (SHA-256, whose stream lemmas it reuses), and so on #109, #108 and #97. It is independent of the HMAC PR (#111). There are no TCB or spec changes. This PR adds implementations proven against the existing Spec.Sha512 contracts.

What

  • vg_sha512_compress(state = r3, blocks = r4, n = r5, scratch = r6) has the structure of the PPC64LE SHA-256 implementation, on whole 64-bit registers:
    • The working variables live in r7–r12, r14 and r15, renamed by the unrolled rounds.
    • The 16-word schedule window is in scratch[0..128), and the nonvolatile r14–r19 are saved in scratch[128..176).
    • The message is loaded big-endian with ldbrx.
    • Each Kₜ is built with lis, ori, sldi, oris, ori (movImm64, proven equal to the constant once, movImm64_eq).
  • vg_sha384_init/vg_sha512_init/vg_sha512_224_init/vg_sha512_256_init, vg_sha512_update and vg_sha512_finalize:
    • As on AArch64, these inline the compression function instead of calling it. They change neither the link register nor the stack, and need no frame (the contracts take stack = 0).
    • Their variables live in r26–r31, with the caller's values saved in scratch[176..224).
    • The update/finalize proofs track r14–r19, which only the inlined compression function writes, through its Verified ABI guarantee (WP.inline).
    • The final hash value and the 128-bit bit length are stored big-endian with stdbrx.

The proofs are in Proof/Sha512/PPC64LE/. The code uses 176 bytes of scratch for compress and 224 for update/finalize. Shared.lean widens these to the shared contracts' current 1328/1376 bytes (sized on main for x86-64's AVX2 compression function), as AArch64 does, and moves them to the shared contracts. The seven artifacts are registered in Api form in Artifacts/Sha512/PPC64LE.lean.

Rust

README

Regenerated by ci/algorithms_table.py: the SHA-384/512 row is ✅ on PPC64LE.

Testing

On current main (with #97), these all pass:

  • lake build and Emit.lean --check
  • ci/check_lean_imports.py, check_lean_speed.py, check_vectors.py, check_arch_gates.py, check_variants.py, algorithms_table.py --check
  • cargo fmt, and cargo clippy -D warnings on the host and for ppc64le
  • cargo test on x86-64, and cross-built for powerpc64le-unknown-linux-gnu under qemu-ppc64le (CAVP short, long and Monte Carlo for all four of SHA-384, SHA-512, SHA-512/224 and SHA-512/256)

🤖 Generated with Claude Code

https://claude.ai/code/session_01Fw6RULWHCeVgMDGc3wRrwE

Copy link
Copy Markdown
Member

This PR still uses the old layout that the conflict restructure (#144, #147, #148, #150) replaced on main. Moving it over makes it add files instead of editing shared lists, so it stops conflicting with other PRs.

What to move:

  • Artifacts.lean entries (vg_sha512_* and the SHA-384/512-224/512-256 inits on PPC64LE): move them out of lean/VerifiedGarbage/Artifacts.lean into registration files, one per algorithm and target: lean/VerifiedGarbage/Artifacts/Sha512/PPC64LE.lean. Each defines VG.Artifacts.<Alg>.<Target>.artifacts : List Artifact (see Artifacts/Selftest/X86_64.lean or Artifacts/Scrypt/X86_64.lean); Emit.lean finds them automatically. The legacy SHA/HMAC/ChaCha20/MD5/SHA-1/SHA-3 entries are also moving into such files in a pending PR, so if a file you need already exists by then, append to its list.
  • README table: if README: generate the algorithm table from the code #151 lands, the table is generated; add a docs/algorithms/<alg>.toml and run python3 ci/algorithms_table.py instead of editing README.md by hand.

This PR is stacked on another branch, so apply the same moves on that base first.

See the "Keeping parallel PRs from conflicting" section of CLAUDE.md and step 4 of "Adding a primitive".


Generated by Claude Code

@alex
alex force-pushed the claude/cool-hamilton-crn96s-sha256 branch from 0272e1e to 8ea0ee5 Compare September 28, 2026 22:10
@alex
alex force-pushed the claude/cool-hamilton-crn96s-sha512 branch from d363933 to 0f3b0ca Compare September 28, 2026 22:10

alex commented Sep 28, 2026

Copy link
Copy Markdown
Member Author

Done, on current main (0f3b0ca): the seven vg_sha512_*/vg_sha384_init/vg_sha512_224_init/vg_sha512_256_init artifacts on PPC64LE are in lean/VerifiedGarbage/Artifacts/Sha512/PPC64LE.lean (the same entries as Artifacts/Sha512/AArch64.lean up to the target, plus explicit spSafes), src/hashes/sha512.rs and tests/cavp/sha512.rs name PPC64LE in their inner #[cfg(...)], and the README row is regenerated. The bases got the same moves first. SHA-384/512 and the CAVP vectors pass under qemu-ppc64le.


Generated by Claude Code

@alex
alex force-pushed the claude/cool-hamilton-crn96s-sha256 branch from 8ea0ee5 to 2b795d9 Compare September 29, 2026 23:22
@alex
alex force-pushed the claude/cool-hamilton-crn96s-sha512 branch from 0f3b0ca to 8b97f12 Compare September 29, 2026 23:30
@alex
alex force-pushed the claude/cool-hamilton-crn96s-sha256 branch from 2b795d9 to 49dc845 Compare October 1, 2026 02:42
@alex
alex force-pushed the claude/cool-hamilton-crn96s-sha512 branch 2 times, most recently from 936e48b to f009c56 Compare October 1, 2026 13:14
@alex
alex force-pushed the claude/cool-hamilton-crn96s-sha256 branch from 49dc845 to e55a1eb Compare October 1, 2026 13:14
claude added 3 commits October 1, 2026 14:07
The same algorithm as on AArch64. vg_hmac_sha256_init stores H0 in both
states, XORs the key into the ipad and opad blocks, and calls
vg_sha256_compress on each; vg_hmac_sha256_finalize calls
vg_sha256_finalize on the inner state, rebuilds it as (K0 ^ opad) ||
digest from the outer hash value, and finalizes it again, leaving the MAC
in scratch[176..208). Both move the link register to r0 and save it in an
ELFv2 frame; init keeps its variables in r26-r31 (saved in scratch) and
finalize in r24-r25, which the callees preserve.

As on AArch64, the proofs use 160 and 240 bytes of scratch, and Shared.lean
widens them to the shared contracts' 608 and 688. The target-independent
lemmas come from Proof/Hmac/Common.lean.

HMAC-SHA-256 and its Wycheproof tests now build on little-endian powerpc64
(with the MAC left in scratch, as on the other 64-bit targets); they pass
under qemu-ppc64le. The other HMACs, and PBKDF2 (the only user of
sha256_key_states), stay on the other architectures.

Refs #55

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fw6RULWHCeVgMDGc3wRrwE
HMAC's verify compares MACs with vg_ct_eq (crate::ct), which needs an
implementation on every architecture that uses it: a verified PPC64LE one,
the same algorithm as AArch64's.

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

vg_sha512_compress has the structure of the SHA-256 implementation on whole
64-bit registers: the working variables in r7-r12, r14 and r15 (saving
the nonvolatile r14-r19 in scratch[128..176)), the message loaded
big-endian with ldbrx, and each 64-bit constant built with lis, ori, sldi,
oris and ori.

As on AArch64, init/update/finalize inline the compression function rather
than call it, so they change neither the link register nor the stack and
need no frame. Their variables live in r26-r31 (saved in
scratch[176..224)); the proofs track r14-r19, which only the inlined
compression function writes, through its ABI guarantee. The digest and
the 128-bit message length are stored big-endian with stdbrx.

The SHA-512 family's API and CAVP tests now build on little-endian
powerpc64; they pass under qemu-ppc64le. Its benchmark and CAVP tests lose
their four-architecture gates.

Refs #55

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fw6RULWHCeVgMDGc3wRrwE
@alex
alex force-pushed the claude/cool-hamilton-crn96s-sha256 branch from e55a1eb to e9146d5 Compare October 1, 2026 14:21
@alex
alex force-pushed the claude/cool-hamilton-crn96s-sha512 branch from f009c56 to 1ea32bf Compare October 1, 2026 14:21
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.

3 participants