Implement AES-CMAC on AArch64, with an AES-extension variant - #469
Conversation
The three AES-CMAC primitives specified in VG.Spec.Cmac (vg_cmac_aes_subkeys, vg_cmac_aes_update, vg_cmac_aes_finalize), proven against their contracts on x86-64: correct and constant time. Each encrypts a block by calling the verified vg_aes_ctr32 on a zero block with the block as the counter, so the CMAC code is generic over the implementations of ctr32 (a new AesCtr32 interface under Generic/ and Variants/): the emitter also emits the _aesni functions, calling vg_aes_ctr32_aesni. The Rust API is verified_garbage::cmac::aes::AesCmac (new, update, finalize, verify, mac), choosing the implementation by CPU feature. It is tested against Wycheproof's aes_cmac_test.json and every vector of the vendored NIST CAVP CMAC generation and verification files, and benchmarked against OpenSSL. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WkLN6tAYk76HACiEWLbAMD
The three AES-CMAC primitives specified in VG.Spec.Cmac (vg_cmac_aes_subkeys, vg_cmac_aes_update, vg_cmac_aes_finalize), proven against their contracts on AArch64: correct and constant time. As on x86-64, each encrypts a block by calling the verified vg_aes_ctr32 on a zero block with the block as the counter, and is generic over the implementations of ctr32 (the AesCtr32 interface on AArch64): the emitter also emits the _aes functions, which call vg_aes_ctr32_aes. The calls keep the return address in x30, which each function saves in the scratch buffer, so no stack is used. The lemmas about blocks in memory that do not depend on the target move to Proof/Cmac/Frame.lean and Proof/Cmac/Block.lean. The Rust API (verified_garbage::cmac::aes::AesCmac), its tests and its benchmark now cover AArch64 too, choosing the AES extension's implementation when the CPU has it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WkLN6tAYk76HACiEWLbAMD
…ngth check The rust-cpu-features jobs run only the tests they name; without cmac, the scalar implementation (chosen under SDE's Pentium 4) never ran under coverage. The rejected key's assertion keeps its message on one line, which coverage counts as run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WkLN6tAYk76HACiEWLbAMD
…mistic-mayer-jdgs35-aarch64
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WkLN6tAYk76HACiEWLbAMD
|
The Benchmarks jobs (Compare with base) on this PR were cancelled at their 15-minute timeout, so they show no result. The cause is not this PR's code. This PR's only benchmark change is the arch #488 fixes this: a changed benchmark now narrows the run to the modules its Generated by Claude Code |
Implements AES-CMAC on AArch64, following the x86-64 implementation (#463, merged). Like #463, this is an implementation only: it changes no
Spec/orTCB/files.Lean
Impl/CmacAes/AArch64.lean:vg_cmac_aes_subkeys,vg_cmac_aes_updateandvg_cmac_aes_finalize. Each encrypts a block by calling the verifiedvg_aes_ctr32on a zero block, with the block as the counter, as on x86-64.bl) keep the return address inx30. Each function savesx30and the callee-saved registers it uses in the scratch buffer ([2064, 2120)), so no stack is used (stack := 0).cbz/cbnz(onn, onlast_len − 16and onlast_len), and the last bytes are copied through advancing pointers.AesCtr32interface:Impl/Aes/AArch64/Callee.leanandProof/Aes/AArch64/Variant.leandefine the interface.Variants/AesCtr32/AArch64/{Scalar,Aese}.leanadd the implementations.Generic/AesCtr32/AArch64/CmacAes.leanregisters the functions, so the emitter also emitsvg_cmac_aes_*_aes(featureaes), which callvg_aes_ctr32_aes.Proof/CmacAes/AArch64/):sig_impliesconnects to the shared contracts ofSpec/Cmac/Contract.lean.RelCT.callwith ctr32's own constant-time proof for each call.keepsV, a field of each variant).Proof/Cmac/Frame.leanandProof/Cmac/Block.lean. The x86-64 proofs keep their own copies, so this PR doesn't touch them.Rust
cmac::aes::AesCmacnow also builds on AArch64, with an exhaustive backendmatch(Scalar/ArmCrypto). Its tests and benchmark are gated the same way.Testing
cargo testpassed foraarch64-unknown-linux-gnuunder qemu (Wycheproofaes_cmac_test.json, all CAVPCMACGenandCMACVervectors, and the unit tests), both with the AES extension and withVG_CPU_FEATURES=none.lake buildandlake env lean --run Emit.lean --checkci/check_*.pyscriptscargo fmt --checkandcargo clippy(both host andaarch64)🤖 Generated with Claude Code
https://claude.ai/code/session_01WkLN6tAYk76HACiEWLbAMD