diff --git a/src/constant_time.rs b/src/constant_time.rs index 89f89ac3d..3b033a8b2 100644 --- a/src/constant_time.rs +++ b/src/constant_time.rs @@ -16,12 +16,16 @@ use crate::{c, error}; +mod boolmask; + #[cfg(target_pointer_width = "64")] pub(crate) type Word = u64; #[cfg(target_pointer_width = "32")] pub(crate) type Word = u32; +pub(crate) use self::boolmask::BoolMask; + /// Returns `Ok(())` if `a == b` and `Err(error::Unspecified)` otherwise. /// The comparison of `a` and `b` is done in constant time with respect to the /// contents of each, but NOT in constant time with respect to the lengths of @@ -60,7 +64,8 @@ pub(crate) fn xor_assign_at_start<'a>( #[cfg(test)] mod tests { - use crate::{bssl, constant_time::xor_assign_at_start, error, limb::LimbMask, rand}; + use super::*; + use crate::{bssl, rand}; #[test] fn test_constant_time() -> Result<(), error::Unspecified> { @@ -84,13 +89,13 @@ mod tests { let ref_out = if b { input } else { out }; prefixed_extern! { - fn bssl_constant_time_test_conditional_memcpy(dst: &mut [u8; 256], src: &[u8; 256], b: LimbMask); + fn bssl_constant_time_test_conditional_memcpy(dst: &mut [u8; 256], src: &[u8; 256], b: BoolMask); } unsafe { bssl_constant_time_test_conditional_memcpy( &mut out, &input, - if b { LimbMask::True } else { LimbMask::False }, + if b { BoolMask::TRUE } else { BoolMask::FALSE }, ) } assert_eq!(ref_in, input); @@ -117,13 +122,13 @@ mod tests { }; prefixed_extern! { - fn bssl_constant_time_test_conditional_memxor(dst: &mut [u8; 256], src: &[u8; 256], b: LimbMask); + fn bssl_constant_time_test_conditional_memxor(dst: &mut [u8; 256], src: &[u8; 256], b: BoolMask); } unsafe { bssl_constant_time_test_conditional_memxor( &mut out, &input, - if b { LimbMask::True } else { LimbMask::False }, + if b { BoolMask::TRUE } else { BoolMask::FALSE }, ); } diff --git a/src/constant_time/boolmask.rs b/src/constant_time/boolmask.rs new file mode 100644 index 000000000..4a2374923 --- /dev/null +++ b/src/constant_time/boolmask.rs @@ -0,0 +1,32 @@ +// Copyright 2024 Brian Smith. +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY +// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +use super::Word; + +// BoolMask is either `BoolMask::TRUE` or `BoolMask::FALSE`. +#[repr(transparent)] +pub struct BoolMask(Word); + +impl BoolMask { + #[cfg(test)] + pub(super) const TRUE: Self = Self(Word::MAX); + #[cfg(test)] + pub(super) const FALSE: Self = Self(0); + + /// Returns true if `self` is `BoolMask::TRUE`; otherwise, returns false + /// (`self` is `BoolMask::FALSE`). + pub(crate) fn leak(self) -> bool { + self.0 != 0 + } +} diff --git a/src/limb.rs b/src/limb.rs index 0927fc12f..42308c4ac 100644 --- a/src/limb.rs +++ b/src/limb.rs @@ -18,10 +18,10 @@ //! Limbs ordered least-significant-limb to most-significant-limb. The bits //! limbs use the native endianness. -use crate::{c, error, polyfill::ArrayFlatMap}; +use crate::{c, constant_time, error, polyfill::ArrayFlatMap}; #[cfg(any(test, feature = "alloc"))] -use crate::{bits, constant_time, polyfill::usize_from_u32}; +use crate::{bits, polyfill::usize_from_u32}; #[cfg(feature = "alloc")] use core::num::Wrapping; @@ -29,24 +29,10 @@ use core::num::Wrapping; // XXX: Not correct for x32 ABIs. pub type Limb = constant_time::Word; pub const LIMB_BITS: usize = usize_from_u32(Limb::BITS); - -#[cfg_attr(target_pointer_width = "64", repr(u64))] -#[cfg_attr(target_pointer_width = "32", repr(u32))] -pub enum LimbMask { - #[cfg_attr(not(test), allow(dead_code))] // Only constructed by non-Rust & test code. - True = Limb::MAX, - #[cfg_attr(not(test), allow(dead_code))] // Only constructed by non-Rust & test code. - False = 0, -} - -impl LimbMask { - pub fn leak(self) -> bool { - !matches!(self, LimbMask::False) - } -} - pub const LIMB_BYTES: usize = (LIMB_BITS + 7) / 8; +pub type LimbMask = constant_time::BoolMask; + #[inline] pub fn limbs_equal_limbs_consttime(a: &[Limb], b: &[Limb]) -> LimbMask { prefixed_extern! {