# RustCrypto Utilities cmov: `thumbv6m-none-eabi` compiler emits non-constant time assembly when using `cmovnz`

LLVM on thumbv6m-none-eabi compiles cmov's portable mask computation into a branch, leaking secret-dependent timing in constant-time selection.

- Payout: Research
- Severity: high
- Program: RustCrypto cmov
- Found by: NicsTr
- Disclosed: 2026-01-15
- CVE: CVE-2026-23519
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-2gqc-6j2q-83qp
- Library page: http://bugbountylibrary.com/r/ghsa%3AGHSA-2gqc-6j2q-83qp
- Tags: area:oss domain:oss kind:research platform:ghsa sev:high tech:rust technique:reverse-engineering technique:source-review vuln:crypto

**Target:** cmov crate portable cmovnz on thumbv6m-none-eabi (Cortex-M0/M0+/M1)
**Root cause:** LLVM recognizes bitnz's 0/1 result as boolean and turns the unmasked `.wrapping_sub(1)` mask computation into a conditional branch (`bne`/`mvns`) instead of branchless arithmetic.
**Steps:**
1. Build a no_std crate depending on cmov < 0.4.4 with `pub fn test_ct_cmov(a: &mut u8, b: u8, c: u8) { a.cmovnz(&b, c); }`
2. Compile with `cargo asm --release --target thumbv6m-none-eabi`
3. Observe emitted `bne .LBB0_2` / `mvns r3, r3` branch instead of branchless mask
**How found:** Reporter inspected generated assembly for the portable cmovnz path on embedded targets, suspecting LLVM could optimize the mask computation; found the bitnz 0/1 intermediate is treated as a boolean because it isn't hidden behind black_box.
**Insight:** When auditing constant-time primitives, don't trust source-level branchlessness: compile for each target and inspect asm, since LLVM pattern-matches 0/1 intermediates into branches unless black_box blocks the optimization.

## Proof of concept (copied exactly from the original report)

**Minimal cmovnz PoC function**

```
#![no_std]
use cmov::Cmov;

#[inline(never)]
pub fn test_ct_cmov(a: &mut u8, b: u8, c: u8) {
    a.cmovnz(&b, c);
}
```

**Non-constant-time branch in emitted assembly**

```
bne .LBB0_2
	mvns r3, r3
.LBB0_2:
```

