From 4b0bd3fbe48ead3f4b63977f2e5ec41dd0673fe8 Mon Sep 17 00:00:00 2001 From: Ray Walker Date: Tue, 22 Sep 2026 20:45:46 +1000 Subject: [PATCH 1/2] fix(encryption): probe the Armv8 Crypto Extension on aarch64 instead of NEON detect_hardware_acceleration() on aarch64 without a compile-time `aes` target feature returned cfg!(target_feature = "neon"). NEON is a default feature on every aarch64 target, so the flag was a constant true on all aarch64 builds, including Cortex-A72-class parts (Raspberry Pi 3/4) that have no AES instructions and run software AES in ring. Use std::arch::is_aarch64_feature_detected!("aes") (stable since 1.60, within MSRV 1.85). The compile-time short-circuit stays. Add the first unit test for the flag: it pins hardware_acceleration_enabled() to the platform's own runtime probe on x86/x86_64 and aarch64; both probes fold to const true under a compile-time `aes` feature, so the pin also covers the short-circuit path. Correct the metrics and module docs that named only AES-NI or claimed acceleration "was used (for SHA, AES, etc.)": the flag is informational and the crypto backend dispatches on its own. Crypto dispatch is unchanged. Ticket: LAB-4650 --- src/encryption/core.rs | 22 ++++++++++++++++++---- src/encryption/mod.rs | 2 +- src/metrics.rs | 3 ++- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/encryption/core.rs b/src/encryption/core.rs index 7ffd4d2..6fa89c4 100644 --- a/src/encryption/core.rs +++ b/src/encryption/core.rs @@ -283,12 +283,11 @@ impl ZeroKnowledgeEncryptor { true } - // Runtime detection for AArch64 crypto extensions + // NEON is default on every aarch64 target, so a cfg!(target_feature = "neon") + // check is const true and says nothing about AES (Cortex-A72 / Pi 3-4: NEON, no AES). #[cfg(not(target_feature = "aes"))] { - // ARM crypto extensions are usually available on modern ARM64 - // ring library will use them automatically if available - return cfg!(target_feature = "neon"); + std::arch::is_aarch64_feature_detected!("aes") } } @@ -605,6 +604,21 @@ impl ZeroKnowledgeEncryptor { mod tests { use super::*; + // Both probes fold to const true under compile-time aes, so the cfg short-circuit is pinned too. + #[cfg(any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64"))] + #[test] + fn test_hardware_acceleration_matches_platform_probe() { + let reported = ZeroKnowledgeEncryptor::new() + .unwrap() + .hardware_acceleration_enabled(); + + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + assert_eq!(reported, std::arch::is_x86_feature_detected!("aes")); + + #[cfg(target_arch = "aarch64")] + assert_eq!(reported, std::arch::is_aarch64_feature_detected!("aes")); + } + #[test] fn test_encrypt_decrypt_roundtrip() { let encryptor = ZeroKnowledgeEncryptor::new().unwrap(); diff --git a/src/encryption/mod.rs b/src/encryption/mod.rs index e55e13d..0ef307a 100644 --- a/src/encryption/mod.rs +++ b/src/encryption/mod.rs @@ -6,7 +6,7 @@ //! # Features //! - **AES-256-GCM. Not configurable by design.** Authenticated encryption with ring library //! - HKDF-SHA256 key derivation with domain separation (RFC 5869) -//! - Hardware acceleration detection and usage (AES-NI) +//! - Hardware acceleration detection and usage (AES-NI / Armv8 Crypto Extension) //! - Per-tenant key isolation with cryptographic guarantees //! - Zero-knowledge guarantees: storage never sees plaintext or keys diff --git a/src/metrics.rs b/src/metrics.rs index b9a9120..7d9f0c6 100644 --- a/src/metrics.rs +++ b/src/metrics.rs @@ -20,7 +20,8 @@ pub struct OperationMetrics { /// Encryption operation time in microseconds (None if not performed) pub encryption_time_micros: Option, - /// Whether hardware acceleration was used (for SHA, AES, etc.) + /// Whether the CPU reports AES hardware (AES-NI / Armv8 Crypto Extension). + /// Informational only: the crypto backend dispatches on its own detection. pub hardware_accelerated: bool, } From 7f3361135ec39908cb9deb2a21673fe7ccb13cf1 Mon Sep 17 00:00:00 2001 From: Ray Walker Date: Tue, 22 Sep 2026 21:02:01 +1000 Subject: [PATCH 2/2] docs(encryption): describe capability detection, not usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The module header listed "Hardware acceleration detection and usage", which overstates what this module does. detect_hardware_acceleration() reports CPU capability only — ring selects its own implementation independently, as the function's own rustdoc already states. --- src/encryption/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/encryption/mod.rs b/src/encryption/mod.rs index 0ef307a..f6b6589 100644 --- a/src/encryption/mod.rs +++ b/src/encryption/mod.rs @@ -6,7 +6,7 @@ //! # Features //! - **AES-256-GCM. Not configurable by design.** Authenticated encryption with ring library //! - HKDF-SHA256 key derivation with domain separation (RFC 5869) -//! - Hardware acceleration detection and usage (AES-NI / Armv8 Crypto Extension) +//! - Hardware acceleration capability detection (AES-NI / Armv8 Crypto Extension) //! - Per-tenant key isolation with cryptographic guarantees //! - Zero-knowledge guarantees: storage never sees plaintext or keys