RUSTSEC-2026-0003
Non-constant-time code generation on ARM32 targets
Details
## Summary
While the `cmov` crate has a special backend for `aarch64` which uses special CSEL instructions, on 32-bit ARM it uses a portable pure Rust fallback implementation. This implementation uses a combination of bitwise arithmetic and `core::hint::black_box` to attempt to coerce constant-time code generation out of the optimizer, but the implementation in v0.4.3 and earlier failed to do this on 32-bit ARM targets.
## Impact
Branch instructions inserted by the LLVM optimizer on 32-bit targets can be leveraged using various microarchitectural sidechannels like cache timing attacks to learn secret information that `cmov` is designed to protect.
## Details
The following assembly was emitted when using `Cmov::cmovnz`, a function which implements a conditional move when a provided value is non-zero:
```asm bne .LBB0_2 mvns r3, r3 ```
This includes a branch instruction `bne`: Branch if Not Equal.
## PoC
The following code reproduces the issue:
```rust #![no_std] use cmov::Cmov;
#[inline(never)] pub fn test_ct_cmov(a: &mut u8, b: u8, c: u8) { a.cmovnz(&b, c); } ```
## Resolution
`cmov` v0.4.4 includes a portable `black_box`-based tactical mitigation for the issue which coerced the compiler into producing the expected codegen, and additionally v0.4.5 added an `asm!` reimplementation of the problematic mask generation function for ARM32 targets which should guarantee that particular function never contains a branch on such targets.
Are you affected?
Enter the version of the package you're using.
Affected packages
0.0.0-0 Fixed in: 0.4.4 Upgrade cmov to 0.4.4 or newer (ecosystem crates.io).