Skip to content

feat: hardware_aes() to detect the silent software-AES fallback; stay on aes 0.8 - #108

Open
coderdan wants to merge 2 commits into
mainfrom
fix/hardware-aes-check
Open

coderdan wants to merge 2 commits into
mainfrom
fix/hardware-aes-check

Conversation

@coderdan

Copy link
Copy Markdown
Contributor

Refs #86. This replaces the approach in #106 (now a draft).

Why not aes 0.9

aes 0.9 removes the --cfg aes_armv8 flag, but on aarch64 it is 2–2.5x slower per AES call than 0.8.4 with the flag. On an Apple M4 that makes:

  • chained encryption about 3x slower
  • full encryption 32–52% slower
  • comparisons 59–123% slower

The measurements are in docs/benchmarks/2026-10-12-aes-0.9-results.md: an A/B/A run with under 1.2% drift between the two A runs, plus a microbenchmark of the AES calls alone. The upstream x86 regression (RustCrypto/block-ciphers#574) was fixed in 0.9.2, but aarch64 is still slow in 0.9.3, and no open issue reports it. aws-lc-rs was also measured and isn't faster.

What this PR does instead

It keeps aes 0.8 and makes the silent fallback that #86 worried about detectable:

  • ore_rs::hardware_aes() (new public fn): returns true only when this build uses hardware AES on the current CPU. On aarch64 that means cfg(aes_armv8) plus CPU support; on x86 it means AES-NI. Applications can assert it at startup or in a test.
    • Why not a build-script warning: Cargo only shows cargo:warning for path dependencies, so a warning from ore-rs would never reach crates.io users.
  • tests/hardware_aes.rs: fails on an aarch64 host that has AES when the flag is missing, so the aarch64 CI job catches a RUSTFLAGS override. Verified locally both ways:
    • passes with the workspace config
    • with RUSTFLAGS=-Dwarnings, fails with: "this CPU has AES, but ore-rs was built without --cfg aes_armv8; is RUSTFLAGS overriding .cargo/config.toml?"
  • README: documents the RUSTFLAGS pitfall and hardware_aes(), and links the benchmark write-up.
  • Cargo.toml: adds cfg(aes_armv8) to check-cfg.

Verification

Rust 1.78 (CI's toolchain on main):

clippy -D warnings is also clean on 1.89.

On aarch64, `aes` 0.8 uses hardware AES only with `--cfg aes_armv8`, and
a RUSTFLAGS environment variable silently replaces the rustflags in
.cargo/config.toml (#86). Upgrading to `aes` 0.9 removes the flag but is
2-2.5x slower per AES call on aarch64 (docs/benchmarks/2026-10-12-aes-0.9-results.md),
so stay on 0.8 and make the fallback detectable instead:

- `ore_rs::hardware_aes()` reports whether this build uses hardware AES
  on the current CPU, for applications to assert at startup or in tests.
  Build-script warnings would not reach downstream users: Cargo shows
  them only for path dependencies.
- tests/hardware_aes.rs fails on an AES-capable aarch64 host built
  without the flag, so the aarch64 CI job catches a RUSTFLAGS override.
- README: document the override pitfall, `hardware_aes()`, and why we
  are not on aes 0.9 yet.
- Record the aes 0.8 vs 0.9 (and aws-lc) benchmarks.

Refs #86
…n-drop

Encryption: #580 (aes 0.9.3) added non-inline load/store helpers that
don't inline across crates; fixed upstream in #598, unreleased.
Legacy compares: since 0.9.0, dropping Aes128 wipes the whole backend
union byte by byte (zeroize_flat_type). Measures Aes128Enc as a
mitigation.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant