Skip to content

chore(deps): upgrade aes 0.8 -> 0.9 and drop the aes_armv8 cfg workaround - #106

Draft
coderdan wants to merge 2 commits into
mainfrom
chore/aes-0.9
Draft

coderdan wants to merge 2 commits into
mainfrom
chore/aes-0.9

Conversation

@coderdan

Copy link
Copy Markdown
Contributor

Closes #86.

Summary

aes 0.9 turns on the ARMv8 backend by default and detects it at runtime. That means hardware AES on aarch64 no longer needs --cfg aes_armv8, in this workspace or in downstream builds. It also removes a trap: a RUSTFLAGS environment variable silently overrides the flag set in .cargo/config.toml.

  • API port: moved to the cipher 0.5 API. GenericArray is now hybrid-array's Array, and BlockEncrypt is now BlockCipherEncrypt. The deprecated from_slice calls are replaced with From/TryFrom. Runtime 16-byte slices go through a crate-private primitives::block_ref, which panics on a wrong length, just as from_slice did.
  • Flag removed: deleted .cargo/config.toml and the README's warning that downstream crates must set the flag.
  • Unused dependency: dropped block-modes.
  • MSRV: raised to 1.89, because aes 0.9.3 needs it (0.9.1 and 0.9.2 need 1.85). rust-version is now declared, and CI and .tool-versions move to 1.89.0. The new rustfmt reformats one where clause in orderable-bytes.
  • Lockfiles: updated the separate ct-dudect, ct-taint and fuzz lockfiles.

⚠️ Downstream impact

  • Rust version: downstream crates now need Rust ≥ 1.89 to build ore-rs. This belongs in the 0.9.0 release notes.
  • Old flag: projects that set --cfg aes_armv8 can remove it. It no longer has any effect.

Verification

Run locally on Rust 1.89, aarch64, with no rustflags:

  • Ciphertexts: the legacy, Bit6 and chained compat-vector suites pass byte for byte, so the output is unchanged.
  • Tests and checks: all tests and the ct_bench tests pass, and clippy -D warnings and fmt --check are clean.
  • Hardware AES with no flag: Bit6 encrypt-u64 takes 11.6 µs, against 95 µs when built with --cfg aes_backend="soft".
  • x86_64: not run locally. CI covers it.

…ound

aes 0.9 enables the ARMv8 backend by default with runtime detection, so
hardware AES on aarch64 no longer needs `--cfg aes_armv8` here or in
downstream builds. That removes the RUSTFLAGS-override footgun where the
flag in .cargo/config.toml was silently ignored.

- Port to the cipher 0.5 API: GenericArray -> hybrid-array Array,
  BlockEncrypt -> BlockCipherEncrypt, deprecated from_slice calls ->
  From/TryFrom (a crate-private `block_ref` for runtime 16-byte slices).
- Remove .cargo/config.toml and the README's downstream-flag caveat.
- Drop the unused block-modes dependency.
- Raise MSRV to 1.89 (aes 0.9.3); declare rust-version, move CI and
  .tool-versions to 1.89.0. rustfmt 1.89 reformats one where clause in
  orderable-bytes.
- Update the detached ct-dudect, ct-taint and fuzz lockfiles.

Ciphertexts are unchanged: the legacy, Bit6 and chained compat vectors
pass byte for byte. Bit6 encrypt-u64 on aarch64 with no flags: 11.6 us,
against 95 us with `--cfg aes_backend="soft"`.

Closes #86
@coderdan
coderdan marked this pull request as draft October 12, 2026 11:26
@coderdan

Copy link
Copy Markdown
Contributor Author

Converted to draft: aes 0.9.3 is 2–2.5x slower per AES call than aes 0.8.4 with aes_armv8 on aarch64.

The flag problem goes away, but encryption gets much slower. Measured on an Apple M4 (mains power, Low Power Mode off), Rust 1.89, criterion medians. The run went main → this branch → main again; the two main runs agree within about 1%.

bench aes 0.8 + flag aes 0.9.3 Δ
chained encrypt (str, 17 B) 13.95 µs 40.63 µs +191%
chained encrypt (str, 43 B) 34.47 µs 101.64 µs +195%
Bit6 encrypt u64 7.93 µs 12.07 µs +52%
legacy encrypt u64 17.76 µs 23.63 µs +33%
legacy compare u64 234 ns 371 ns +59%
compare date 142 ns 313 ns +121%
left-only encrypt — — +4 to +8%

A microbenchmark of the AES calls alone (same process, interleaved, confidence intervals under 1%):

shape aes 0.8 + flag aes 0.9.3
one block 5.8 ns 11.6 ns
64 blocks, fixed key 41.7 ns 101.8 ns
256 blocks, fixed key 164 ns 399 ns
key schedule 38 ns 38 ns

-C target-feature=+aes changes nothing, because aarch64-apple-darwin already enables aes. In the disassembly, aes 0.9's bulk path does about 99 128-bit loads, 40 stores and 34 calls, against 13, 7 and 5 for 0.8: the AES state is spilled to memory and helper calls aren't inlined.

Upstream: RustCrypto/block-ciphers#574 reported the 0.8 → 0.9 regression on x86_64. RustCrypto/block-ciphers#575 ("refactor backends") fixed it, and the fix shipped in 0.9.2. 0.9.3 is still slow on aarch64. I found no open report for aarch64.

Plan: stay on aes 0.8 for ore-rs 0.9.0. A separate PR adds a check that catches builds where hardware AES is missing, which addresses the silent fallback from #86. This PR stays as a draft until upstream fixes the aarch64 path. Full write-up: docs/benchmarks/2026-10-12-aes-0.9-results.md (in that PR).

@coderdan

Copy link
Copy Markdown
Contributor Author

The separate PR mentioned above is #108. It also contains the full write-up (docs/benchmarks/2026-10-12-aes-0.9-results.md).

…arch64 fix

aes 0.9.3 is 2-2.5x slower on aarch64; block-ciphers #598 fixes it but
is unreleased. The patch only affects this workspace, so this PR must
not be released until it's replaced by a crates.io aes release.
@coderdan

Copy link
Copy Markdown
Contributor Author

Pushed 00ef8c9: [patch.crates-io] pins aes to upstream block-ciphers master (b99ebe6), which includes #598, the unreleased fix for the aarch64 slowdown in 0.9.3. Root cause and numbers are in #108 (docs/benchmarks/2026-10-13-aes-0.9-root-cause.md). With this pin, encryption is 3–11% faster than main. Legacy comparisons are still 21–62% slower because of the zeroize-on-drop cost; #109 reduces that.

Do not merge or release this as-is. A [patch] only applies to this workspace. A crate published from here would depend on crates.io aes 0.9.3, the slow release, and crates.io doesn't accept git dependencies. This stays a draft until an aes release after 0.9.3 is out; then the patch comes out and the requirement moves to that version.

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.

Upgrade aes 0.8 -> 0.9 to drop the aes_armv8 cfg workaround

1 participant