From d2fe57b6e438689ad64b56a21738fe173595a481 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Fri, 19 Dec 2025 17:58:15 -0700 Subject: [PATCH] ctutils: downgrade MSRV to 1.85 This is implemented as its own PR so we can easily revert it when we are ready to bump MSRV to 1.87. The main thing we lose here is `const fn` support for `Choice::to_u8` and `to_bool`, since these use `black_box`. In addition the macros to write the signed impls of `CtEq` and `CtSelect` become a little uglier, but that's not the end of the world. --- .github/workflows/ctutils.yml | 4 ++-- ctutils/Cargo.toml | 2 +- ctutils/README.md | 2 +- ctutils/src/choice.rs | 6 ++++-- ctutils/src/traits/ct_eq.rs | 6 +++--- ctutils/src/traits/ct_select.rs | 6 +++--- 6 files changed, 14 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ctutils.yml b/.github/workflows/ctutils.yml index 349c3dca..2b253145 100644 --- a/.github/workflows/ctutils.yml +++ b/.github/workflows/ctutils.yml @@ -31,7 +31,7 @@ jobs: strategy: matrix: rust: - - 1.87.0 # MSRV + - 1.85.0 # MSRV - stable target: - thumbv7em-none-eabi @@ -55,7 +55,7 @@ jobs: strategy: matrix: rust: - - 1.87.0 # MSRV + - 1.85.0 # MSRV - stable steps: - uses: actions/checkout@v5 diff --git a/ctutils/Cargo.toml b/ctutils/Cargo.toml index 7acecf8b..4ac01f9f 100644 --- a/ctutils/Cargo.toml +++ b/ctutils/Cargo.toml @@ -14,7 +14,7 @@ categories = ["cryptography", "no-std"] keywords = ["crypto", "intrinsics"] readme = "README.md" edition = "2024" -rust-version = "1.87" +rust-version = "1.85" [dependencies] cmov = "0.4" diff --git a/ctutils/README.md b/ctutils/README.md index ac088521..65fe6e73 100644 --- a/ctutils/README.md +++ b/ctutils/README.md @@ -57,7 +57,7 @@ dual licensed as above, without any additional terms or conditions. [docs-image]: https://docs.rs/ctutils/badge.svg [docs-link]: https://docs.rs/ctutils/ [license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg -[msrv-image]: https://img.shields.io/badge/rustc-1.87+-blue.svg +[msrv-image]: https://img.shields.io/badge/rustc-1.85+-blue.svg [build-image]: https://github.com/RustCrypto/utils/actions/workflows/ctutils.yml/badge.svg?branch=master [build-link]: https://github.com/RustCrypto/utils/actions/workflows/ctutils.yml?query=branch:master diff --git a/ctutils/src/choice.rs b/ctutils/src/choice.rs index 9288b474..6163c69a 100644 --- a/ctutils/src/choice.rs +++ b/ctutils/src/choice.rs @@ -45,12 +45,14 @@ impl Choice { /// the small amount of timing variability it introduces can potentially be exploited. Whenever /// possible, prefer fully constant-time approaches instead. /// - pub const fn to_bool(self) -> bool { + // TODO(tarcieri): `const fn` when MSRV 1.86 + pub fn to_bool(self) -> bool { self.to_u8() != 0 } /// Convert [`Choice`] to a `u8`, attempting to apply a "best effort" optimization barrier. - pub const fn to_u8(self) -> u8 { + // TODO(tarcieri): `const fn` when MSRV 1.86 + pub fn to_u8(self) -> u8 { // `black_box` is documented as working on a "best effort" basis. That's fine, this type is // likewise documented as only working on a "best effort" basis itself. The only way we // rely on `black_box` for correctness is it behaving as the identity function. diff --git a/ctutils/src/traits/ct_eq.rs b/ctutils/src/traits/ct_eq.rs index 47db87f2..c104c80e 100644 --- a/ctutils/src/traits/ct_eq.rs +++ b/ctutils/src/traits/ct_eq.rs @@ -38,12 +38,12 @@ macro_rules! impl_unsigned_ct_eq_with_cmov { // Impl `CtEq` by first casting to unsigned then using the unsigned `CtEq` impls // TODO(tarcieri): add signed integer support to `cmov` macro_rules! impl_signed_ct_eq_with_cmov { - ( $($int:ty),+ ) => { + ( $($int:ty => $uint:ty),+ ) => { $( impl CtEq for $int { #[inline] fn ct_eq(&self, other: &Self) -> Choice { - self.cast_unsigned().ct_eq(&other.cast_unsigned()) + (*self as $uint).ct_eq(&(*other as $uint)) } } )+ @@ -51,7 +51,7 @@ macro_rules! impl_signed_ct_eq_with_cmov { } impl_unsigned_ct_eq_with_cmov!(u8, u16, u32, u64, u128); -impl_signed_ct_eq_with_cmov!(i8, i16, i32, i64, i128); +impl_signed_ct_eq_with_cmov!(i8 => u8, i16 => u16, i32 => u32, i64 => u64, i128 => u128); #[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))] impl CtEq for usize { diff --git a/ctutils/src/traits/ct_select.rs b/ctutils/src/traits/ct_select.rs index 287fc6e1..9e4f233d 100644 --- a/ctutils/src/traits/ct_select.rs +++ b/ctutils/src/traits/ct_select.rs @@ -47,12 +47,12 @@ macro_rules! impl_unsigned_ct_select_with_cmov { // Impl `CtSelect` by first casting to unsigned then using the unsigned `CtSelect` impls // TODO(tarcieri): add signed integer support to `cmov` macro_rules! impl_signed_ct_select_with_cmov { - ( $($int:ty),+ ) => { + ( $($int:ty => $uint:ty),+ ) => { $( impl CtSelect for $int { #[inline] fn ct_select(&self, other: &Self, choice: Choice) -> Self { - self.cast_unsigned().ct_select(&other.cast_unsigned(), choice).cast_signed() + (*self as $uint).ct_select(&(*other as $uint), choice) as Self } } )+ @@ -60,7 +60,7 @@ macro_rules! impl_signed_ct_select_with_cmov { } impl_unsigned_ct_select_with_cmov!(u8, u16, u32, u64, u128); -impl_signed_ct_select_with_cmov!(i8, i16, i32, i64, i128); +impl_signed_ct_select_with_cmov!(i8 => u8, i16 => u16, i32 => u32, i64 => u64, i128 => u128); #[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))] impl CtSelect for usize {