GitHub Advisoryadvisory · crates.io

GHSA-2gqc-6j2q-83qp RustCrypto Utilities cmov: `thumbv6m-none-eabi` compiler emits non-constant time assembly when using `cmovnz`

HIGH Published 2026-01-15 Modified 2026-01-23 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

Weakness · CWE (2)

  • CWE-203 Observable Discrepancy weakness
  • CWE-208 Observable Timing Discrepancy weakness

References