Skip to content

Commit ec311d6

Browse files
authored
BoxedUint: impl ConstantTimeGreater/Less and PartialOrd/Ord (#316)
1 parent 3f6422e commit ec311d6

File tree

1 file changed

+101
-4
lines changed

1 file changed

+101
-4
lines changed

src/boxed/uint/cmp.rs

Lines changed: 101 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
//! By default these are all constant-time and use the `subtle` crate.
44
55
use super::BoxedUint;
6-
use crate::Limb;
7-
use core::cmp;
8-
use subtle::{Choice, ConstantTimeEq};
6+
use crate::{CtChoice, Limb};
7+
use core::cmp::{self, Ordering};
8+
use subtle::{
9+
Choice, ConditionallySelectable, ConstantTimeEq, ConstantTimeGreater, ConstantTimeLess,
10+
};
911

1012
impl ConstantTimeEq for BoxedUint {
1113
#[inline]
@@ -23,17 +25,55 @@ impl ConstantTimeEq for BoxedUint {
2325
}
2426
}
2527

28+
impl ConstantTimeGreater for BoxedUint {
29+
#[inline]
30+
fn ct_gt(&self, other: &Self) -> Choice {
31+
let (_, borrow) = other.sbb(self, Limb::ZERO);
32+
CtChoice::from_mask(borrow.0).into()
33+
}
34+
}
35+
36+
impl ConstantTimeLess for BoxedUint {
37+
#[inline]
38+
fn ct_lt(&self, other: &Self) -> Choice {
39+
let (_, borrow) = self.sbb(other, Limb::ZERO);
40+
CtChoice::from_mask(borrow.0).into()
41+
}
42+
}
43+
2644
impl Eq for BoxedUint {}
2745
impl PartialEq for BoxedUint {
2846
fn eq(&self, other: &Self) -> bool {
2947
self.ct_eq(other).into()
3048
}
3149
}
3250

51+
impl Ord for BoxedUint {
52+
fn cmp(&self, other: &Self) -> Ordering {
53+
let mut ret = Ordering::Equal;
54+
ret.conditional_assign(&Ordering::Greater, self.ct_gt(other));
55+
ret.conditional_assign(&Ordering::Less, self.ct_lt(other));
56+
57+
#[cfg(debug_assertions)]
58+
if ret == Ordering::Equal {
59+
debug_assert_eq!(self, other);
60+
}
61+
62+
ret
63+
}
64+
}
65+
66+
impl PartialOrd for BoxedUint {
67+
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
68+
Some(self.cmp(other))
69+
}
70+
}
71+
3372
#[cfg(test)]
3473
mod tests {
3574
use super::BoxedUint;
36-
use subtle::ConstantTimeEq;
75+
use core::cmp::Ordering;
76+
use subtle::{ConstantTimeEq, ConstantTimeGreater, ConstantTimeLess};
3777

3878
#[test]
3979
fn ct_eq() {
@@ -45,4 +85,61 @@ mod tests {
4585
assert!(!bool::from(b.ct_eq(&a)));
4686
assert!(bool::from(b.ct_eq(&b)));
4787
}
88+
89+
#[test]
90+
fn ct_gt() {
91+
let a = BoxedUint::zero();
92+
let b = BoxedUint::one();
93+
let c = BoxedUint::max(64).unwrap();
94+
95+
assert!(bool::from(b.ct_gt(&a)));
96+
assert!(bool::from(c.ct_gt(&a)));
97+
assert!(bool::from(c.ct_gt(&b)));
98+
99+
assert!(!bool::from(a.ct_gt(&a)));
100+
assert!(!bool::from(b.ct_gt(&b)));
101+
assert!(!bool::from(c.ct_gt(&c)));
102+
103+
assert!(!bool::from(a.ct_gt(&b)));
104+
assert!(!bool::from(a.ct_gt(&c)));
105+
assert!(!bool::from(b.ct_gt(&c)));
106+
}
107+
108+
#[test]
109+
fn ct_lt() {
110+
let a = BoxedUint::zero();
111+
let b = BoxedUint::one();
112+
let c = BoxedUint::max(64).unwrap();
113+
114+
assert!(bool::from(a.ct_lt(&b)));
115+
assert!(bool::from(a.ct_lt(&c)));
116+
assert!(bool::from(b.ct_lt(&c)));
117+
118+
assert!(!bool::from(a.ct_lt(&a)));
119+
assert!(!bool::from(b.ct_lt(&b)));
120+
assert!(!bool::from(c.ct_lt(&c)));
121+
122+
assert!(!bool::from(b.ct_lt(&a)));
123+
assert!(!bool::from(c.ct_lt(&a)));
124+
assert!(!bool::from(c.ct_lt(&b)));
125+
}
126+
127+
#[test]
128+
fn cmp() {
129+
let a = BoxedUint::zero();
130+
let b = BoxedUint::one();
131+
let c = BoxedUint::max(64).unwrap();
132+
133+
assert_eq!(a.cmp(&b), Ordering::Less);
134+
assert_eq!(a.cmp(&c), Ordering::Less);
135+
assert_eq!(b.cmp(&c), Ordering::Less);
136+
137+
assert_eq!(a.cmp(&a), Ordering::Equal);
138+
assert_eq!(b.cmp(&b), Ordering::Equal);
139+
assert_eq!(c.cmp(&c), Ordering::Equal);
140+
141+
assert_eq!(b.cmp(&a), Ordering::Greater);
142+
assert_eq!(c.cmp(&a), Ordering::Greater);
143+
assert_eq!(c.cmp(&b), Ordering::Greater);
144+
}
48145
}

0 commit comments

Comments
 (0)