summaryrefslogtreecommitdiffstats
path: root/vendor/crypto-bigint/src/uint/cmp.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-19 09:26:03 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-19 09:26:03 +0000
commit9918693037dce8aa4bb6f08741b6812923486c18 (patch)
tree21d2b40bec7e6a7ea664acee056eb3d08e15a1cf /vendor/crypto-bigint/src/uint/cmp.rs
parentReleasing progress-linux version 1.75.0+dfsg1-5~progress7.99u1. (diff)
downloadrustc-9918693037dce8aa4bb6f08741b6812923486c18.tar.xz
rustc-9918693037dce8aa4bb6f08741b6812923486c18.zip
Merging upstream version 1.76.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/crypto-bigint/src/uint/cmp.rs')
-rw-r--r--vendor/crypto-bigint/src/uint/cmp.rs95
1 files changed, 85 insertions, 10 deletions
diff --git a/vendor/crypto-bigint/src/uint/cmp.rs b/vendor/crypto-bigint/src/uint/cmp.rs
index 8815369e3..b513242e4 100644
--- a/vendor/crypto-bigint/src/uint/cmp.rs
+++ b/vendor/crypto-bigint/src/uint/cmp.rs
@@ -72,12 +72,52 @@ impl<const LIMBS: usize> Uint<LIMBS> {
CtChoice::from_mask(borrow.0)
}
- /// Returns the truthy value if `self <= rhs` and the falsy value otherwise.
+ /// 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)
}
+
+ /// Returns the ordering between `self` and `rhs` as an i8.
+ /// Values correspond to the Ordering enum:
+ /// -1 is Less
+ /// 0 is Equal
+ /// 1 is Greater
+ #[inline]
+ pub(crate) const fn ct_cmp(lhs: &Self, rhs: &Self) -> i8 {
+ let mut i = 0;
+ let mut borrow = Limb::ZERO;
+ let mut diff = Limb::ZERO;
+
+ while i < LIMBS {
+ let (w, b) = rhs.limbs[i].sbb(lhs.limbs[i], borrow);
+ diff = diff.bitor(w);
+ borrow = b;
+ i += 1;
+ }
+ let sgn = ((borrow.0 & 2) as i8) - 1;
+ (diff.ct_is_nonzero().to_u8() as i8) * sgn
+ }
+
+ /// Returns the Ordering between `self` and `rhs` in variable time.
+ pub const fn cmp_vartime(&self, rhs: &Self) -> Ordering {
+ let mut i = LIMBS - 1;
+ loop {
+ let (val, borrow) = self.limbs[i].sbb(rhs.limbs[i], Limb::ZERO);
+ if val.0 != 0 {
+ return if borrow.0 != 0 {
+ Ordering::Less
+ } else {
+ Ordering::Greater
+ };
+ }
+ if i == 0 {
+ return Ordering::Equal;
+ }
+ i -= 1;
+ }
+ }
}
impl<const LIMBS: usize> ConstantTimeEq for Uint<LIMBS> {
@@ -105,15 +145,11 @@ impl<const LIMBS: usize> Eq for Uint<LIMBS> {}
impl<const LIMBS: usize> Ord for Uint<LIMBS> {
fn cmp(&self, other: &Self) -> Ordering {
- let is_lt = self.ct_lt(other);
- let is_eq = self.ct_eq(other);
-
- if is_lt.into() {
- Ordering::Less
- } else if is_eq.into() {
- Ordering::Equal
- } else {
- Ordering::Greater
+ let c = Self::ct_cmp(self, other);
+ match c {
+ -1 => Ordering::Less,
+ 0 => Ordering::Equal,
+ _ => Ordering::Greater,
}
}
}
@@ -133,6 +169,7 @@ impl<const LIMBS: usize> PartialEq for Uint<LIMBS> {
#[cfg(test)]
mod tests {
use crate::{Integer, Zero, U128};
+ use core::cmp::Ordering;
use subtle::{ConstantTimeEq, ConstantTimeGreater, ConstantTimeLess};
#[test]
@@ -197,4 +234,42 @@ mod tests {
assert!(!bool::from(c.ct_lt(&a)));
assert!(!bool::from(c.ct_lt(&b)));
}
+
+ #[test]
+ fn cmp() {
+ let a = U128::ZERO;
+ let b = U128::ONE;
+ let c = U128::MAX;
+
+ assert_eq!(a.cmp(&b), Ordering::Less);
+ assert_eq!(a.cmp(&c), Ordering::Less);
+ assert_eq!(b.cmp(&c), Ordering::Less);
+
+ assert_eq!(a.cmp(&a), Ordering::Equal);
+ assert_eq!(b.cmp(&b), Ordering::Equal);
+ assert_eq!(c.cmp(&c), Ordering::Equal);
+
+ assert_eq!(b.cmp(&a), Ordering::Greater);
+ assert_eq!(c.cmp(&a), Ordering::Greater);
+ assert_eq!(c.cmp(&b), Ordering::Greater);
+ }
+
+ #[test]
+ fn cmp_vartime() {
+ let a = U128::ZERO;
+ let b = U128::ONE;
+ let c = U128::MAX;
+
+ assert_eq!(a.cmp_vartime(&b), Ordering::Less);
+ assert_eq!(a.cmp_vartime(&c), Ordering::Less);
+ assert_eq!(b.cmp_vartime(&c), Ordering::Less);
+
+ assert_eq!(a.cmp_vartime(&a), Ordering::Equal);
+ assert_eq!(b.cmp_vartime(&b), Ordering::Equal);
+ assert_eq!(c.cmp_vartime(&c), Ordering::Equal);
+
+ assert_eq!(b.cmp_vartime(&a), Ordering::Greater);
+ assert_eq!(c.cmp_vartime(&a), Ordering::Greater);
+ assert_eq!(c.cmp_vartime(&b), Ordering::Greater);
+ }
}