Repository navigation
AES-GCM x86-64: seal_split for every variant; every gather seals through it - #1866
Conversation
|
This PR doesn't cause it. Only Generated by Claude Code |
|
I'll re-run the failed job once when the run completes. Generated by Claude Code |
|
merge conflicts |
717683d to
c625dda
Compare
|
merge conflicts |
|
The restack onto main is ready locally: one squashed commit, with the two import conflicts resolved and the 20 new Lean files converted to modules. It hasn't been built, regenerated or pushed yet, because this session's permission layer refused the git command that brings the commit into the build checkout. I've asked for that to be allowed. Once it is, I'll build, regenerate, test and force-push. (For about a minute, this branch briefly pointed at #1975's head by mistake. It's back on c625dda.) Generated by Claude Code |
|
merge conflict |
|
still waiting on a merge conflict fix here |
…ugh it Squashed and rebased onto main: the new files are modules. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FoYWDDEDFq1DFev5X7n2aq
|
Rebased onto main as one squashed commit (26eba23). Two proof files needed updating for main's #1859, which replaced Generated by Claude Code |
Stacked on #1850, which adds the spec and contract of
vg_aes_gcm_seal_split. Merge that first.What
AesGcm::encrypt(out of place) runsvg_aes_gcm_seal_gather. On main the gather takes one of two paths:copyBelow, it copies every slice todstand callssealthere.For a TLS record (the payload, then a 1-byte content type), copying first means the payload is read and written twice before any of it is encrypted (#1228).
This PR adds
vg_aes_gcm_seal_splitfor every implementation. It seals a text whose firsttlbytes are read fromsrcand whose rest is already in place atdst + tl. The prefix is encrypted straight fromsrctodstwith the instance'sencrypt_blocks_to(ctr32_to), and the rest is sealed in place.The gather's short path now also takes a text whose first slice holds all its whole blocks, at any length, and chooses between
sealandseal_split, inside the verified code (copyShort,Impl/AesGcm/X86_64/SealGather.lean):seal_split: used when the first slice holds all the text's whole blocks and at least the variant'ssplitFrombytes. The gather then copies only the slices after the first and callsseal_splitwith the first slice assrc.seal: used otherwise. The gather copies everything and callsseal, as on main.Where whole blocks follow the first slice (e.g. two halves), sealing in two places would take a second pass of the blocks loop, which costs more than the copy. So those texts keep the copy.
splitFrom(Generic/AesGcm/X86_64/AesGcm.lean), chosen from the Benchmarks results below:copyBelowsplitFromVariants: every
seal_gather_<s>calls bothseal_<s>andseal_split_<s>, and eachseal_split_<s>calls its ownctr32_<s>,encrypt_blocks_<s>andghash_<s>.ci/check_variants.pypasses with no exceptions. The Rust side is unchanged apart from the generated code.Each instance's
seal_splitends the way itssealdoes:Short.finish, with the short-message path (runShort) in front, assealhas.finishWith finKsA.oneCrypt; oneTag 0.Proofs
Spec/andTCB/are unchanged by this PR (the spec is Spec: AES-GCM seal of a plaintext whose prefix is read from elsewhere (vg_aes_gcm_seal_split) #1850's).seal_splitis proven once, generic over its ending (FinOk/FinRel,Split/Fin.lean,Split/FinCT.lean) and its middle (MidOk/MidRel):run:Split/Run.lean,Split/CT.lean.runShort:Split/ShortRun.lean,Split/ShortCT.lean. It reusessealShort's proof from a virtual entry state whosedstalready holdssrc's bytes.sealGather quick fast test short,sealGatherG_wp/sealGatherG_ct): a text belowsplitFromgoes tofast(copySeal, main's path) afterquickTest; only longer texts reachtest/short.ShortFn.ofBoth,Gather/Verified.lean):splitTest,selTest(Gather/SplitPath.lean,Gather/SplitCT.lean).Gather/SealCall,Gather/SealCallee,Gather/Split*.splitFrom_le(splitFrom + 16 ≤ copyBelow) is what lets a copied TLS text stay withinseal's short path.Measurements
Below
splitFromthe gather runs main's instructions. A text shorter than its variant'ssplitFromtakes the copy-and-sealpath after one compare and one branch. That is the same instruction sequence as main's short path; only the threshold immediate differs. This covers every size up to 384 B, and 600 B with VAES or AVX-512. Only longer texts reach the slice tests (splitTest, thenselTest).These results are from the Benchmarks workflow (
bench.yml,modules=aes_gcm) on this head (c625dda), against base 135a4d9:encrypt/384,encrypt/1024,decrypt/1024,encrypt-reused-key/4000), which this PR does not change, moved by more than 10% in them.The table gives mean % faster, then n. "two-pieces" is the TLS shape (payload, then a 1-byte content type) with a new key each time; "TLS" rows reuse the key.
AVX-512, per sample. The default job lands on an AVX-512 runner only when it is not given an EPYC 7763, so these were sampled until there were five clean AMD runs, Zen 4 and Zen 5 both. Two of them are from the previous head (761d821), whose gather runs the same instructions below
splitFrom:The five AMD samples average −0.8%, or +1.0% on this head alone. The one −7% run is not repeated in the four other AMD runs. Two more AMD runs (38201427078, 38203153182, both 761d821) and one on this head (38208862806, +2.3) moved an in-place control by more than 10% and are left out.
AVX-512 and the TLS shape with a reused key. With a reused key, AVX-512 is unchanged at 1350 and 4000 B (−0.1, +0.2): its out-of-place path already reads unaligned slices without buffering, so there is little left to save there. The earlier +7/+9% at those sizes came from one run (38201427078) whose base was slow; it is left out above. With a new key per text (two-pieces), AVX-512 is +11.7% at 1024 B and +3.3% at 16 KiB.
AES-NI+AVX at 600 B. The text is above that variant's
splitFrom(384), so it reads the first slice's length before it is copied and sealed as on main. Trimming a redundant length test fromcopyShort(selTestis now onelenTest) closed the earlier −3.2%:halves-reused-key/600is +0.9 (n=28) and TLS/600 is +2.7 (n=28), sosplitFromstays 384.🤖 Generated with Claude Code
https://claude.ai/code/session_01FoYWDDEDFq1DFev5X7n2aq