diff options
Diffstat (limited to 'vendor/crypto-bigint/src/limb/cmp.rs')
-rw-r--r-- | vendor/crypto-bigint/src/limb/cmp.rs | 50 |
1 files changed, 37 insertions, 13 deletions
diff --git a/vendor/crypto-bigint/src/limb/cmp.rs b/vendor/crypto-bigint/src/limb/cmp.rs index 76cc4b07c..4cdec5b5d 100644 --- a/vendor/crypto-bigint/src/limb/cmp.rs +++ b/vendor/crypto-bigint/src/limb/cmp.rs @@ -1,6 +1,7 @@ //! Limb comparisons -use super::{Limb, SignedWord, WideSignedWord, Word, HI_BIT}; +use super::HI_BIT; +use crate::{CtChoice, Limb}; use core::cmp::Ordering; use subtle::{Choice, ConstantTimeEq, ConstantTimeGreater, ConstantTimeLess}; @@ -24,22 +25,45 @@ impl Limb { self.0 == other.0 } - /// Returns all 1's if `a`!=0 or 0 if `a`==0. - /// - /// Const-friendly: we can't yet use `subtle` in `const fn` contexts. + /// 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)) + } + + /// 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 is_nonzero(self) -> Word { - let inner = self.0 as SignedWord; - ((inner | inner.saturating_neg()) >> HI_BIT) as Word + 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_cmp(lhs: Self, rhs: Self) -> SignedWord { - let a = lhs.0 as WideSignedWord; - let b = rhs.0 as WideSignedWord; - let gt = ((b - a) >> Limb::BIT_SIZE) & 1; - let lt = ((a - b) >> Limb::BIT_SIZE) & 1 & !gt; - (gt as SignedWord) - (lt as SignedWord) + 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) } } |