VDB
KO

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

crates.io / cmov
Introduced in: 0.0.0-0 Fixed in: 0.4.4

Upgrade cmov to 0.4.4 or newer (ecosystem crates.io).

References