Skip to content

Commit

Permalink
constant_time: Refactor LimbMask to constant_time::BoolMask.
Browse files Browse the repository at this point in the history
`LimbMask` now is an alias for `BoolMask`.

`BoolMask` is now fully opaque to the compiler, instead of being an
enum.
  • Loading branch information
briansmith committed Dec 7, 2024
1 parent df14ce9 commit dbae856
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 23 deletions.
15 changes: 10 additions & 5 deletions src/constant_time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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> {
Expand All @@ -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);
Expand All @@ -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 },
);
}

Expand Down
32 changes: 32 additions & 0 deletions src/constant_time/boolmask.rs
Original file line number Diff line number Diff line change
@@ -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
}
}
22 changes: 4 additions & 18 deletions src/limb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,35 +18,21 @@
//! 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;

// 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! {
Expand Down

0 comments on commit dbae856

Please sign in to comment.