Repository navigation
Conversation
`Hmac::finalize_reset(&mut self)` returns the MAC of everything absorbed and leaves the computation keyed with the same key, ready for the next message. Unlike `finalize(self)` it never moves the state, so it leaves no copy of it where the caller's variable was (one Rust makes to pass a variable by value). The state keeps the hash value of K0 ^ ipad (`ipad`, the keyed inner state of one block, whose buffer it does not read), copied in place after `init`; `hmac_reset` copies it back in place and sets the inner length to a block. `ipad` follows `outer` in C's layout, so one wipe covers both. Benchmarked next to OpenSSL (a `Signer` from the same `PKey` per message, as rust-openssl has no reset) and aws-lc-rs (one `hmac::Key`, reused): `hmac-<hash>-reset`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013RJ8JEAFPoUJwyYZ7WE48r
Member
Author
|
Closing: stack-residue work dropped by the maintainer. Generated by Claude Code |
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.
New public API, stacked on #2687. Rust only: no Lean,
src/asm/,TCB/orSpec/changes.Hmac::finalize_reset(&mut self) -> H::Outputreturns the MAC of everything absorbed and leaves the computation keyed again with the same key, ready for the next message. It closes the last dead-stack copy #2687 couldn't reach:finalize(self)takes the state by value, so a caller'snew+update+finalizehas Rust copy its variable to pass it, and leaves the original unwiped in the caller's frame.finalize_resettakes&mut selfand never moves the state.The name and semantics follow what the dead-stack design (#2680's session) uses for the other streaming types, and RustCrypto's
FixedOutputReset::finalize_reset. For HMAC, "reset" means keyed again. The coordinator approved it as a PR of its own, with a benchmark. The rustls provider (#991) will switch to it.How
ipad: [u8; V], the hash value ofK₀ ⊕ ipad, which is the inner state once keyed (V= state size − block size: 16, 20, 32 or 64 bytes).hmac_initcopies it in place after the verifiedinit.hmac_resetcopiesipadback into the inner state in place and sets the inner length to one block.ReprFrom(Spec/Sha256.lean, and the same shape for each hash) readslength % Bbytes of the buffer, here none.K₀ ⊕ ipad, asinitleft it. The verifiedfinalize's precondition holds for every later message, as afternew.StreamingHmacStateis#[repr(C)], soipaddirectly followsouter(byte arrays, no padding), andDropwipes both with onezeroize_raw.set_length:streaming_hash!gains apub(crate)set_lengthfor the reset.Dead-stack harness
The harness is #2674's (key A, key B, key A from a dirtied stack, after a warm-up), on a tree with #2674's and #2696's asm and this branch's Rust. It measures a caller's own out-of-line
new+update+ then either:finalize(self)finalize_reset(&mut self)avx,avx2,bmi1,bmi2andnoneTests
hmac::<hash>::tests::finalize_reset, generated for every hash, checks:finalize_reset;Hmac::mac's, with a short key and with one longer than a block;verifyandfinalizeafter a reset see only what follows it.It runs in every CPU-feature configuration, since
ci/cpu_tests.py's groups name thehmac::<hash>modules. It passes on x86-64 withVG_CPU_FEATURESunset,none,avx,avx2,bmi1,bmi2andsha,ssse3, and on AArch64 under qemu.Cost
Measured by instruction count under callgrind, x86-64 AVX2, 64-byte message, against #2687:
Hmac::<Sha256>::macnew+update+verify, SHA-256Hmac::<Sha512>::macnew+update+verify, SHA-512The
ipadcopy costs a few instructions, and the wipe stays one call. A first version wipedipadwith a secondzeroizeand cost about 80–100 instructions; merging the two wipes removed that.Benchmark
hmac-<hash>-reset, inbench/benches/primitives/hmac_*.rs, through a sharedhmac_reset_group:update+finalize_resetper message.Signermade from the samePKeyper message, since rust-openssl has no reset.hmac::Keywithhmac::sign, which is the same work.Locally (x86-64 with SHA-NI, unscoped timing), HMAC-SHA-256 per message:
A scoped Benchmarks dispatch (the
hmac_*modules) will follow, when the queue allows; I'll link it here.Checks
cargo fmt --check(crate andbench/);cargo clippy --all-targets -- -D warnings;ci/check_arch_gates.py;cargo bench --no-run.Generated by Claude Code