diff --git a/benches/uint.rs b/benches/uint.rs index 532a59e33..084307921 100644 --- a/benches/uint.rs +++ b/benches/uint.rs @@ -891,7 +891,7 @@ fn bench_invert_mod(c: &mut Criterion) { loop { let x = U256::random_from_rng(&mut rng); let inv_x = x.invert_odd_mod_vartime(&m); - if inv_x.is_some().into() { + if inv_x.is_some() { break (x, m); } } diff --git a/src/modular/boxed_monty_form/invert.rs b/src/modular/boxed_monty_form/invert.rs index 4a5ddbf2c..68e66345d 100644 --- a/src/modular/boxed_monty_form/invert.rs +++ b/src/modular/boxed_monty_form/invert.rs @@ -1,7 +1,7 @@ //! Multiplicative inverses of boxed integers in Montgomery form. use super::{BoxedMontyForm, BoxedMontyParams}; -use crate::{CtOption, Invert, modular::safegcd::boxed::BoxedSafeGcdInverter}; +use crate::{Choice, CtOption, Invert, modular::safegcd::boxed::BoxedSafeGcdInverter}; impl BoxedMontyForm { /// Computes `self^-1` representing the multiplicative inverse of `self`, @@ -22,19 +22,19 @@ impl BoxedMontyForm { /// Computes `self^-1` representing the multiplicative inverse of `self`, /// i.e. `self * self^-1 = 1`. /// - /// This version is variable-time with respect to the self of `self`, but constant-time with + /// Returns `None` if the number is not invertible. + /// + /// This version is variable-time with respect to the value of `self`, but constant-time with /// respect to `self`'s `params`. #[must_use] - pub fn invert_vartime(&self) -> CtOption { - let montgomery_form = self.params.inverter().invert_vartime(&self.montgomery_form); - let is_some = montgomery_form.is_some(); - let montgomery_form2 = self.montgomery_form.clone(); - let ret = BoxedMontyForm { - montgomery_form: Option::from(montgomery_form).unwrap_or(montgomery_form2), - params: self.params.clone(), - }; - - CtOption::new(ret, is_some) + pub fn invert_vartime(&self) -> Option { + self.params + .inverter() + .invert_vartime(&self.montgomery_form) + .map(|montgomery_form| BoxedMontyForm { + montgomery_form, + params: self.params.clone(), + }) } } @@ -46,7 +46,10 @@ impl Invert for BoxedMontyForm { } fn invert_vartime(&self) -> Self::Output { - self.invert_vartime() + match self.invert_vartime() { + Some(value) => CtOption::some(value), + None => CtOption::new(self.clone(), Choice::FALSE), + } } } diff --git a/src/modular/const_monty_form/invert.rs b/src/modular/const_monty_form/invert.rs index ab5f119d8..36f17f647 100644 --- a/src/modular/const_monty_form/invert.rs +++ b/src/modular/const_monty_form/invert.rs @@ -1,7 +1,7 @@ //! Multiplicative inverses of integers in Montgomery form with a constant modulus. use super::{ConstMontyForm, ConstMontyParams}; -use crate::{CtOption, Invert, modular::SafeGcdInverter}; +use crate::{Choice, CtOption, Invert, modular::SafeGcdInverter}; use core::marker::PhantomData; impl, const LIMBS: usize> ConstMontyForm { @@ -42,41 +42,38 @@ impl, const LIMBS: usize> ConstMontyForm CtOption { + pub const fn inv_vartime(&self) -> Option { self.invert_vartime() } /// Computes `self^-1` representing the multiplicative inverse of `self`, /// i.e. `self * self^-1 = 1`. /// - /// If the number was invertible, the second element of the tuple is the truthy value, - /// otherwise it is the falsy value (in which case the first element's value is unspecified). + /// Returns `None` if the number is not invertible. /// /// This version is variable-time with respect to the value of `self`, but constant-time with /// respect to `MOD`. #[must_use] - pub const fn invert_vartime(&self) -> CtOption { + pub const fn invert_vartime(&self) -> Option { let inverter = SafeGcdInverter::new_with_inverse( &MOD::PARAMS.modulus, MOD::PARAMS.mod_inv, &MOD::PARAMS.r2, ); - let maybe_inverse = inverter.invert_vartime(&self.montgomery_form); - - let ret = Self { - montgomery_form: maybe_inverse.to_inner_unchecked(), - phantom: PhantomData, - }; - - CtOption::new(ret, maybe_inverse.is_some()) + match inverter.invert_vartime(&self.montgomery_form) { + Some(montgomery_form) => Some(Self { + montgomery_form, + phantom: PhantomData, + }), + None => None, + } } } @@ -88,7 +85,10 @@ impl, const LIMBS: usize> Invert for ConstMontyForm } fn invert_vartime(&self) -> Self::Output { - self.invert_vartime() + match self.invert_vartime() { + Some(value) => CtOption::some(value), + None => CtOption::new(*self, Choice::FALSE), + } } } diff --git a/src/modular/fixed_monty_form/invert.rs b/src/modular/fixed_monty_form/invert.rs index c342dace4..1ad3eca70 100644 --- a/src/modular/fixed_monty_form/invert.rs +++ b/src/modular/fixed_monty_form/invert.rs @@ -1,7 +1,7 @@ //! Multiplicative inverses of integers in Montgomery form with a modulus set at runtime. use super::{FixedMontyForm, FixedMontyParams}; -use crate::{CtOption, modular::SafeGcdInverter, traits::Invert}; +use crate::{Choice, CtOption, modular::SafeGcdInverter, traits::Invert}; impl FixedMontyForm { /// Computes `self^-1` representing the multiplicative inverse of `self`. @@ -36,36 +36,33 @@ impl FixedMontyForm { /// Computes `self^-1` representing the multiplicative inverse of `self`. /// i.e. `self * self^-1 = 1`. /// - /// If the number was invertible, the second element of the tuple is the truthy value, - /// otherwise it is the falsy value (in which case the first element's value is unspecified). + /// Returns `None` if the number is not invertible. /// /// This version is variable-time with respect to the value of `self`, but constant-time with /// respect to `self`'s `params`. #[deprecated(since = "0.7.0", note = "please use `invert_vartime` instead")] #[must_use] - pub const fn inv_vartime(&self) -> CtOption { + pub const fn inv_vartime(&self) -> Option { self.invert_vartime() } /// Computes `self^-1` representing the multiplicative inverse of `self`. /// i.e. `self * self^-1 = 1`. /// - /// If the number was invertible, the second element of the tuple is the truthy value, - /// otherwise it is the falsy value (in which case the first element's value is unspecified). + /// Returns `None` if the number is not invertible. /// /// This version is variable-time with respect to the value of `self`, but constant-time with /// respect to `self`'s `params`. #[must_use] - pub const fn invert_vartime(&self) -> CtOption { + pub const fn invert_vartime(&self) -> Option { let inverter = self.params.inverter(); - let maybe_inverse = inverter.invert_vartime(&self.montgomery_form); - - let ret = Self { - montgomery_form: maybe_inverse.to_inner_unchecked(), - params: self.params, - }; - - CtOption::new(ret, maybe_inverse.is_some()) + match inverter.invert_vartime(&self.montgomery_form) { + Some(montgomery_form) => Some(Self { + montgomery_form, + params: self.params, + }), + None => None, + } } } @@ -77,7 +74,10 @@ impl Invert for FixedMontyForm { } fn invert_vartime(&self) -> Self::Output { - self.invert_vartime() + match self.invert_vartime() { + Some(value) => CtOption::some(value), + None => CtOption::new(*self, Choice::FALSE), + } } } diff --git a/src/modular/safegcd.rs b/src/modular/safegcd.rs index b8f5579f6..12bbf35f0 100644 --- a/src/modular/safegcd.rs +++ b/src/modular/safegcd.rs @@ -91,8 +91,9 @@ impl SafeGcdInverter { /// depending on invertibility of the argument, i.e. its coprimality with the modulus. /// /// This version is variable-time with respect to `value`. - pub const fn invert_vartime(&self, value: &Uint) -> CtOption> { + pub const fn invert_vartime(&self, value: &Uint) -> Option> { invert_odd_mod_precomp::(value, &self.modulus, self.inverse, &self.adjuster) + .into_option_copied() } } diff --git a/src/modular/safegcd/boxed.rs b/src/modular/safegcd/boxed.rs index d8ace2e05..fa5944580 100644 --- a/src/modular/safegcd/boxed.rs +++ b/src/modular/safegcd/boxed.rs @@ -63,13 +63,14 @@ impl BoxedSafeGcdInverter { } /// Perform variable-time modular inversion. - pub(crate) fn invert_vartime(&self, value: &BoxedUint) -> CtOption { + pub(crate) fn invert_vartime(&self, value: &BoxedUint) -> Option { invert_odd_mod_precomp::( value, &self.modulus, self.inverse, Some(self.adjuster.clone()), ) + .into_option() } } diff --git a/src/uint/boxed/invert_mod.rs b/src/uint/boxed/invert_mod.rs index e92d5df84..c8dc8e723 100644 --- a/src/uint/boxed/invert_mod.rs +++ b/src/uint/boxed/invert_mod.rs @@ -20,9 +20,11 @@ impl BoxedUint { } /// Computes the multiplicative inverse of `self` mod `modulus`, where `modulus` is odd. + /// + /// This method is variable-time with respect to `self`. #[must_use] - pub fn invert_odd_mod_vartime(&self, modulus: &Odd) -> CtOption { - safegcd::boxed::invert_odd_mod::(self, modulus) + pub fn invert_odd_mod_vartime(&self, modulus: &Odd) -> Option { + safegcd::boxed::invert_odd_mod::(self, modulus).into_option() } /// Computes 1/`self` mod `2^k`. diff --git a/src/uint/boxed/pow.rs b/src/uint/boxed/pow.rs index 653055cf7..3a20930d1 100644 --- a/src/uint/boxed/pow.rs +++ b/src/uint/boxed/pow.rs @@ -27,13 +27,17 @@ impl BoxedUint { CtOption::new(lo, overflow.not()) } - /// Computes `self^exp`, returning a `CtOption` which is none in the case of overflow. + /// Computes `self^exp`, returning `None` in the case of overflow. /// /// This method is variable time in the exponent `exp` only. #[must_use] - pub fn checked_pow_vartime(&self, exp: impl AsRef) -> CtOption { + pub fn checked_pow_vartime(&self, exp: impl AsRef) -> Option { let (lo, overflow) = self.overflowing_pow_vartime(exp); - CtOption::new(lo, overflow.not()) + if overflow.to_bool_vartime() { + None + } else { + Some(lo) + } } /// Computes `self^exp`, returning a `Self::MAX` in the case of overflow. @@ -249,7 +253,7 @@ mod tests { expect.map(BoxedUint::from), ); assert_eq!(base.checked_pow(&pow).into_option(), expect); - assert_eq!(base.checked_pow_vartime(&pow).into_option(), expect); + assert_eq!(base.checked_pow_vartime(&pow), expect); assert_eq!( Checked(CtOption::some(base)).pow(&pow).0.into_option(), expect diff --git a/src/uint/invert_mod.rs b/src/uint/invert_mod.rs index 72f26e047..18eda1e12 100644 --- a/src/uint/invert_mod.rs +++ b/src/uint/invert_mod.rs @@ -92,11 +92,10 @@ impl Uint { /// This method is constant-time w.r.t. `self` but not `k`. /// /// If the inverse does not exist (`k > 0` and `self` is even), - /// returns `Choice::FALSE` as the second element of the tuple, - /// otherwise returns `Choice::TRUE`. + /// returns `None`, otherwise returns `Some`. #[deprecated(since = "0.7.0", note = "please use `invert_mod2k_vartime` instead")] #[must_use] - pub const fn inv_mod2k_vartime(&self, k: u32) -> CtOption { + pub const fn inv_mod2k_vartime(&self, k: u32) -> Option { self.invert_mod2k_vartime(k) } @@ -104,18 +103,22 @@ impl Uint { /// This method is constant-time w.r.t. `self` but not `k`. /// /// If the inverse does not exist (`k > 0` and `self` is even, or `k > Self::BITS`), - /// returns `CtOption::none`, otherwise returns `CtOption::some`. + /// returns `None`. #[inline] #[must_use] - pub const fn invert_mod2k_vartime(&self, k: u32) -> CtOption { + pub const fn invert_mod2k_vartime(&self, k: u32) -> Option { if k == 0 { - CtOption::some(Self::ZERO) + Some(Self::ZERO) } else if k > Self::BITS { - CtOption::new(Self::ZERO, Choice::FALSE) + None } else { let (self_odd, is_some) = self.to_odd_or_one(); let inv = self_odd.invert_mod2k_vartime(k); - CtOption::new(inv, is_some) + if is_some.to_bool_vartime() { + Some(inv) + } else { + None + } } } @@ -160,8 +163,8 @@ impl Uint { /// /// This method is variable-time with respect to `self`. #[must_use] - pub const fn invert_odd_mod_vartime(&self, modulus: &Odd) -> CtOption { - safegcd::invert_odd_mod::(self, modulus) + pub const fn invert_odd_mod_vartime(&self, modulus: &Odd) -> Option { + safegcd::invert_odd_mod::(self, modulus).into_option_copied() } /// Computes the multiplicative inverse of `self` mod `modulus`. @@ -306,7 +309,7 @@ mod tests { assert!(a.is_none().to_bool_vartime()); let a = U256::from(10u64).invert_mod2k_vartime(4); - assert!(a.is_none().to_bool_vartime()); + assert!(a.is_none()); // A degenerate case. An inverse mod 2^0 == 1 always exists even for even numbers. diff --git a/src/uint/pow.rs b/src/uint/pow.rs index 7ce8473f2..3f3493931 100644 --- a/src/uint/pow.rs +++ b/src/uint/pow.rs @@ -29,16 +29,20 @@ impl Uint { CtOption::new(lo, overflow.not()) } - /// Computes `self^exp`, returning a `CtOption` which is none in the case of overflow. + /// Computes `self^exp`, returning `None` in the case of overflow. /// /// This method is variable time in the exponent `exp` only. #[must_use] pub const fn checked_pow_vartime( &self, exp: &Uint, - ) -> CtOption { + ) -> Option { let (lo, overflow) = self.overflowing_pow_vartime(exp); - CtOption::new(lo, overflow.not()) + if overflow.to_bool_vartime() { + None + } else { + Some(lo) + } } /// Computes `self^exp`, returning a `Self::MAX` in the case of overflow. @@ -252,7 +256,7 @@ mod tests { ]; for (base, pow, expect) in checks { assert_eq!(base.checked_pow(&pow).into_option(), expect); - assert_eq!(base.checked_pow_vartime(&pow).into_option(), expect); + assert_eq!(base.checked_pow_vartime(&pow), expect); assert_eq!( Checked(CtOption::some(base)).pow(&pow).0.into_option(), expect diff --git a/src/uint/root.rs b/src/uint/root.rs index 7a092daa8..b0cff5a77 100644 --- a/src/uint/root.rs +++ b/src/uint/root.rs @@ -146,7 +146,7 @@ mod tests { .expect("overflow, {s} exp={exp}, root={rt}"); assert!(s2 <= s.get(), "overflow, {s} exp={exp}, root={root}"); let rt_p1 = root.wrapping_add_limb(Limb::ONE); - let s3 = rt_p1.checked_pow_vartime(&exp_uint).into_option(); + let s3 = rt_p1.checked_pow_vartime(&exp_uint); assert!( s3.is_none_or(|s3| s3 > s2), "underflow, {s} exp={exp}, root={root}"