diff --git a/src/ct_choice.rs b/src/ct_choice.rs index 921e72de9..10c2b2230 100644 --- a/src/ct_choice.rs +++ b/src/ct_choice.rs @@ -15,63 +15,132 @@ impl CtChoice { /// The truthy value. pub const TRUE: Self = Self(Word::MAX); + #[inline] + pub(crate) const fn as_u32_mask(&self) -> u32 { + #[allow(trivial_numeric_casts)] + (self.0.wrapping_neg() as u32).wrapping_neg() + } + /// Returns the truthy value if `value == Word::MAX`, and the falsy value if `value == 0`. /// Panics for other values. - pub(crate) const fn from_mask(value: Word) -> Self { + #[inline] + pub(crate) const fn from_word_mask(value: Word) -> Self { debug_assert!(value == Self::FALSE.0 || value == Self::TRUE.0); Self(value) } /// Returns the truthy value if `value == 1`, and the falsy value if `value == 0`. /// Panics for other values. - pub(crate) const fn from_lsb(value: Word) -> Self { + #[inline] + pub(crate) const fn from_word_lsb(value: Word) -> Self { debug_assert!(value == 0 || value == 1); Self(value.wrapping_neg()) } + #[inline] + pub(crate) const fn from_u32_lsb(value: u32) -> Self { + debug_assert!(value == 0 || value == 1); + #[allow(trivial_numeric_casts)] + Self((value as Word).wrapping_neg()) + } + + /// Returns the truthy value if `value != 0`, and the falsy value otherwise. + #[inline] + pub(crate) const fn from_u32_nonzero(value: u32) -> Self { + Self::from_u32_lsb((value | value.wrapping_neg()) >> (u32::BITS - 1)) + } + /// Returns the truthy value if `value != 0`, and the falsy value otherwise. - pub(crate) const fn from_usize_being_nonzero(value: usize) -> Self { - const HI_BIT: u32 = usize::BITS - 1; - Self::from_lsb(((value | value.wrapping_neg()) >> HI_BIT) as Word) + #[inline] + pub(crate) const fn from_word_nonzero(value: Word) -> Self { + Self::from_word_lsb((value | value.wrapping_neg()) >> (Word::BITS - 1)) + } + + /// Returns the truthy value if `x == y`, and the falsy value otherwise. + #[inline] + pub(crate) const fn from_u32_eq(x: u32, y: u32) -> Self { + Self::from_u32_nonzero(x ^ y).not() } /// Returns the truthy value if `x == y`, and the falsy value otherwise. - pub(crate) const fn from_usize_equality(x: usize, y: usize) -> Self { - Self::from_usize_being_nonzero(x.wrapping_sub(y)).not() + #[inline] + pub(crate) const fn from_word_eq(x: Word, y: Word) -> Self { + Self::from_word_nonzero(x ^ y).not() + } + + /// Returns the truthy value if `x < y`, and the falsy value otherwise. + #[inline] + pub(crate) const fn from_word_lt(x: Word, y: Word) -> Self { + let bit = (((!x) & y) | (((!x) | y) & (x.wrapping_sub(y)))) >> (Word::BITS - 1); + Self::from_word_lsb(bit) } /// Returns the truthy value if `x < y`, and the falsy value otherwise. - pub(crate) const fn from_usize_lt(x: usize, y: usize) -> Self { - let bit = (((!x) & y) | (((!x) | y) & (x.wrapping_sub(y)))) >> (usize::BITS - 1); - Self::from_lsb(bit as Word) + #[inline] + pub(crate) const fn from_u32_lt(x: u32, y: u32) -> Self { + let bit = (((!x) & y) | (((!x) | y) & (x.wrapping_sub(y)))) >> (u32::BITS - 1); + Self::from_u32_lsb(bit) + } + + /// Returns the truthy value if `x <= y` and the falsy value otherwise. + #[inline] + pub(crate) const fn from_word_le(x: Word, y: Word) -> Self { + let bit = (((!x) | y) & ((x ^ y) | !(y.wrapping_sub(x)))) >> (Word::BITS - 1); + Self::from_word_lsb(bit) + } + + /// Returns the truthy value if `x <= y` and the falsy value otherwise. + #[inline] + pub(crate) const fn from_u32_le(x: u32, y: u32) -> Self { + let bit = (((!x) | y) & ((x ^ y) | !(y.wrapping_sub(x)))) >> (u32::BITS - 1); + Self::from_u32_lsb(bit) } + #[inline] pub(crate) const fn not(&self) -> Self { Self(!self.0) } + #[inline] pub(crate) const fn or(&self, other: Self) -> Self { Self(self.0 | other.0) } + #[inline] pub(crate) const fn and(&self, other: Self) -> Self { Self(self.0 & other.0) } /// Return `b` if `self` is truthy, otherwise return `a`. - pub(crate) const fn select(&self, a: Word, b: Word) -> Word { + #[inline] + pub(crate) const fn select_word(&self, a: Word, b: Word) -> Word { a ^ (self.0 & (a ^ b)) } + /// Return `b` if `self` is truthy, otherwise return `a`. + #[inline] + pub(crate) const fn select_u32(&self, a: u32, b: u32) -> u32 { + a ^ (self.as_u32_mask() & (a ^ b)) + } + /// Return `x` if `self` is truthy, otherwise return 0. - pub(crate) const fn if_true(&self, x: Word) -> Word { + #[inline] + pub(crate) const fn if_true_word(&self, x: Word) -> Word { x & self.0 } + /// Return `x` if `self` is truthy, otherwise return 0. + #[inline] + pub(crate) const fn if_true_u32(&self, x: u32) -> u32 { + x & self.as_u32_mask() + } + + #[inline] pub(crate) const fn is_true_vartime(&self) -> bool { self.0 == CtChoice::TRUE.0 } + #[inline] pub(crate) const fn to_u8(self) -> u8 { (self.0 as u8) & 1 } @@ -98,7 +167,7 @@ mod tests { fn select() { let a: Word = 1; let b: Word = 2; - assert_eq!(CtChoice::TRUE.select(a, b), b); - assert_eq!(CtChoice::FALSE.select(a, b), a); + assert_eq!(CtChoice::TRUE.select_word(a, b), b); + assert_eq!(CtChoice::FALSE.select_word(a, b), a); } } diff --git a/src/limb.rs b/src/limb.rs index 3d7f60342..521452b09 100644 --- a/src/limb.rs +++ b/src/limb.rs @@ -54,7 +54,7 @@ pub type Word = u64; pub type WideWord = u128; /// Highest bit in a [`Limb`]. -pub(crate) const HI_BIT: usize = Limb::BITS - 1; +pub(crate) const HI_BIT: u32 = Limb::BITS - 1; /// Big integers are represented as an array of smaller CPU word-size integers /// called "limbs". @@ -78,7 +78,7 @@ impl Limb { /// Size of the inner integer in bits. #[cfg(target_pointer_width = "32")] - pub const BITS: usize = 32; + pub const BITS: u32 = 32; /// Size of the inner integer in bytes. #[cfg(target_pointer_width = "32")] pub const BYTES: usize = 4; @@ -87,14 +87,14 @@ impl Limb { /// Size of the inner integer in bits. #[cfg(target_pointer_width = "64")] - pub const BITS: usize = 64; + pub const BITS: u32 = 64; /// Size of the inner integer in bytes. #[cfg(target_pointer_width = "64")] pub const BYTES: usize = 8; } impl Bounded for Limb { - const BITS: usize = Self::BITS; + const BITS: u32 = Self::BITS; const BYTES: usize = Self::BYTES; } diff --git a/src/limb/bits.rs b/src/limb/bits.rs index c769e33e9..1c7674f49 100644 --- a/src/limb/bits.rs +++ b/src/limb/bits.rs @@ -2,22 +2,22 @@ use super::Limb; impl Limb { /// Calculate the number of bits needed to represent this number. - pub const fn bits(self) -> usize { - Limb::BITS - (self.0.leading_zeros() as usize) + pub const fn bits(self) -> u32 { + Limb::BITS - self.0.leading_zeros() } /// Calculate the number of leading zeros in the binary representation of this number. - pub const fn leading_zeros(self) -> usize { - self.0.leading_zeros() as usize + pub const fn leading_zeros(self) -> u32 { + self.0.leading_zeros() } /// Calculate the number of trailing zeros in the binary representation of this number. - pub const fn trailing_zeros(self) -> usize { - self.0.trailing_zeros() as usize + pub const fn trailing_zeros(self) -> u32 { + self.0.trailing_zeros() } /// Calculate the number of trailing ones the binary representation of this number. - pub const fn trailing_ones(self) -> usize { - self.0.trailing_ones() as usize + pub const fn trailing_ones(self) -> u32 { + self.0.trailing_ones() } } diff --git a/src/limb/cmp.rs b/src/limb/cmp.rs index 4cdec5b5d..bd3fff701 100644 --- a/src/limb/cmp.rs +++ b/src/limb/cmp.rs @@ -1,6 +1,5 @@ //! Limb comparisons -use super::HI_BIT; use crate::{CtChoice, Limb}; use core::cmp::Ordering; use subtle::{Choice, ConstantTimeEq, ConstantTimeGreater, ConstantTimeLess}; @@ -28,42 +27,13 @@ impl Limb { /// Return `b` if `c` is truthy, otherwise return `a`. #[inline] pub(crate) const fn ct_select(a: Self, b: Self, c: CtChoice) -> Self { - Self(c.select(a.0, b.0)) + Self(c.select_word(a.0, b.0)) } /// Returns the truthy value if `self != 0` and the falsy value otherwise. #[inline] pub(crate) const fn ct_is_nonzero(&self) -> CtChoice { - let inner = self.0; - CtChoice::from_lsb((inner | inner.wrapping_neg()) >> HI_BIT) - } - - /// Returns the truthy value if `lhs == rhs` and the falsy value otherwise. - #[inline] - pub(crate) const fn ct_eq(lhs: Self, rhs: Self) -> CtChoice { - let x = lhs.0; - let y = rhs.0; - - // x ^ y == 0 if and only if x == y - Self(x ^ y).ct_is_nonzero().not() - } - - /// Returns the truthy value if `lhs < rhs` and the falsy value otherwise. - #[inline] - pub(crate) const fn ct_lt(lhs: Self, rhs: Self) -> CtChoice { - let x = lhs.0; - let y = rhs.0; - let bit = (((!x) & y) | (((!x) | y) & (x.wrapping_sub(y)))) >> (Limb::BITS - 1); - CtChoice::from_lsb(bit) - } - - /// Returns the truthy value if `lhs <= rhs` and the falsy value otherwise. - #[inline] - pub(crate) const fn ct_le(lhs: Self, rhs: Self) -> CtChoice { - let x = lhs.0; - let y = rhs.0; - let bit = (((!x) | y) & ((x ^ y) | !(y.wrapping_sub(x)))) >> (Limb::BITS - 1); - CtChoice::from_lsb(bit) + CtChoice::from_word_nonzero(self.0) } } diff --git a/src/limb/rand.rs b/src/limb/rand.rs index 43471682d..bfaf62ebe 100644 --- a/src/limb/rand.rs +++ b/src/limb/rand.rs @@ -21,9 +21,9 @@ impl RandomMod for Limb { fn random_mod(rng: &mut impl CryptoRngCore, modulus: &NonZero) -> Self { let mut bytes = ::Repr::default(); - let n_bits = modulus.bits(); + let n_bits = modulus.bits() as usize; let n_bytes = (n_bits + 7) / 8; - let mask = 0xff >> (8 * n_bytes - n_bits); + let mask = 0xffu8 >> (8 * n_bytes - n_bits); loop { rng.fill_bytes(&mut bytes[..n_bytes]); diff --git a/src/limb/shl.rs b/src/limb/shl.rs index 88e37f01e..03e4a1035 100644 --- a/src/limb/shl.rs +++ b/src/limb/shl.rs @@ -1,46 +1,30 @@ //! Limb left bitshift -use crate::{Limb, Word}; +use crate::Limb; use core::ops::{Shl, ShlAssign}; impl Limb { - /// Computes `self << rhs`. - /// Panics if `rhs` overflows `Limb::BITS`. + /// Computes `self << shift`. + /// Panics if `shift` overflows `Limb::BITS`. #[inline(always)] - pub const fn shl(self, rhs: Self) -> Self { - Limb(self.0 << rhs.0) + pub const fn shl(self, shift: u32) -> Self { + Limb(self.0 << shift) } } -impl Shl for Limb { +impl Shl for Limb { type Output = Self; #[inline(always)] - fn shl(self, rhs: Self) -> Self::Output { - self.shl(rhs) + fn shl(self, shift: u32) -> Self::Output { + self.shl(shift) } } -impl Shl for Limb { - type Output = Self; - - #[inline(always)] - fn shl(self, rhs: usize) -> Self::Output { - self.shl(Limb(rhs as Word)) - } -} - -impl ShlAssign for Limb { - #[inline(always)] - fn shl_assign(&mut self, other: Self) { - *self = self.shl(other); - } -} - -impl ShlAssign for Limb { +impl ShlAssign for Limb { #[inline(always)] - fn shl_assign(&mut self, other: usize) { - *self = self.shl(Limb(other as Word)); + fn shl_assign(&mut self, shift: u32) { + *self = self.shl(shift); } } diff --git a/src/limb/shr.rs b/src/limb/shr.rs index 7c422e045..a91c65d54 100644 --- a/src/limb/shr.rs +++ b/src/limb/shr.rs @@ -1,46 +1,30 @@ //! Limb right bitshift -use crate::{Limb, Word}; +use crate::Limb; use core::ops::{Shr, ShrAssign}; impl Limb { - /// Computes `self >> rhs`. - /// Panics if `rhs` overflows `Limb::BITS`. + /// Computes `self >> shift`. + /// Panics if `shift` overflows `Limb::BITS`. #[inline(always)] - pub const fn shr(self, rhs: Self) -> Self { - Limb(self.0 >> rhs.0) + pub const fn shr(self, shift: u32) -> Self { + Limb(self.0 >> shift) } } -impl Shr for Limb { +impl Shr for Limb { type Output = Self; #[inline(always)] - fn shr(self, rhs: Self) -> Self::Output { - self.shr(rhs) + fn shr(self, shift: u32) -> Self::Output { + self.shr(shift) } } -impl Shr for Limb { - type Output = Self; - - #[inline(always)] - fn shr(self, rhs: usize) -> Self::Output { - self.shr(Limb(rhs as Word)) - } -} - -impl ShrAssign for Limb { - #[inline(always)] - fn shr_assign(&mut self, other: Self) { - *self = self.shr(other); - } -} - -impl ShrAssign for Limb { +impl ShrAssign for Limb { #[inline(always)] - fn shr_assign(&mut self, other: usize) { - *self = self.shr(Limb(other as Word)); + fn shr_assign(&mut self, shift: u32) { + *self = self.shr(shift); } } diff --git a/src/macros.rs b/src/macros.rs index 49aef10af..a291f015f 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -59,7 +59,7 @@ macro_rules! const_assert_ne { #[macro_export] macro_rules! nlimbs { ($bits:expr) => { - $bits / $crate::Limb::BITS + $bits / $crate::Limb::BITS as usize }; } diff --git a/src/modular/boxed_residue.rs b/src/modular/boxed_residue.rs index d7277340e..536b60d87 100644 --- a/src/modular/boxed_residue.rs +++ b/src/modular/boxed_residue.rs @@ -67,8 +67,7 @@ impl BoxedResidueParams { // we can take the modulo right away and calculate the inverse of the first limb only. let modulus_lo = BoxedUint::from(modulus.limbs.get(0).copied().unwrap_or_default()); - let mod_neg_inv = - Limb(Word::MIN.wrapping_sub(modulus_lo.inv_mod2k(Word::BITS as usize).limbs[0].0)); + let mod_neg_inv = Limb(Word::MIN.wrapping_sub(modulus_lo.inv_mod2k(Word::BITS).limbs[0].0)); let r3 = montgomery_reduction_boxed(&mut r2.square(), &modulus, mod_neg_inv); @@ -89,7 +88,7 @@ impl BoxedResidueParams { } /// Bits of precision in the modulus. - pub fn bits_precision(&self) -> usize { + pub fn bits_precision(&self) -> u32 { self.modulus.bits_precision() } } @@ -132,7 +131,7 @@ impl BoxedResidue { } /// Bits of precision in the modulus. - pub fn bits_precision(&self) -> usize { + pub fn bits_precision(&self) -> u32 { self.residue_params.bits_precision() } diff --git a/src/modular/boxed_residue/pow.rs b/src/modular/boxed_residue/pow.rs index 04d1b298b..f65750a15 100644 --- a/src/modular/boxed_residue/pow.rs +++ b/src/modular/boxed_residue/pow.rs @@ -18,7 +18,7 @@ impl BoxedResidue { /// to take into account for the exponent. /// /// NOTE: `exponent_bits` may be leaked in the time pattern. - pub fn pow_bounded_exp(&self, exponent: &BoxedUint, exponent_bits: usize) -> Self { + pub fn pow_bounded_exp(&self, exponent: &BoxedUint, exponent_bits: u32) -> Self { Self { montgomery_form: pow_montgomery_form( &self.montgomery_form, @@ -34,7 +34,7 @@ impl BoxedResidue { } impl PowBoundedExp for BoxedResidue { - fn pow_bounded_exp(&self, exponent: &BoxedUint, exponent_bits: usize) -> Self { + fn pow_bounded_exp(&self, exponent: &BoxedUint, exponent_bits: u32) -> Self { self.pow_bounded_exp(exponent, exponent_bits) } } @@ -46,7 +46,7 @@ impl PowBoundedExp for BoxedResidue { fn pow_montgomery_form( x: &BoxedUint, exponent: &BoxedUint, - exponent_bits: usize, + exponent_bits: u32, modulus: &BoxedUint, r: &BoxedUint, mod_neg_inv: Limb, @@ -55,7 +55,7 @@ fn pow_montgomery_form( return r.clone(); // 1 in Montgomery form } - const WINDOW: usize = 4; + const WINDOW: u32 = 4; const WINDOW_MASK: Word = (1 << WINDOW) - 1; // powers[i] contains x^i @@ -67,7 +67,7 @@ fn pow_montgomery_form( i += 1; } - let starting_limb = (exponent_bits - 1) / Limb::BITS; + let starting_limb = ((exponent_bits - 1) / Limb::BITS) as usize; let starting_bit_in_limb = (exponent_bits - 1) % Limb::BITS; let starting_window = starting_bit_in_limb / WINDOW; let starting_window_mask = (1 << (starting_bit_in_limb % WINDOW + 1)) - 1; @@ -103,7 +103,7 @@ fn pow_montgomery_form( let mut power = powers[0].clone(); let mut i = 1; while i < 1 << WINDOW { - power = BoxedUint::conditional_select(&power, &powers[i], (i as Word).ct_eq(&idx)); + power = BoxedUint::conditional_select(&power, &powers[i as usize], i.ct_eq(&idx)); i += 1; } diff --git a/src/modular/dyn_residue.rs b/src/modular/dyn_residue.rs index ca3d53b96..f00901b37 100644 --- a/src/modular/dyn_residue.rs +++ b/src/modular/dyn_residue.rs @@ -43,9 +43,8 @@ impl DynResidueParams { // Since we are calculating the inverse modulo (Word::MAX+1), // we can take the modulo right away and calculate the inverse of the first limb only. let modulus_lo = Uint::<1>::from_words([modulus.limbs[0].0]); - let mod_neg_inv = Limb( - Word::MIN.wrapping_sub(modulus_lo.inv_mod2k_vartime(Word::BITS as usize).limbs[0].0), - ); + let mod_neg_inv = + Limb(Word::MIN.wrapping_sub(modulus_lo.inv_mod2k_vartime(Word::BITS).limbs[0].0)); let r3 = montgomery_reduction(&r2.square_wide(), modulus, mod_neg_inv); diff --git a/src/modular/dyn_residue/pow.rs b/src/modular/dyn_residue/pow.rs index e89b7b98f..5749e4a08 100644 --- a/src/modular/dyn_residue/pow.rs +++ b/src/modular/dyn_residue/pow.rs @@ -26,7 +26,7 @@ impl DynResidue { pub const fn pow_bounded_exp( &self, exponent: &Uint, - exponent_bits: usize, + exponent_bits: u32, ) -> Self { Self { montgomery_form: pow_montgomery_form( @@ -45,7 +45,7 @@ impl DynResidue { impl PowBoundedExp> for DynResidue { - fn pow_bounded_exp(&self, exponent: &Uint, exponent_bits: usize) -> Self { + fn pow_bounded_exp(&self, exponent: &Uint, exponent_bits: u32) -> Self { self.pow_bounded_exp(exponent, exponent_bits) } } @@ -56,7 +56,7 @@ impl { fn multi_exponentiate_bounded_exp( bases_and_exponents: &[(Self, Uint); N], - exponent_bits: usize, + exponent_bits: u32, ) -> Self { const_assert_ne!(N, 0, "bases_and_exponents must not be empty"); let residue_params = bases_and_exponents[0].0.residue_params; @@ -90,7 +90,7 @@ impl { fn multi_exponentiate_bounded_exp( bases_and_exponents: &[(Self, Uint)], - exponent_bits: usize, + exponent_bits: u32, ) -> Self { assert!( !bases_and_exponents.is_empty(), diff --git a/src/modular/pow.rs b/src/modular/pow.rs index f09bc4c6c..5f6d74e8e 100644 --- a/src/modular/pow.rs +++ b/src/modular/pow.rs @@ -1,11 +1,11 @@ -use crate::{Limb, Uint, Word}; +use crate::{CtChoice, Limb, Uint, Word}; use super::mul::{mul_montgomery_form, square_montgomery_form}; #[cfg(feature = "alloc")] use alloc::vec::Vec; -const WINDOW: usize = 4; +const WINDOW: u32 = 4; const WINDOW_MASK: Word = (1 << WINDOW) - 1; /// Performs modular exponentiation using Montgomery's ladder. @@ -15,7 +15,7 @@ const WINDOW_MASK: Word = (1 << WINDOW) - 1; pub const fn pow_montgomery_form( x: &Uint, exponent: &Uint, - exponent_bits: usize, + exponent_bits: u32, modulus: &Uint, r: &Uint, mod_neg_inv: Limb, @@ -35,7 +35,7 @@ pub const fn multi_exponentiate_montgomery_form_array< const N: usize, >( bases_and_exponents: &[(Uint, Uint); N], - exponent_bits: usize, + exponent_bits: u32, modulus: &Uint, r: &Uint, mod_neg_inv: Limb, @@ -72,7 +72,7 @@ pub const fn multi_exponentiate_montgomery_form_array< #[cfg(feature = "alloc")] pub fn multi_exponentiate_montgomery_form_slice( bases_and_exponents: &[(Uint, Uint)], - exponent_bits: usize, + exponent_bits: u32, modulus: &Uint, r: &Uint, mod_neg_inv: Limb, @@ -117,12 +117,12 @@ const fn compute_powers( const fn multi_exponentiate_montgomery_form_internal( powers_and_exponents: &[([Uint; 1 << WINDOW], Uint)], - exponent_bits: usize, + exponent_bits: u32, modulus: &Uint, r: &Uint, mod_neg_inv: Limb, ) -> Uint { - let starting_limb = (exponent_bits - 1) / Limb::BITS; + let starting_limb = ((exponent_bits - 1) / Limb::BITS) as usize; let starting_bit_in_limb = (exponent_bits - 1) % Limb::BITS; let starting_window = starting_bit_in_limb / WINDOW; let starting_window_mask = (1 << (starting_bit_in_limb % WINDOW + 1)) - 1; @@ -163,8 +163,8 @@ const fn multi_exponentiate_montgomery_form_internal::ct_select(&power, &powers[j], choice); + let choice = CtChoice::from_word_eq(j, idx); + power = Uint::::ct_select(&power, &powers[j as usize], choice); j += 1; } diff --git a/src/modular/residue/macros.rs b/src/modular/residue/macros.rs index 3a03b75bd..de3bb2afd 100644 --- a/src/modular/residue/macros.rs +++ b/src/modular/residue/macros.rs @@ -39,7 +39,7 @@ macro_rules! impl_modulus { const MOD_NEG_INV: $crate::Limb = $crate::Limb( $crate::Word::MIN.wrapping_sub( Self::MODULUS - .inv_mod2k_vartime($crate::Word::BITS as usize) + .inv_mod2k_vartime($crate::Word::BITS) .as_limbs()[0] .0, ), diff --git a/src/modular/residue/pow.rs b/src/modular/residue/pow.rs index cca9659ae..69bca9f37 100644 --- a/src/modular/residue/pow.rs +++ b/src/modular/residue/pow.rs @@ -26,7 +26,7 @@ impl, const LIMBS: usize> Residue { pub const fn pow_bounded_exp( &self, exponent: &Uint, - exponent_bits: usize, + exponent_bits: u32, ) -> Residue { Self { montgomery_form: pow_montgomery_form( @@ -45,7 +45,7 @@ impl, const LIMBS: usize> Residue { impl, const LIMBS: usize, const RHS_LIMBS: usize> PowBoundedExp> for Residue { - fn pow_bounded_exp(&self, exponent: &Uint, exponent_bits: usize) -> Self { + fn pow_bounded_exp(&self, exponent: &Uint, exponent_bits: u32) -> Self { self.pow_bounded_exp(exponent, exponent_bits) } } @@ -56,7 +56,7 @@ impl, const LIMBS: usize, const RHS_LI { fn multi_exponentiate_bounded_exp( bases_and_exponents: &[(Self, Uint); N], - exponent_bits: usize, + exponent_bits: u32, ) -> Self { let mut bases_and_exponents_montgomery_form = [(Uint::::ZERO, Uint::::ZERO); N]; @@ -88,7 +88,7 @@ impl, const LIMBS: usize, const RHS_LIMBS: usize> { fn multi_exponentiate_bounded_exp( bases_and_exponents: &[(Self, Uint)], - exponent_bits: usize, + exponent_bits: u32, ) -> Self { let bases_and_exponents: Vec<(Uint, Uint)> = bases_and_exponents .iter() diff --git a/src/non_zero.rs b/src/non_zero.rs index bd630db6b..96c98c31a 100644 --- a/src/non_zero.rs +++ b/src/non_zero.rs @@ -61,7 +61,7 @@ where T: Bounded + Zero, { /// Total size of the represented integer in bits. - pub const BITS: usize = T::BITS; + pub const BITS: u32 = T::BITS; /// Total size of the represented integer in bytes. pub const BYTES: usize = T::BYTES; diff --git a/src/traits.rs b/src/traits.rs index e63719fb0..81edcd15d 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -17,7 +17,7 @@ use rand_core::CryptoRngCore; /// Integers whose representation takes a bounded amount of space. pub trait Bounded { /// Size of this integer in bits. - const BITS: usize; + const BITS: u32; /// Size of this integer in bytes. const BYTES: usize; @@ -65,10 +65,10 @@ pub trait Integer: + for<'a> Rem<&'a NonZero, Output = Self> + Send + Sized - + Shl - + ShlAssign - + Shr - + ShrAssign + + Shl + + ShlAssign + + Shr + + ShrAssign + SubMod + Sync + Zero @@ -77,20 +77,20 @@ pub trait Integer: fn one() -> Self; /// Calculate the number of bits required to represent a given number. - fn bits(&self) -> usize; + fn bits(&self) -> u32; /// Calculate the number of bits required to represent a given number in variable-time with /// respect to `self`. - fn bits_vartime(&self) -> usize; + fn bits_vartime(&self) -> u32; /// Precision of this integer in bits. - fn bits_precision(&self) -> usize; + fn bits_precision(&self) -> u32; /// Precision of this integer in bytes. fn bytes_precision(&self) -> usize; /// Calculate the number of leading zeros in the binary representation of this number. - fn leading_zeros(&self) -> usize { + fn leading_zeros(&self) -> u32 { self.bits_precision() - self.bits() } @@ -366,7 +366,7 @@ pub trait PowBoundedExp { /// to take into account for the exponent. /// /// NOTE: `exponent_bits` may be leaked in the time pattern. - fn pow_bounded_exp(&self, exponent: &Exponent, exponent_bits: usize) -> Self; + fn pow_bounded_exp(&self, exponent: &Exponent, exponent_bits: u32) -> Self; } /// Performs modular multi-exponentiation using Montgomery's ladder. @@ -404,7 +404,7 @@ where /// Calculates `x1 ^ k1 * ... * xn ^ kn`. fn multi_exponentiate_bounded_exp( bases_and_exponents: &BasesAndExponents, - exponent_bits: usize, + exponent_bits: u32, ) -> Self; } diff --git a/src/uint.rs b/src/uint.rs index 4b6eb4241..fd116fc4c 100644 --- a/src/uint.rs +++ b/src/uint.rs @@ -86,11 +86,11 @@ impl Uint { }; /// Total size of the represented integer in bits. - pub const BITS: usize = LIMBS * Limb::BITS; + pub const BITS: u32 = LIMBS as u32 * Limb::BITS; /// Bit size of `BITS`. - // Note: assumes the type of `BITS` is `usize`. Any way to assert that? - pub(crate) const LOG2_BITS: usize = (usize::BITS - Self::BITS.leading_zeros()) as usize; + // Note: assumes the type of `BITS` is `u32`. Any way to assert that? + pub(crate) const LOG2_BITS: u32 = u32::BITS - Self::BITS.leading_zeros(); /// Total size of the represented integer in bytes. pub const BYTES: usize = LIMBS * Limb::BYTES; @@ -204,7 +204,7 @@ impl ConditionallySelectable for Uint { } impl Bounded for Uint { - const BITS: usize = Self::BITS; + const BITS: u32 = Self::BITS; const BYTES: usize = Self::BYTES; } @@ -228,15 +228,15 @@ impl Integer for Uint { Self::ONE } - fn bits(&self) -> usize { + fn bits(&self) -> u32 { self.bits() } - fn bits_vartime(&self) -> usize { + fn bits_vartime(&self) -> u32 { self.bits_vartime() } - fn bits_precision(&self) -> usize { + fn bits_precision(&self) -> u32 { Self::BITS } diff --git a/src/uint/add.rs b/src/uint/add.rs index e4f7bfa42..94047743e 100644 --- a/src/uint/add.rs +++ b/src/uint/add.rs @@ -24,7 +24,7 @@ impl Uint { /// Perform saturating addition, returning `MAX` on overflow. pub const fn saturating_add(&self, rhs: &Self) -> Self { let (res, overflow) = self.adc(rhs, Limb::ZERO); - Self::ct_select(&res, &Self::MAX, CtChoice::from_lsb(overflow.0)) + Self::ct_select(&res, &Self::MAX, CtChoice::from_word_lsb(overflow.0)) } /// Perform wrapping addition, discarding overflow. @@ -41,7 +41,7 @@ impl Uint { ) -> (Self, CtChoice) { let actual_rhs = Uint::ct_select(&Uint::ZERO, rhs, choice); let (sum, carry) = self.adc(&actual_rhs, Limb::ZERO); - (sum, CtChoice::from_lsb(carry.0)) + (sum, CtChoice::from_word_lsb(carry.0)) } } diff --git a/src/uint/bits.rs b/src/uint/bits.rs index 615d0a04b..70eb584b5 100644 --- a/src/uint/bits.rs +++ b/src/uint/bits.rs @@ -1,25 +1,25 @@ -use crate::{CtChoice, Limb, Uint, Word}; +use crate::{CtChoice, Limb, Uint}; impl Uint { /// Get the value of the bit at position `index`, as a truthy or falsy `CtChoice`. /// Returns the falsy value for indices out of range. - pub const fn bit(&self, index: usize) -> CtChoice { + pub const fn bit(&self, index: u32) -> CtChoice { let limb_num = index / Limb::BITS; let index_in_limb = index % Limb::BITS; let index_mask = 1 << index_in_limb; let limbs = self.as_words(); - let mut result: Word = 0; + let mut result = 0; let mut i = 0; while i < LIMBS { let bit = limbs[i] & index_mask; - let is_right_limb = CtChoice::from_usize_equality(i, limb_num); - result |= is_right_limb.if_true(bit); + let is_right_limb = CtChoice::from_u32_eq(i as u32, limb_num); + result |= is_right_limb.if_true_word(bit); i += 1; } - CtChoice::from_lsb(result >> index_in_limb) + CtChoice::from_word_lsb(result >> index_in_limb) } /// Returns `true` if the bit at position `index` is set, `false` otherwise. @@ -27,54 +27,54 @@ impl Uint { /// # Remarks /// This operation is variable time with respect to `index` only. #[inline(always)] - pub const fn bit_vartime(&self, index: usize) -> bool { + pub const fn bit_vartime(&self, index: u32) -> bool { if index >= Self::BITS { false } else { - (self.limbs[index / Limb::BITS].0 >> (index % Limb::BITS)) & 1 == 1 + (self.limbs[(index / Limb::BITS) as usize].0 >> (index % Limb::BITS)) & 1 == 1 } } /// Calculate the number of bits needed to represent this number. #[inline] - pub const fn bits(&self) -> usize { + pub const fn bits(&self) -> u32 { Self::BITS - self.leading_zeros() } /// Calculate the number of bits needed to represent this number in variable-time with respect /// to `self`. - pub const fn bits_vartime(&self) -> usize { + pub const fn bits_vartime(&self) -> u32 { let mut i = LIMBS - 1; while i > 0 && self.limbs[i].0 == 0 { i -= 1; } let limb = self.limbs[i]; - Limb::BITS * (i + 1) - limb.leading_zeros() + Limb::BITS * (i as u32 + 1) - limb.leading_zeros() } /// Calculate the number of leading zeros in the binary representation of this number. - pub const fn leading_zeros(&self) -> usize { + pub const fn leading_zeros(&self) -> u32 { let limbs = self.as_limbs(); - let mut count: Word = 0; + let mut count = 0; let mut i = LIMBS; let mut nonzero_limb_not_encountered = CtChoice::TRUE; while i > 0 { i -= 1; let l = limbs[i]; - let z = l.leading_zeros() as Word; - count += nonzero_limb_not_encountered.if_true(z); + let z = l.leading_zeros(); + count += nonzero_limb_not_encountered.if_true_u32(z); nonzero_limb_not_encountered = - nonzero_limb_not_encountered.and(l.ct_is_nonzero().not()); + nonzero_limb_not_encountered.and(CtChoice::from_word_nonzero(l.0).not()); } - count as usize + count } /// Calculate the number of leading zeros in the binary representation of this number in /// variable-time with respect to `self`. - pub const fn leading_zeros_vartime(&self) -> usize { + pub const fn leading_zeros_vartime(&self) -> u32 { let limbs = self.as_limbs(); let mut count = 0; @@ -93,27 +93,27 @@ impl Uint { } /// Calculate the number of trailing zeros in the binary representation of this number. - pub const fn trailing_zeros(&self) -> usize { + pub const fn trailing_zeros(&self) -> u32 { let limbs = self.as_limbs(); - let mut count: Word = 0; + let mut count = 0; let mut i = 0; let mut nonzero_limb_not_encountered = CtChoice::TRUE; while i < LIMBS { let l = limbs[i]; - let z = l.trailing_zeros() as Word; - count += nonzero_limb_not_encountered.if_true(z); + let z = l.trailing_zeros(); + count += nonzero_limb_not_encountered.if_true_u32(z); nonzero_limb_not_encountered = - nonzero_limb_not_encountered.and(l.ct_is_nonzero().not()); + nonzero_limb_not_encountered.and(CtChoice::from_word_nonzero(l.0).not()); i += 1; } - count as usize + count } /// Calculate the number of trailing zeros in the binary representation of this number in /// variable-time with respect to `self`. - pub const fn trailing_zeros_vartime(&self) -> usize { + pub const fn trailing_zeros_vartime(&self) -> u32 { let limbs = self.as_limbs(); let mut count = 0; @@ -132,27 +132,27 @@ impl Uint { } /// Calculate the number of trailing ones in the binary representation of this number. - pub const fn trailing_ones(&self) -> usize { + pub const fn trailing_ones(&self) -> u32 { let limbs = self.as_limbs(); - let mut count: Word = 0; + let mut count = 0; let mut i = 0; let mut nonmax_limb_not_encountered = CtChoice::TRUE; while i < LIMBS { let l = limbs[i]; - let z = l.trailing_ones() as Word; - count += nonmax_limb_not_encountered.if_true(z); + let z = l.trailing_ones(); + count += nonmax_limb_not_encountered.if_true_u32(z); nonmax_limb_not_encountered = - nonmax_limb_not_encountered.and(Limb::ct_eq(l, Limb::MAX)); + nonmax_limb_not_encountered.and(CtChoice::from_word_eq(l.0, Limb::MAX.0)); i += 1; } - count as usize + count } /// Calculate the number of trailing ones in the binary representation of this number, /// variable time in `self`. - pub const fn trailing_ones_vartime(&self) -> usize { + pub const fn trailing_ones_vartime(&self) -> u32 { let limbs = self.as_limbs(); let mut count = 0; @@ -171,7 +171,7 @@ impl Uint { } /// Sets the bit at `index` to 0 or 1 depending on the value of `bit_value`. - pub(crate) const fn set_bit(self, index: usize, bit_value: CtChoice) -> Self { + pub(crate) const fn set_bit(self, index: u32, bit_value: CtChoice) -> Self { let mut result = self; let limb_num = index / Limb::BITS; let index_in_limb = index % Limb::BITS; @@ -179,10 +179,10 @@ impl Uint { let mut i = 0; while i < LIMBS { - let is_right_limb = CtChoice::from_usize_equality(i, limb_num); + let is_right_limb = CtChoice::from_u32_eq(i as u32, limb_num); let old_limb = result.limbs[i].0; - let new_limb = bit_value.select(old_limb & !index_mask, old_limb | index_mask); - result.limbs[i] = Limb(is_right_limb.select(old_limb, new_limb)); + let new_limb = bit_value.select_word(old_limb & !index_mask, old_limb | index_mask); + result.limbs[i] = Limb(is_right_limb.select_word(old_limb, new_limb)); i += 1; } result @@ -193,7 +193,7 @@ impl Uint { mod tests { use crate::{CtChoice, U256}; - fn uint_with_bits_at(positions: &[usize]) -> U256 { + fn uint_with_bits_at(positions: &[u32]) -> U256 { let mut result = U256::ZERO; for pos in positions { result |= U256::ONE << *pos; diff --git a/src/uint/boxed.rs b/src/uint/boxed.rs index 39fe1ed38..62b5f4916 100644 --- a/src/uint/boxed.rs +++ b/src/uint/boxed.rs @@ -60,14 +60,14 @@ impl BoxedUint { /// Get the value `0` with the given number of bits of precision. /// /// Panics if the precision is not a multiple of [`Limb::BITS`]. - pub fn zero_with_precision(bits_precision: usize) -> Self { + pub fn zero_with_precision(bits_precision: u32) -> Self { assert_eq!( bits_precision % Limb::BITS, 0, "precision is not a multiple of limb size" ); - vec![Limb::ZERO; bits_precision / Limb::BITS].into() + vec![Limb::ZERO; (bits_precision / Limb::BITS) as usize].into() } /// Get the value `1`, represented as succinctly as possible. @@ -81,7 +81,7 @@ impl BoxedUint { /// /// Panics if the precision is not at least [`Limb::BITS`] or if it is not /// a multiple thereof. - pub fn one_with_precision(bits_precision: usize) -> Self { + pub fn one_with_precision(bits_precision: u32) -> Self { assert!(bits_precision >= Limb::BITS, "precision too small"); let mut ret = Self::zero_with_precision(bits_precision); ret.limbs[0] = Limb::ONE; @@ -128,14 +128,14 @@ impl BoxedUint { /// Get the maximum value for a given number of bits of precision. /// /// Panics if the precision is not a multiple of [`Limb::BITS`]. - pub fn max(bits_precision: usize) -> Self { + pub fn max(bits_precision: u32) -> Self { assert_eq!( bits_precision % Limb::BITS, 0, "precision is not a multiple of limb size" ); - vec![Limb::MAX; bits_precision / Limb::BITS].into() + vec![Limb::MAX; (bits_precision / Limb::BITS) as usize].into() } /// Create a [`BoxedUint`] from an array of [`Word`]s (i.e. word-sized unsigned @@ -237,7 +237,7 @@ impl BoxedUint { /// /// Panics if `bits_precision` is not a multiple of `Limb::BITS` or smaller than the current /// precision. - pub fn widen(&self, bits_precision: usize) -> BoxedUint { + pub fn widen(&self, bits_precision: u32) -> BoxedUint { assert!(bits_precision % Limb::BITS == 0); assert!(bits_precision >= self.bits_precision()); @@ -250,7 +250,7 @@ impl BoxedUint { /// /// Panics if `bits_precision` is not a multiple of `Limb::BITS` or smaller than the current /// precision. - pub fn shorten(&self, bits_precision: usize) -> BoxedUint { + pub fn shorten(&self, bits_precision: u32) -> BoxedUint { assert!(bits_precision % Limb::BITS == 0); assert!(bits_precision <= self.bits_precision()); let mut ret = BoxedUint::zero_with_precision(bits_precision); @@ -306,7 +306,7 @@ impl NonZero { /// Widen this type's precision to the given number of bits. /// /// See [`BoxedUint::widen`] for more information, including panic conditions. - pub fn widen(&self, bits_precision: usize) -> Self { + pub fn widen(&self, bits_precision: u32) -> Self { NonZero(self.0.widen(bits_precision)) } } @@ -408,15 +408,15 @@ impl Integer for BoxedUint { Self::one() } - fn bits(&self) -> usize { + fn bits(&self) -> u32 { self.bits() } - fn bits_vartime(&self) -> usize { + fn bits_vartime(&self) -> u32 { self.bits_vartime() } - fn bits_precision(&self) -> usize { + fn bits_precision(&self) -> u32 { self.bits_precision() } diff --git a/src/uint/boxed/bits.rs b/src/uint/boxed/bits.rs index d7bc8672c..fa681d224 100644 --- a/src/uint/boxed/bits.rs +++ b/src/uint/boxed/bits.rs @@ -1,6 +1,6 @@ //! Bit manipulation functions. -use crate::{BoxedUint, Limb, Word, Zero}; +use crate::{BoxedUint, Limb, Zero}; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq}; impl BoxedUint { @@ -8,7 +8,7 @@ impl BoxedUint { /// set bit. /// /// Use [`BoxedUint::bits_precision`] to get the total capacity of this integer. - pub fn bits(&self) -> usize { + pub fn bits(&self) -> u32 { // Use `u32` because `subtle` can't select on `usize` and it matches what `core` uses for // the return value of `leading_zeros` let mut leading_zeros = 0u32; @@ -18,52 +18,52 @@ impl BoxedUint { n.conditional_assign(&(n + 1), !limb.is_zero() | !n.ct_eq(&0)); // Set `leading_zeros` for the first nonzero limb we encounter - leading_zeros.conditional_assign(&(limb.leading_zeros() as u32), n.ct_eq(&1)); + leading_zeros.conditional_assign(&limb.leading_zeros(), n.ct_eq(&1)); } - Limb::BITS * (n as usize) - (leading_zeros as usize) + Limb::BITS * n - leading_zeros } /// Calculate the number of bits needed to represent this number in variable-time with respect /// to `self`. - pub fn bits_vartime(&self) -> usize { + pub fn bits_vartime(&self) -> u32 { let mut i = self.nlimbs() - 1; while i > 0 && self.limbs[i].0 == 0 { i -= 1; } let limb = self.limbs[i]; - Limb::BITS * (i + 1) - limb.leading_zeros() + Limb::BITS * (i as u32 + 1) - limb.leading_zeros() } /// Get the precision of this [`BoxedUint`] in bits. - pub fn bits_precision(&self) -> usize { - self.limbs.len() * Limb::BITS + pub fn bits_precision(&self) -> u32 { + self.limbs.len() as u32 * Limb::BITS } /// Calculate the number of trailing zeros in the binary representation of this number. - pub fn trailing_zeros(&self) -> usize { - let mut count: Word = 0; + pub fn trailing_zeros(&self) -> u32 { + let mut count = 0; let mut nonzero_limb_not_encountered = Choice::from(1u8); for l in &*self.limbs { - let z = l.trailing_zeros() as Word; - count += Word::conditional_select(&0, &z, nonzero_limb_not_encountered); + let z = l.trailing_zeros(); + count += u32::conditional_select(&0, &z, nonzero_limb_not_encountered); nonzero_limb_not_encountered &= l.is_zero(); } - count as usize + count } /// Sets the bit at `index` to 0 or 1 depending on the value of `bit_value`. - pub(crate) fn set_bit(&mut self, index: usize, bit_value: Choice) { - let limb_num = index / Limb::BITS; + pub(crate) fn set_bit(&mut self, index: u32, bit_value: Choice) { + let limb_num = (index / Limb::BITS) as usize; let index_in_limb = index % Limb::BITS; let index_mask = 1 << index_in_limb; for i in 0..self.nlimbs() { let limb = &mut self.limbs[i]; - let is_right_limb = (i as Word).ct_eq(&(limb_num as Word)); + let is_right_limb = i.ct_eq(&limb_num); let old_limb = *limb; let new_limb = Limb::conditional_select( &Limb(old_limb.0 & !index_mask), @@ -81,7 +81,7 @@ mod tests { use hex_literal::hex; use subtle::Choice; - fn uint_with_bits_at(positions: &[usize]) -> BoxedUint { + fn uint_with_bits_at(positions: &[u32]) -> BoxedUint { let mut result = BoxedUint::zero_with_precision(256); for &pos in positions { result |= BoxedUint::one_with_precision(256).shl_vartime(pos); diff --git a/src/uint/boxed/cmp.rs b/src/uint/boxed/cmp.rs index 5701727f8..a3bf5b0a6 100644 --- a/src/uint/boxed/cmp.rs +++ b/src/uint/boxed/cmp.rs @@ -30,7 +30,7 @@ impl ConstantTimeGreater for BoxedUint { #[inline] fn ct_gt(&self, other: &Self) -> Choice { let (_, borrow) = other.sbb(self, Limb::ZERO); - CtChoice::from_mask(borrow.0).into() + CtChoice::from_word_mask(borrow.0).into() } } @@ -38,7 +38,7 @@ impl ConstantTimeLess for BoxedUint { #[inline] fn ct_lt(&self, other: &Self) -> Choice { let (_, borrow) = self.sbb(other, Limb::ZERO); - CtChoice::from_mask(borrow.0).into() + CtChoice::from_word_mask(borrow.0).into() } } diff --git a/src/uint/boxed/encoding.rs b/src/uint/boxed/encoding.rs index b9bf4a139..ab4b0c0ad 100644 --- a/src/uint/boxed/encoding.rs +++ b/src/uint/boxed/encoding.rs @@ -36,7 +36,7 @@ impl BoxedUint { /// /// If the length of `bytes` (when interpreted as bits) is larger than `bits_precision`, this /// function will return [`DecodeError::InputSize`]. - pub fn from_be_slice(bytes: &[u8], bits_precision: usize) -> Result { + pub fn from_be_slice(bytes: &[u8], bits_precision: u32) -> Result { if bytes.is_empty() && bits_precision == 0 { return Ok(Self::zero()); } @@ -45,7 +45,7 @@ impl BoxedUint { return Err(DecodeError::Precision); } - if bytes.len() % Limb::BYTES != 0 || bytes.len() * 8 > bits_precision { + if bytes.len() % Limb::BYTES != 0 || bytes.len() * 8 > bits_precision as usize { return Err(DecodeError::InputSize); } @@ -66,7 +66,7 @@ impl BoxedUint { /// /// If the length of `bytes` (when interpreted as bits) is larger than `bits_precision`, this /// function will return [`DecodeError::InputSize`]. - pub fn from_le_slice(bytes: &[u8], bits_precision: usize) -> Result { + pub fn from_le_slice(bytes: &[u8], bits_precision: u32) -> Result { if bytes.is_empty() && bits_precision == 0 { return Ok(Self::zero()); } @@ -75,7 +75,7 @@ impl BoxedUint { return Err(DecodeError::Precision); } - if bytes.len() % Limb::BYTES != 0 || bytes.len() * 8 > bits_precision { + if bytes.len() % Limb::BYTES != 0 || bytes.len() * 8 > bits_precision as usize { return Err(DecodeError::InputSize); } diff --git a/src/uint/boxed/inv_mod.rs b/src/uint/boxed/inv_mod.rs index ad992a011..26a04bb0d 100644 --- a/src/uint/boxed/inv_mod.rs +++ b/src/uint/boxed/inv_mod.rs @@ -1,6 +1,6 @@ //! [`BoxedUint`] modular inverse (i.e. reciprocal) operations. -use crate::{BoxedUint, Word}; +use crate::BoxedUint; use subtle::{Choice, ConstantTimeEq, ConstantTimeLess, CtOption}; impl BoxedUint { @@ -18,7 +18,7 @@ impl BoxedUint { let (a, a_is_some) = self.inv_odd_mod(&s); let b = self.inv_mod2k(k); // inverse modulo 2^k exists either if `k` is 0 or if `self` is odd. - let b_is_some = (k as Word).ct_eq(&0) | self.is_odd(); + let b_is_some = k.ct_eq(&0) | self.is_odd(); // Restore from RNS: // self^{-1} = a mod s = b mod 2^k @@ -40,7 +40,7 @@ impl BoxedUint { /// Computes 1/`self` mod `2^k`. /// /// Conditions: `self` < 2^k and `self` must be odd - pub(crate) fn inv_mod2k(&self, k: usize) -> Self { + pub(crate) fn inv_mod2k(&self, k: u32) -> Self { // This is the same algorithm as in `inv_mod2k_vartime()`, // but made constant-time w.r.t `k` as well. @@ -50,7 +50,7 @@ impl BoxedUint { for i in 0..self.bits_precision() { // Only iterations for i = 0..k need to change `x`, // the rest are dummy ones performed for the sake of constant-timeness. - let within_range = (i as Word).ct_lt(&(k as Word)); + let within_range = i.ct_lt(&k); // X_i = b_i mod 2 let x_i = b.limbs[0].0 & 1; @@ -86,12 +86,7 @@ impl BoxedUint { /// **Note:** variable time in `bits` and `modulus_bits`. /// /// The algorithm is the same as in GMP 6.2.1's `mpn_sec_invert`. - fn inv_odd_mod_bounded( - &self, - modulus: &Self, - bits: usize, - modulus_bits: usize, - ) -> (Self, Choice) { + fn inv_odd_mod_bounded(&self, modulus: &Self, bits: u32, modulus_bits: u32) -> (Self, Choice) { debug_assert_eq!(self.bits_precision(), modulus.bits_precision()); let bits_precision = self.bits_precision(); diff --git a/src/uint/boxed/rand.rs b/src/uint/boxed/rand.rs index 74df0375b..386cfec51 100644 --- a/src/uint/boxed/rand.rs +++ b/src/uint/boxed/rand.rs @@ -6,7 +6,7 @@ use rand_core::CryptoRngCore; impl BoxedUint { /// Generate a cryptographically secure random [`BoxedUint`]. - pub fn random(mut rng: &mut impl CryptoRngCore, bits_precision: usize) -> Self { + pub fn random(mut rng: &mut impl CryptoRngCore, bits_precision: u32) -> Self { let mut ret = BoxedUint::zero_with_precision(bits_precision); for limb in &mut *ret.limbs { diff --git a/src/uint/boxed/shl.rs b/src/uint/boxed/shl.rs index f09d6a148..469da8bda 100644 --- a/src/uint/boxed/shl.rs +++ b/src/uint/boxed/shl.rs @@ -1,6 +1,6 @@ //! [`BoxedUint`] bitwise left shift operations. -use crate::{BoxedUint, Limb, Word}; +use crate::{BoxedUint, CtChoice, Limb, Word}; use core::ops::{Shl, ShlAssign}; use subtle::{Choice, ConstantTimeLess}; @@ -8,30 +8,26 @@ impl BoxedUint { /// Computes `self << shift` where `0 <= shift < Limb::BITS`, /// returning the result and the carry. #[inline(always)] - pub(crate) fn shl_limb(&self, n: usize) -> (Self, Limb) { + pub(crate) fn shl_limb(&self, shift: u32) -> (Self, Limb) { let nlimbs = self.nlimbs(); let mut limbs = vec![Limb::ZERO; nlimbs].into_boxed_slice(); - let nz = Limb(n as Word).ct_is_nonzero(); - let lshift = n as Word; - let rshift = Limb::ct_select(Limb::ZERO, Limb((Limb::BITS - n) as Word), nz).0; - let carry = Limb::ct_select( - Limb::ZERO, - Limb(self.limbs[nlimbs - 1].0.wrapping_shr(Word::BITS - n as u32)), - nz, - ); + let nz = CtChoice::from_u32_nonzero(shift); + let lshift = shift; + let rshift = nz.if_true_u32(Limb::BITS - shift); + let carry = nz.if_true_word(self.limbs[nlimbs - 1].0.wrapping_shr(Word::BITS - shift)); let mut i = nlimbs - 1; while i > 0 { let mut limb = self.limbs[i].0 << lshift; let hi = self.limbs[i - 1].0 >> rshift; - limb |= nz.if_true(hi); + limb |= nz.if_true_word(hi); limbs[i] = Limb(limb); i -= 1 } limbs[0] = Limb(self.limbs[0].0 << lshift); - (Self { limbs }, carry) + (Self { limbs }, Limb(carry)) } /// Computes `self << shift`. @@ -40,15 +36,15 @@ impl BoxedUint { /// /// When used with a fixed `shift`, this function is constant-time with respect to `self`. #[inline(always)] - pub fn shl_vartime(&self, shift: usize) -> Self { + pub fn shl_vartime(&self, shift: u32) -> Self { let nlimbs = self.nlimbs(); let mut limbs = vec![Limb::ZERO; nlimbs].into_boxed_slice(); - if shift >= Limb::BITS * nlimbs { + if shift >= self.bits_precision() { return Self { limbs }; } - let shift_num = shift / Limb::BITS; + let shift_num = (shift / Limb::BITS) as usize; let rem = shift % Limb::BITS; let mut i = nlimbs; @@ -61,16 +57,16 @@ impl BoxedUint { new_lower } - /// Computes `self << n`. - /// Returns zero if `n >= Self::BITS`. - pub fn shl(&self, shift: usize) -> Self { - let overflow = !(shift as Word).ct_lt(&(self.bits_precision() as Word)); + /// Computes `self << shift`. + /// Returns zero if `shift >= Self::BITS`. + pub fn shl(&self, shift: u32) -> Self { + let overflow = !shift.ct_lt(&self.bits_precision()); let shift = shift % self.bits_precision(); - let log2_bits = (usize::BITS - self.bits_precision().leading_zeros()) as usize; + let log2_bits = u32::BITS - self.bits_precision().leading_zeros(); let mut result = self.clone(); for i in 0..log2_bits { - let bit = Choice::from(((shift as Word >> i) & 1) as u8); + let bit = Choice::from(((shift >> i) & 1) as u8); result = Self::conditional_select(&result, &result.shl_vartime(1 << i), bit); } @@ -82,38 +78,38 @@ impl BoxedUint { } } -impl Shl for BoxedUint { +impl Shl for BoxedUint { type Output = BoxedUint; - /// NOTE: this operation is variable time with respect to `rhs` *ONLY*. + /// NOTE: this operation is variable time with respect to `shift` *ONLY*. /// - /// When used with a fixed `rhs`, this function is constant-time with respect + /// When used with a fixed `shift`, this function is constant-time with respect /// to `self`. - fn shl(self, rhs: usize) -> BoxedUint { - Self::shl(&self, rhs) + fn shl(self, shift: u32) -> BoxedUint { + Self::shl(&self, shift) } } -impl Shl for &BoxedUint { +impl Shl for &BoxedUint { type Output = BoxedUint; - /// NOTE: this operation is variable time with respect to `rhs` *ONLY*. + /// NOTE: this operation is variable time with respect to `shift` *ONLY*. /// - /// When used with a fixed `rhs`, this function is constant-time with respect + /// When used with a fixed `shift`, this function is constant-time with respect /// to `self`. - fn shl(self, rhs: usize) -> BoxedUint { - self.shl(rhs) + fn shl(self, shift: u32) -> BoxedUint { + self.shl(shift) } } -impl ShlAssign for BoxedUint { - /// NOTE: this operation is variable time with respect to `rhs` *ONLY*. +impl ShlAssign for BoxedUint { + /// NOTE: this operation is variable time with respect to `shift` *ONLY*. /// - /// When used with a fixed `rhs`, this function is constant-time with respect + /// When used with a fixed `shift`, this function is constant-time with respect /// to `self`. - fn shl_assign(&mut self, rhs: usize) { + fn shl_assign(&mut self, shift: u32) { // TODO(tarcieri): in-place implementation that avoids clone - *self = self.clone().shl(rhs) + *self = self.clone().shl(shift) } } diff --git a/src/uint/boxed/shr.rs b/src/uint/boxed/shr.rs index 573c0f1ca..57ab5cdda 100644 --- a/src/uint/boxed/shr.rs +++ b/src/uint/boxed/shr.rs @@ -1,6 +1,6 @@ //! [`BoxedUint`] bitwise right shift operations. -use crate::{limb::HI_BIT, BoxedUint, Limb, Word}; +use crate::{limb::HI_BIT, BoxedUint, Limb}; use core::ops::{Shr, ShrAssign}; use subtle::{Choice, ConstantTimeLess}; @@ -36,13 +36,13 @@ impl BoxedUint { /// /// When used with a fixed `shift`, this function is constant-time with respect to `self`. #[inline(always)] - pub fn shr_vartime(&self, shift: usize) -> Self { + pub fn shr_vartime(&self, shift: u32) -> Self { let nlimbs = self.nlimbs(); - let full_shifts = shift / Limb::BITS; + let full_shifts = (shift / Limb::BITS) as usize; let small_shift = shift & (Limb::BITS - 1); let mut limbs = vec![Limb::ZERO; nlimbs].into_boxed_slice(); - if shift > Limb::BITS * nlimbs { + if shift > self.bits_precision() { return Self { limbs }; } @@ -70,16 +70,16 @@ impl BoxedUint { Self { limbs } } - /// Computes `self << n`. - /// Returns zero if `n >= Self::BITS`. - pub fn shr(&self, shift: usize) -> Self { - let overflow = !(shift as Word).ct_lt(&(self.bits_precision() as Word)); + /// Computes `self << shift`. + /// Returns zero if `shift >= Self::BITS`. + pub fn shr(&self, shift: u32) -> Self { + let overflow = !shift.ct_lt(&self.bits_precision()); let shift = shift % self.bits_precision(); - let log2_bits = (usize::BITS - self.bits_precision().leading_zeros()) as usize; + let log2_bits = u32::BITS - self.bits_precision().leading_zeros(); let mut result = self.clone(); for i in 0..log2_bits { - let bit = Choice::from(((shift as Word >> i) & 1) as u8); + let bit = Choice::from(((shift >> i) & 1) as u8); result = Self::conditional_select(&result, &result.shr_vartime(1 << i), bit); } @@ -91,34 +91,34 @@ impl BoxedUint { } } -impl Shr for BoxedUint { +impl Shr for BoxedUint { type Output = BoxedUint; - /// NOTE: this operation is variable time with respect to `rhs` *ONLY*. + /// NOTE: this operation is variable time with respect to `shift` *ONLY*. /// - /// When used with a fixed `rhs`, this function is constant-time with respect + /// When used with a fixed `shift`, this function is constant-time with respect /// to `self`. - fn shr(self, rhs: usize) -> BoxedUint { - Self::shr(&self, rhs) + fn shr(self, shift: u32) -> BoxedUint { + Self::shr(&self, shift) } } -impl Shr for &BoxedUint { +impl Shr for &BoxedUint { type Output = BoxedUint; - /// NOTE: this operation is variable time with respect to `rhs` *ONLY*. + /// NOTE: this operation is variable time with respect to `shift` *ONLY*. /// - /// When used with a fixed `rhs`, this function is constant-time with respect + /// When used with a fixed `shift`, this function is constant-time with respect /// to `self`. - fn shr(self, rhs: usize) -> BoxedUint { - self.shr(rhs) + fn shr(self, shift: u32) -> BoxedUint { + self.shr(shift) } } -impl ShrAssign for BoxedUint { - fn shr_assign(&mut self, rhs: usize) { +impl ShrAssign for BoxedUint { + fn shr_assign(&mut self, shift: u32) { // TODO(tarcieri): in-place implementation that avoids clone - *self = self.clone().shr(rhs); + *self = self.clone().shr(shift); } } diff --git a/src/uint/cmp.rs b/src/uint/cmp.rs index b513242e4..e2740d179 100644 --- a/src/uint/cmp.rs +++ b/src/uint/cmp.rs @@ -44,7 +44,7 @@ impl Uint { /// Returns the truthy value if `self` is odd or the falsy value otherwise. pub(crate) const fn ct_is_odd(&self) -> CtChoice { - CtChoice::from_lsb(self.limbs[0].0 & 1) + CtChoice::from_word_lsb(self.limbs[0].0 & 1) } /// Returns the truthy value if `self == rhs` or the falsy value otherwise. @@ -69,14 +69,14 @@ impl Uint { // but since we have to use Uint::wrapping_sub(), which calls `sbb()`, // there are no savings compared to just calling `sbb()` directly. let (_res, borrow) = lhs.sbb(rhs, Limb::ZERO); - CtChoice::from_mask(borrow.0) + CtChoice::from_word_mask(borrow.0) } /// Returns the truthy value if `self >= rhs` and the falsy value otherwise. #[inline] pub(crate) const fn ct_gt(lhs: &Self, rhs: &Self) -> CtChoice { let (_res, borrow) = rhs.sbb(lhs, Limb::ZERO); - CtChoice::from_mask(borrow.0) + CtChoice::from_word_mask(borrow.0) } /// Returns the ordering between `self` and `rhs` as an i8. diff --git a/src/uint/div.rs b/src/uint/div.rs index 503a5167b..2d3883cd6 100644 --- a/src/uint/div.rs +++ b/src/uint/div.rs @@ -1,7 +1,7 @@ //! [`Uint`] division operations. use super::div_limb::{div_rem_limb_with_reciprocal, Reciprocal}; -use crate::{CheckedDiv, CtChoice, Limb, NonZero, Uint, Word, Wrapping}; +use crate::{CheckedDiv, CtChoice, Limb, NonZero, Uint, Wrapping}; use core::ops::{Div, DivAssign, Rem, RemAssign}; use subtle::CtOption; @@ -60,9 +60,9 @@ impl Uint { loop { let (mut r, borrow) = rem.sbb(&c, Limb::ZERO); - rem = Self::ct_select(&r, &rem, CtChoice::from_mask(borrow.0)); + rem = Self::ct_select(&r, &rem, CtChoice::from_word_mask(borrow.0)); r = quo.bitor(&Self::ONE); - quo = Self::ct_select(&r, &quo, CtChoice::from_mask(borrow.0)); + quo = Self::ct_select(&r, &quo, CtChoice::from_word_mask(borrow.0)); if bd == 0 { break; } @@ -71,7 +71,7 @@ impl Uint { quo = quo.shl_vartime(1); } - let is_some = Limb(mb as Word).ct_is_nonzero(); + let is_some = CtChoice::from_u32_nonzero(mb); quo = Self::ct_select(&Self::ZERO, &quo, is_some); (quo, rem, is_some) } @@ -92,7 +92,7 @@ impl Uint { loop { let (r, borrow) = rem.sbb(&c, Limb::ZERO); - rem = Self::ct_select(&r, &rem, CtChoice::from_mask(borrow.0)); + rem = Self::ct_select(&r, &rem, CtChoice::from_word_mask(borrow.0)); if bd == 0 { break; } @@ -100,7 +100,7 @@ impl Uint { c = c.shr_vartime(1); } - let is_some = Limb(mb as Word).ct_is_nonzero(); + let is_some = CtChoice::from_u32_nonzero(mb); (rem, is_some) } @@ -127,8 +127,8 @@ impl Uint { let (lower_sub, borrow) = lower.sbb(&c.0, Limb::ZERO); let (upper_sub, borrow) = upper.sbb(&c.1, borrow); - lower = Self::ct_select(&lower_sub, &lower, CtChoice::from_mask(borrow.0)); - upper = Self::ct_select(&upper_sub, &upper, CtChoice::from_mask(borrow.0)); + lower = Self::ct_select(&lower_sub, &lower, CtChoice::from_word_mask(borrow.0)); + upper = Self::ct_select(&upper_sub, &upper, CtChoice::from_word_mask(borrow.0)); if bd == 0 { break; } @@ -136,27 +136,28 @@ impl Uint { c = Self::shr_vartime_wide(c, 1); } - let is_some = Limb(mb as Word).ct_is_nonzero(); + let is_some = CtChoice::from_u32_nonzero(mb); (lower, is_some) } /// Computes `self` % 2^k. Faster than reduce since its a power of 2. /// Limited to 2^16-1 since Uint doesn't support higher. - pub const fn rem2k(&self, k: usize) -> Self { + pub const fn rem2k(&self, k: u32) -> Self { let highest = (LIMBS - 1) as u32; - let index = k as u32 / (Limb::BITS as u32); - let le = Limb::ct_le(Limb::from_u32(index), Limb::from_u32(highest)); - let word = Limb::ct_select(Limb::from_u32(highest), Limb::from_u32(index), le).0 as usize; + let index = k / Limb::BITS; + let le = CtChoice::from_u32_le(index, highest); + let limb_num = le.select_u32(highest, index) as usize; let base = k % Limb::BITS; let mask = (1 << base) - 1; let mut out = *self; - let outmask = Limb(out.limbs[word].0 & mask); + let outmask = Limb(out.limbs[limb_num].0 & mask); - out.limbs[word] = Limb::ct_select(out.limbs[word], outmask, le); + out.limbs[limb_num] = Limb::ct_select(out.limbs[limb_num], outmask, le); - let mut i = word + 1; + // TODO: this is not constant-time. + let mut i = limb_num + 1; while i < LIMBS { out.limbs[i] = Limb::ZERO; i += 1; @@ -598,8 +599,7 @@ impl RemAssign<&NonZero>> for Wrapping Word { // Hence the `ct_select()`. let x = v2.wrapping_add(1); let (hi, _lo) = mulhilo(x, d); - let hi = Limb::ct_select(Limb(d), Limb(hi), Limb(x).ct_is_nonzero()).0; + let hi = CtChoice::from_u32_nonzero(x).select_word(d, hi); v2.wrapping_sub(hi).wrapping_sub(d) } @@ -63,7 +63,7 @@ pub const fn reciprocal(d: Word) -> Word { // Hence the `ct_select()`. let x = v3.wrapping_add(1); let (hi, _lo) = mulhilo(x, d); - let hi = Limb::ct_select(Limb(d), Limb(hi), Limb(x).ct_is_nonzero()).0; + let hi = CtChoice::from_word_nonzero(x).select_word(d, hi); v3.wrapping_sub(hi).wrapping_sub(d) } @@ -142,17 +142,17 @@ const fn div2by1(u1: Word, u0: Word, reciprocal: &Reciprocal) -> (Word, Word) { let q1 = q1.wrapping_add(1); let r = u0.wrapping_sub(q1.wrapping_mul(d)); - let r_gt_q0 = Limb::ct_lt(Limb(q0), Limb(r)); - let q1 = Limb::ct_select(Limb(q1), Limb(q1.wrapping_sub(1)), r_gt_q0).0; - let r = Limb::ct_select(Limb(r), Limb(r.wrapping_add(d)), r_gt_q0).0; + let r_gt_q0 = CtChoice::from_word_lt(q0, r); + let q1 = r_gt_q0.select_word(q1, q1.wrapping_sub(1)); + let r = r_gt_q0.select_word(r, r.wrapping_add(d)); // If this was a normal `if`, we wouldn't need wrapping ops, because there would be no overflow. // But since we calculate both results either way, we have to wrap. // Added an assert to still check the lack of overflow in debug mode. debug_assert!(r < d || q1 < Word::MAX); - let r_ge_d = Limb::ct_le(Limb(d), Limb(r)); - let q1 = Limb::ct_select(Limb(q1), Limb(q1.wrapping_add(1)), r_ge_d).0; - let r = Limb::ct_select(Limb(r), Limb(r.wrapping_sub(d)), r_ge_d).0; + let r_ge_d = CtChoice::from_word_le(d, r); + let q1 = r_ge_d.select_word(q1, q1.wrapping_add(1)); + let r = r_ge_d.select_word(r, r.wrapping_sub(d)); (q1, r) } @@ -179,20 +179,17 @@ impl Reciprocal { let shift = divisor.0.leading_zeros(); #[allow(trivial_numeric_casts)] - let is_some = Limb((Word::BITS - shift) as Word).ct_is_nonzero(); + let is_some = CtChoice::from_u32_nonzero(Word::BITS - shift); // If `divisor = 0`, shifting `divisor` by `leading_zeros == Word::BITS` will cause a panic. // Have to substitute a "bogus" shift in that case. #[allow(trivial_numeric_casts)] - let shift_limb = Limb::ct_select(Limb::ZERO, Limb(shift as Word), is_some); + let shift = is_some.if_true_u32(shift); // Need to provide bogus normalized divisor and reciprocal too, // so that we don't get a panic in low-level functions. - let divisor_normalized = divisor.shl(shift_limb); - let divisor_normalized = Limb::ct_select(Limb::MAX, divisor_normalized, is_some).0; - - #[allow(trivial_numeric_casts)] - let shift = shift_limb.0 as u32; + let divisor_normalized = divisor.0 << shift; + let divisor_normalized = is_some.select_word(Word::MAX, divisor_normalized); ( Self { @@ -255,7 +252,7 @@ pub(crate) const fn div_rem_limb_with_reciprocal( u: &Uint, reciprocal: &Reciprocal, ) -> (Uint, Limb) { - let (u_shifted, u_hi) = u.shl_limb(reciprocal.shift as usize); + let (u_shifted, u_hi) = u.shl_limb(reciprocal.shift); let mut r = u_hi.0; let mut q = [Limb::ZERO; L]; diff --git a/src/uint/from.rs b/src/uint/from.rs index 0f1bfbca7..e870a27b9 100644 --- a/src/uint/from.rs +++ b/src/uint/from.rs @@ -56,7 +56,7 @@ impl Uint { // TODO(tarcieri): replace with `const impl From` when stable pub const fn from_u128(n: u128) -> Self { assert!( - LIMBS >= (128 / Limb::BITS), + LIMBS >= 16 / Limb::BYTES, "number of limbs must be greater than zero" ); @@ -127,7 +127,7 @@ impl From for Uint { impl From for Uint { fn from(n: u64) -> Self { // TODO(tarcieri): const where clause when possible - debug_assert!(LIMBS >= (64 / Limb::BITS), "not enough limbs"); + debug_assert!(LIMBS >= 8 / Limb::BYTES, "not enough limbs"); Self::from_u64(n) } } @@ -135,7 +135,7 @@ impl From for Uint { impl From for Uint { fn from(n: u128) -> Self { // TODO(tarcieri): const where clause when possible - debug_assert!(LIMBS >= (128 / Limb::BITS), "not enough limbs"); + debug_assert!(LIMBS >= 16 / Limb::BYTES, "not enough limbs"); Self::from_u128(n) } } diff --git a/src/uint/inv_mod.rs b/src/uint/inv_mod.rs index e41dc66b5..9a1827443 100644 --- a/src/uint/inv_mod.rs +++ b/src/uint/inv_mod.rs @@ -6,7 +6,7 @@ impl Uint { /// This method is constant-time w.r.t. `self` but not `k`. /// /// Conditions: `self` < 2^k and `self` must be odd - pub const fn inv_mod2k_vartime(&self, k: usize) -> Self { + pub const fn inv_mod2k_vartime(&self, k: u32) -> Self { // Using the Algorithm 3 from "A Secure Algorithm for Inversion Modulo 2k" // by Sadiel de la Fe and Carles Ferrer. // See . @@ -21,7 +21,7 @@ impl Uint { while i < k { // X_i = b_i mod 2 let x_i = b.limbs[0].0 & 1; - let x_i_choice = CtChoice::from_lsb(x_i); + let x_i_choice = CtChoice::from_word_lsb(x_i); // b_{i+1} = (b_i - a * X_i) / 2 b = Self::ct_select(&b, &b.wrapping_sub(self), x_i_choice).shr_vartime(1); // Store the X_i bit in the result (x = x | (1 << X_i)) @@ -36,7 +36,7 @@ impl Uint { /// Computes 1/`self` mod `2^k`. /// /// Conditions: `self` < 2^k and `self` must be odd - pub const fn inv_mod2k(&self, k: usize) -> Self { + pub const fn inv_mod2k(&self, k: u32) -> Self { // This is the same algorithm as in `inv_mod2k_vartime()`, // but made constant-time w.r.t `k` as well. @@ -47,11 +47,11 @@ impl Uint { while i < Self::BITS { // Only iterations for i = 0..k need to change `x`, // the rest are dummy ones performed for the sake of constant-timeness. - let within_range = CtChoice::from_usize_lt(i, k); + let within_range = CtChoice::from_u32_lt(i, k); // X_i = b_i mod 2 let x_i = b.limbs[0].0 & 1; - let x_i_choice = CtChoice::from_lsb(x_i); + let x_i_choice = CtChoice::from_word_lsb(x_i); // b_{i+1} = (b_i - a * X_i) / 2 b = Self::ct_select(&b, &b.wrapping_sub(self), x_i_choice).shr_vartime(1); @@ -80,8 +80,8 @@ impl Uint { pub const fn inv_odd_mod_bounded( &self, modulus: &Self, - bits: usize, - modulus_bits: usize, + bits: u32, + modulus_bits: u32, ) -> (Self, CtChoice) { debug_assert!(modulus.ct_is_odd().is_true_vartime()); @@ -156,9 +156,7 @@ impl Uint { let (a, a_is_some) = self.inv_odd_mod(&s); let b = self.inv_mod2k(k); // inverse modulo 2^k exists either if `k` is 0 or if `self` is odd. - let b_is_some = CtChoice::from_usize_being_nonzero(k) - .not() - .or(self.ct_is_odd()); + let b_is_some = CtChoice::from_u32_nonzero(k).not().or(self.ct_is_odd()); // Restore from RNS: // self^{-1} = a mod s = b mod 2^k diff --git a/src/uint/neg_mod.rs b/src/uint/neg_mod.rs index a3481dcbd..28cd24b32 100644 --- a/src/uint/neg_mod.rs +++ b/src/uint/neg_mod.rs @@ -12,7 +12,7 @@ impl Uint { while i < LIMBS { // Set ret to 0 if the original value was 0, in which // case ret would be p. - ret.limbs[i].0 = z.if_true(ret.limbs[i].0); + ret.limbs[i].0 = z.if_true_word(ret.limbs[i].0); i += 1; } ret diff --git a/src/uint/rand.rs b/src/uint/rand.rs index 96e8ff567..8f97c7b1b 100644 --- a/src/uint/rand.rs +++ b/src/uint/rand.rs @@ -43,12 +43,12 @@ pub(super) fn random_mod_core( rng: &mut impl CryptoRngCore, n: &mut T, modulus: &NonZero, - n_bits: usize, + n_bits: u32, ) where T: AsMut<[Limb]> + ConstantTimeLess + Zero, { - let n_bytes = (n_bits + 7) / 8; - let n_limbs = (n_bits + Limb::BITS - 1) / Limb::BITS; + let n_bytes = ((n_bits + 7) / 8) as usize; + let n_limbs = ((n_bits + Limb::BITS - 1) / Limb::BITS) as usize; let hi_bytes = n_bytes - (n_limbs - 1) * Limb::BYTES; let mut bytes = Limb::ZERO.to_le_bytes(); diff --git a/src/uint/shl.rs b/src/uint/shl.rs index 1dbc40f05..97030b5a1 100644 --- a/src/uint/shl.rs +++ b/src/uint/shl.rs @@ -7,47 +7,43 @@ impl Uint { /// Computes `self << shift` where `0 <= shift < Limb::BITS`, /// returning the result and the carry. #[inline(always)] - pub(crate) const fn shl_limb(&self, n: usize) -> (Self, Limb) { + pub(crate) const fn shl_limb(&self, shift: u32) -> (Self, Limb) { let mut limbs = [Limb::ZERO; LIMBS]; - let nz = Limb(n as Word).ct_is_nonzero(); - let lshift = n as Word; - let rshift = Limb::ct_select(Limb::ZERO, Limb((Limb::BITS - n) as Word), nz).0; - let carry = Limb::ct_select( - Limb::ZERO, - Limb(self.limbs[LIMBS - 1].0.wrapping_shr(Word::BITS - n as u32)), - nz, - ); + let nz = CtChoice::from_u32_nonzero(shift); + let lshift = shift; + let rshift = nz.if_true_u32(Limb::BITS - shift); + let carry = nz.if_true_word(self.limbs[LIMBS - 1].0.wrapping_shr(Word::BITS - shift)); let mut i = LIMBS - 1; while i > 0 { let mut limb = self.limbs[i].0 << lshift; let hi = self.limbs[i - 1].0 >> rshift; - limb |= nz.if_true(hi); + limb |= nz.if_true_word(hi); limbs[i] = Limb(limb); i -= 1 } limbs[0] = Limb(self.limbs[0].0 << lshift); - (Uint::::new(limbs), carry) + (Uint::::new(limbs), Limb(carry)) } /// Computes `self << shift`. /// - /// NOTE: this operation is variable time with respect to `n` *ONLY*. + /// NOTE: this operation is variable time with respect to `shift` *ONLY*. /// - /// When used with a fixed `n`, this function is constant-time with respect + /// When used with a fixed `shift`, this function is constant-time with respect /// to `self`. #[inline(always)] - pub const fn shl_vartime(&self, n: usize) -> Self { + pub const fn shl_vartime(&self, shift: u32) -> Self { let mut limbs = [Limb::ZERO; LIMBS]; - if n >= Limb::BITS * LIMBS { + if shift >= Self::BITS { return Self { limbs }; } - let shift_num = n / Limb::BITS; - let rem = n % Limb::BITS; + let shift_num = (shift / Limb::BITS) as usize; + let rem = shift % Limb::BITS; let mut i = LIMBS; while i > shift_num { @@ -61,33 +57,33 @@ impl Uint { /// Computes a left shift on a wide input as `(lo, hi)`. /// - /// NOTE: this operation is variable time with respect to `n` *ONLY*. + /// NOTE: this operation is variable time with respect to `shift` *ONLY*. /// - /// When used with a fixed `n`, this function is constant-time with respect + /// When used with a fixed `shift`, this function is constant-time with respect /// to `self`. #[inline(always)] - pub const fn shl_vartime_wide(lower_upper: (Self, Self), n: usize) -> (Self, Self) { + pub const fn shl_vartime_wide(lower_upper: (Self, Self), shift: u32) -> (Self, Self) { let (lower, mut upper) = lower_upper; - let new_lower = lower.shl_vartime(n); - upper = upper.shl_vartime(n); - if n >= Self::BITS { - upper = upper.bitor(&lower.shl_vartime(n - Self::BITS)); + let new_lower = lower.shl_vartime(shift); + upper = upper.shl_vartime(shift); + if shift >= Self::BITS { + upper = upper.bitor(&lower.shl_vartime(shift - Self::BITS)); } else { - upper = upper.bitor(&lower.shr_vartime(Self::BITS - n)); + upper = upper.bitor(&lower.shr_vartime(Self::BITS - shift)); } (new_lower, upper) } - /// Computes `self << n`. - /// Returns zero if `n >= Self::BITS`. - pub const fn shl(&self, shift: usize) -> Self { - let overflow = CtChoice::from_usize_lt(shift, Self::BITS).not(); + /// Computes `self << shift`. + /// Returns zero if `shift >= Self::BITS`. + pub const fn shl(&self, shift: u32) -> Self { + let overflow = CtChoice::from_u32_lt(shift, Self::BITS).not(); let shift = shift % Self::BITS; let mut result = *self; let mut i = 0; while i < Self::LOG2_BITS { - let bit = CtChoice::from_lsb((shift as Word >> i) & 1); + let bit = CtChoice::from_u32_lsb((shift >> i) & 1); result = Uint::ct_select(&result, &result.shl_vartime(1 << i), bit); i += 1; } @@ -96,37 +92,37 @@ impl Uint { } } -impl Shl for Uint { +impl Shl for Uint { type Output = Uint; - /// NOTE: this operation is variable time with respect to `rhs` *ONLY*. + /// NOTE: this operation is variable time with respect to `shift` *ONLY*. /// - /// When used with a fixed `rhs`, this function is constant-time with respect + /// When used with a fixed `shift`, this function is constant-time with respect /// to `self`. - fn shl(self, rhs: usize) -> Uint { - Uint::::shl(&self, rhs) + fn shl(self, shift: u32) -> Uint { + Uint::::shl(&self, shift) } } -impl Shl for &Uint { +impl Shl for &Uint { type Output = Uint; - /// NOTE: this operation is variable time with respect to `rhs` *ONLY*. + /// NOTE: this operation is variable time with respect to `shift` *ONLY*. /// - /// When used with a fixed `rhs`, this function is constant-time with respect + /// When used with a fixed `shift`, this function is constant-time with respect /// to `self`. - fn shl(self, rhs: usize) -> Uint { - self.shl(rhs) + fn shl(self, shift: u32) -> Uint { + self.shl(shift) } } -impl ShlAssign for Uint { - /// NOTE: this operation is variable time with respect to `rhs` *ONLY*. +impl ShlAssign for Uint { + /// NOTE: this operation is variable time with respect to `shift` *ONLY*. /// - /// When used with a fixed `rhs`, this function is constant-time with respect + /// When used with a fixed `shift`, this function is constant-time with respect /// to `self`. - fn shl_assign(&mut self, rhs: usize) { - *self = self.shl(rhs) + fn shl_assign(&mut self, shift: u32) { + *self = self.shl(shift) } } diff --git a/src/uint/shr.rs b/src/uint/shr.rs index 6a36fbe8b..d49ad3afb 100644 --- a/src/uint/shr.rs +++ b/src/uint/shr.rs @@ -1,7 +1,7 @@ //! [`Uint`] bitwise right shift operations. use super::Uint; -use crate::{limb::HI_BIT, CtChoice, Limb, Word}; +use crate::{limb::HI_BIT, CtChoice, Limb}; use core::ops::{Shr, ShrAssign}; impl Uint { @@ -34,36 +34,36 @@ impl Uint { debug_assert!(carry_bits[LIMBS - 1] == 0 || carry_bits[LIMBS - 1] == (1 << HI_BIT)); ( Uint::new(limbs), - CtChoice::from_lsb(carry_bits[0] >> HI_BIT), + CtChoice::from_word_lsb(carry_bits[0] >> HI_BIT), ) } - /// Computes `self >> n`. + /// Computes `self >> shift`. /// - /// NOTE: this operation is variable time with respect to `n` *ONLY*. + /// NOTE: this operation is variable time with respect to `shift` *ONLY*. /// - /// When used with a fixed `n`, this function is constant-time with respect + /// When used with a fixed `shift`, this function is constant-time with respect /// to `self`. #[inline(always)] - pub const fn shr_vartime(&self, shift: usize) -> Self { - let full_shifts = shift / Limb::BITS; + pub const fn shr_vartime(&self, shift: u32) -> Self { + let full_shifts = (shift / Limb::BITS) as usize; let small_shift = shift & (Limb::BITS - 1); let mut limbs = [Limb::ZERO; LIMBS]; - if shift > Limb::BITS * LIMBS { + if shift > Self::BITS { return Self { limbs }; } - let n = LIMBS - full_shifts; + let shift = LIMBS - full_shifts; let mut i = 0; if small_shift == 0 { - while i < n { + while i < shift { limbs[i] = Limb(self.limbs[i + full_shifts].0); i += 1; } } else { - while i < n { + while i < shift { let mut lo = self.limbs[i + full_shifts].0 >> small_shift; if i < (LIMBS - 1) - full_shifts { @@ -80,33 +80,33 @@ impl Uint { /// Computes a right shift on a wide input as `(lo, hi)`. /// - /// NOTE: this operation is variable time with respect to `n` *ONLY*. + /// NOTE: this operation is variable time with respect to `shift` *ONLY*. /// - /// When used with a fixed `n`, this function is constant-time with respect + /// When used with a fixed `shift`, this function is constant-time with respect /// to `self`. #[inline(always)] - pub const fn shr_vartime_wide(lower_upper: (Self, Self), n: usize) -> (Self, Self) { + pub const fn shr_vartime_wide(lower_upper: (Self, Self), shift: u32) -> (Self, Self) { let (mut lower, upper) = lower_upper; - let new_upper = upper.shr_vartime(n); - lower = lower.shr_vartime(n); - if n >= Self::BITS { - lower = lower.bitor(&upper.shr_vartime(n - Self::BITS)); + let new_upper = upper.shr_vartime(shift); + lower = lower.shr_vartime(shift); + if shift >= Self::BITS { + lower = lower.bitor(&upper.shr_vartime(shift - Self::BITS)); } else { - lower = lower.bitor(&upper.shl_vartime(Self::BITS - n)); + lower = lower.bitor(&upper.shl_vartime(Self::BITS - shift)); } (lower, new_upper) } - /// Computes `self << n`. - /// Returns zero if `n >= Self::BITS`. - pub const fn shr(&self, shift: usize) -> Self { - let overflow = CtChoice::from_usize_lt(shift, Self::BITS).not(); + /// Computes `self << shift`. + /// Returns zero if `shift >= Self::BITS`. + pub const fn shr(&self, shift: u32) -> Self { + let overflow = CtChoice::from_u32_lt(shift, Self::BITS).not(); let shift = shift % Self::BITS; let mut result = *self; let mut i = 0; while i < Self::LOG2_BITS { - let bit = CtChoice::from_lsb((shift as Word >> i) & 1); + let bit = CtChoice::from_u32_lsb((shift >> i) & 1); result = Uint::ct_select(&result, &result.shr_vartime(1 << i), bit); i += 1; } @@ -115,33 +115,33 @@ impl Uint { } } -impl Shr for Uint { +impl Shr for Uint { type Output = Uint; - /// NOTE: this operation is variable time with respect to `rhs` *ONLY*. + /// NOTE: this operation is variable time with respect to `shift` *ONLY*. /// - /// When used with a fixed `rhs`, this function is constant-time with respect + /// When used with a fixed `shift`, this function is constant-time with respect /// to `self`. - fn shr(self, rhs: usize) -> Uint { - Uint::::shr(&self, rhs) + fn shr(self, shift: u32) -> Uint { + Uint::::shr(&self, shift) } } -impl Shr for &Uint { +impl Shr for &Uint { type Output = Uint; - /// NOTE: this operation is variable time with respect to `rhs` *ONLY*. + /// NOTE: this operation is variable time with respect to `shift` *ONLY*. /// - /// When used with a fixed `rhs`, this function is constant-time with respect + /// When used with a fixed `shift`, this function is constant-time with respect /// to `self`. - fn shr(self, rhs: usize) -> Uint { - self.shr(rhs) + fn shr(self, shift: u32) -> Uint { + self.shr(shift) } } -impl ShrAssign for Uint { - fn shr_assign(&mut self, rhs: usize) { - *self = self.shr(rhs); +impl ShrAssign for Uint { + fn shr_assign(&mut self, shift: u32) { + *self = self.shr(shift); } } diff --git a/src/uint/sqrt.rs b/src/uint/sqrt.rs index 5c96afb1a..5e1f59f3c 100644 --- a/src/uint/sqrt.rs +++ b/src/uint/sqrt.rs @@ -1,7 +1,7 @@ //! [`Uint`] square root operations. use super::Uint; -use crate::{Limb, Word}; +use crate::CtChoice; use subtle::{ConstantTimeEq, CtOption}; impl Uint { @@ -34,7 +34,7 @@ impl Uint { // Sometimes an increase is too far, especially with large // powers, and then takes a long time to walk back. The upper // bound is based on bit size, so saturate on that. - let le = Limb::ct_le(Limb(xn.bits_vartime() as Word), Limb(max_bits as Word)); + let le = CtChoice::from_u32_le(xn.bits_vartime(), max_bits); guess = Self::ct_select(&cap, &xn, le); xn = { let q = self.wrapping_div(&guess); diff --git a/src/uint/sub.rs b/src/uint/sub.rs index 571dd6aa5..000a4f8c1 100644 --- a/src/uint/sub.rs +++ b/src/uint/sub.rs @@ -25,7 +25,7 @@ impl Uint { /// Perform saturating subtraction, returning `ZERO` on underflow. pub const fn saturating_sub(&self, rhs: &Self) -> Self { let (res, underflow) = self.sbb(rhs, Limb::ZERO); - Self::ct_select(&res, &Self::ZERO, CtChoice::from_mask(underflow.0)) + Self::ct_select(&res, &Self::ZERO, CtChoice::from_word_mask(underflow.0)) } /// Perform wrapping subtraction, discarding underflow and wrapping around @@ -43,7 +43,7 @@ impl Uint { ) -> (Self, CtChoice) { let actual_rhs = Uint::ct_select(&Uint::ZERO, rhs, choice); let (res, borrow) = self.sbb(&actual_rhs, Limb::ZERO); - (res, CtChoice::from_mask(borrow.0)) + (res, CtChoice::from_word_mask(borrow.0)) } } diff --git a/tests/boxed_residue_proptests.rs b/tests/boxed_residue_proptests.rs index 5abcc2b1a..d5eb26d85 100644 --- a/tests/boxed_residue_proptests.rs +++ b/tests/boxed_residue_proptests.rs @@ -38,7 +38,7 @@ prop_compose! { let extra = bytes.len() % Limb::BYTES; let bytes_precision = bytes.len() - extra; bytes.truncate(bytes_precision); - BoxedUint::from_be_slice(&bytes, bytes_precision * 8).unwrap() + BoxedUint::from_be_slice(&bytes, bytes_precision as u32 * 8).unwrap() } } prop_compose! { diff --git a/tests/boxed_uint_proptests.rs b/tests/boxed_uint_proptests.rs index 24a540a96..c95c3352f 100644 --- a/tests/boxed_uint_proptests.rs +++ b/tests/boxed_uint_proptests.rs @@ -16,7 +16,7 @@ fn to_uint(big_uint: BigUint) -> BoxedUint { let pad_count = Limb::BYTES - (bytes.len() % Limb::BYTES); let mut padded_bytes = vec![0u8; pad_count]; padded_bytes.extend_from_slice(&bytes); - BoxedUint::from_be_slice(&padded_bytes, padded_bytes.len() * 8).unwrap() + BoxedUint::from_be_slice(&padded_bytes, padded_bytes.len() as u32 * 8).unwrap() } fn reduce(x: &BoxedUint, n: &BoxedUint) -> BoxedUint { @@ -40,7 +40,7 @@ prop_compose! { let extra = bytes.len() % Limb::BYTES; let bytes_precision = bytes.len() - extra; bytes.truncate(bytes_precision); - BoxedUint::from_be_slice(&bytes, bytes_precision * 8).unwrap() + BoxedUint::from_be_slice(&bytes, bytes_precision as u32 * 8).unwrap() } } prop_compose! { @@ -74,7 +74,7 @@ proptest! { #[test] fn bits(a in uint()) { - let expected = to_biguint(&a).bits(); + let expected = to_biguint(&a).bits() as u32; assert_eq!(expected, a.bits()); assert_eq!(expected, a.bits_vartime()); } diff --git a/tests/uint_proptests.rs b/tests/uint_proptests.rs index 6c452c30a..c3e1d86e8 100644 --- a/tests/uint_proptests.rs +++ b/tests/uint_proptests.rs @@ -51,7 +51,7 @@ proptest! { #[test] fn bits(a in uint()) { - let expected = to_biguint(&a).bits(); + let expected = to_biguint(&a).bits() as u32; assert_eq!(expected, a.bits()); assert_eq!(expected, a.bits_vartime()); } @@ -61,7 +61,7 @@ proptest! { let a_bi = to_biguint(&a); let expected = to_uint(a_bi << shift.into()); - let actual = a.shl_vartime(shift as usize); + let actual = a.shl_vartime(shift.into()); assert_eq!(expected, actual); } @@ -71,9 +71,9 @@ proptest! { let a_bi = to_biguint(&a); // Add a 50% probability of overflow. - let shift = (shift as usize) % (U256::BITS * 2); + let shift = u32::from(shift) % (U256::BITS * 2); - let expected = to_uint((a_bi << shift) & ((BigUint::one() << U256::BITS) - BigUint::one())); + let expected = to_uint((a_bi << shift as usize) & ((BigUint::one() << U256::BITS as usize) - BigUint::one())); let actual = a.shl(shift); assert_eq!(expected, actual); @@ -84,9 +84,9 @@ proptest! { let a_bi = to_biguint(&a); // Add a 50% probability of overflow. - let shift = (shift as usize) % (U256::BITS * 2); + let shift = u32::from(shift) % (U256::BITS * 2); - let expected = to_uint(a_bi >> shift); + let expected = to_uint(a_bi >> shift as usize); let actual = a.shr(shift); assert_eq!(expected, actual); @@ -238,11 +238,11 @@ proptest! { } #[test] - fn inv_mod2k(a in uint(), k in any::()) { + fn inv_mod2k(a in uint(), k in any::()) { let a = a | U256::ONE; // make odd let k = k % (U256::BITS + 1); let a_bi = to_biguint(&a); - let m_bi = BigUint::one() << k; + let m_bi = BigUint::one() << k as usize; let actual = a.inv_mod2k(k); let actual_vartime = a.inv_mod2k_vartime(k);