GitHub Advisoryadvisory · crates.io
GHSA-2gqc-6j2q-83qp RustCrypto Utilities cmov: `thumbv6m-none-eabi` compiler emits non-constant time assembly when using `cmovnz`
HIGH
Official page ↗
- Aliases
- CVE-2026-23519
- Ecosystem
- crates.io
- Packages
- cmov
- Severity
- High
- CVSS vector
- CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N
- Weaknesses
- CWE-203, CWE-208
- Reviewed
- 2026-01-15
Affected packages
• crates.io cmov: < 0.4.4 → fixed in 0.4.4
Description
Summary
`thumbv6m-none-eabi` (Cortex M0, M0+ and M1) compiler emits non-constant time assembly when using `cmovnz` (portable version). I did not found any other target with the same behaviour but I did not go through all targets supported by Rust.
Details
It seems that, during `mask` computation, an LLVM optimisation pass is detecting that `bitnz` is returning 0 or 1, that can be interpreted as a boolean. This intermediate value is not masked by a call to `black_box` and thus the subsequent `.wrapping_sub(1)` can be interpreted as a conditional bitwise conditional not.
PoC
This is an attempt at having a minimal faulty code. In a library crate with an up-to-date `cmov` as only dependency, the content of `src/lib.rs` is:
```rust
![no_std]
use cmov::Cmov;
[inline(never)]
pub fn test_ct_cmov(a: &mut u8, b: u8, c: u8) {
a.cmovnz(&b, c);
}
```
The resulting assembly emitted (shown using `cargo asm --release --target thumbv6m-none-eabi` that uses `cargo-show-asm`):
Collapsed assembly
```asm
.section .text.not_ct::test_ct_cmov,"ax",%progbits
.globl not_ct::test_ct_cmov
.p2align 1
.type not_ct::test_ct_cmov,%function
.code 16
.thumb_func
not_ct::test_ct_cmov:
.fnstart
.cfi_sections .debug_frame
.cfi_startproc
.save {r7, lr}
push {r7, lr}
.cfi_def_cfa_offset 8
.cfi_offset lr, -4
.cfi_offset r7, -8
.setfp r7, sp
add r7, sp, #0
.cfi_def_cfa_register r7
.pad #8
sub sp, #8
movs r3, #0
lsls r2, r2, #24
bne .LBB0_2
mvns r3, r3
.LBB0_2:
ldrb r2, [r0]
str r3, [sp, #4]
str r3, [sp]
mov r3, sp
@APP
@NO_APP
ldr r3, [sp]
bics r1, r3
ands r2, r3
adds r1, r2, r1
strb r1, [r0]
add sp, #8
pop {r7, pc}
```
The non-constant time assembly is:
```asm
bne .LBB0_2
mvns r3, r3
.LBB0_2:
```
Impact
The exact impact is unclear, especially since `cmov` clearly warns users that the portable version is best-effort.
Related
Alias · CVE (1)
- CVE-2026-23519 RustCrypto CMOV provides conditional move CPU intrinsics which are guaranteed on major platforms to execute in constant-time and not be… vulnerability
References
- https://github.com/RustCrypto/utils/security/advisories/GHSA-2gqc-6j2q-83qp web
- https://nvd.nist.gov/vuln/detail/CVE-2026-23519 advisory
- https://github.com/RustCrypto/utils/commit/55977257e7c82a309d5e8abfdd380a774f0f9778 web
- https://github.com/RustCrypto/utils package
- https://rustsec.org/advisories/RUSTSEC-2026-0003.html web