Skip to main content

crypto_bigint/uint/boxed/
ct.rs

1//! Constant-time support: impls of `Ct*` traits.
2
3use super::BoxedUint;
4use crate::{Choice, CtAssign, CtEq, CtGt, CtLt, CtNeg, CtSelect, Limb, UintRef};
5use ctutils::{CtAssignSlice, CtEqSlice};
6
7impl CtAssign for BoxedUint {
8    #[inline]
9    fn ct_assign(&mut self, other: &Self, choice: Choice) {
10        assert_eq!(self.bits_precision(), other.bits_precision());
11        self.limbs.ct_assign(&other.limbs, choice);
12    }
13}
14impl CtAssignSlice for BoxedUint {}
15
16impl<Rhs: AsRef<UintRef> + ?Sized> CtEq<Rhs> for BoxedUint {
17    #[inline]
18    fn ct_eq(&self, other: &Rhs) -> Choice {
19        self.as_uint_ref().ct_eq(other)
20    }
21}
22impl CtEqSlice for BoxedUint {}
23
24impl CtGt for BoxedUint {
25    #[inline]
26    fn ct_gt(&self, other: &Self) -> Choice {
27        UintRef::lt(other.as_uint_ref(), self.as_uint_ref())
28    }
29}
30
31impl CtLt for BoxedUint {
32    #[inline]
33    fn ct_lt(&self, other: &Self) -> Choice {
34        UintRef::lt(self.as_uint_ref(), other.as_uint_ref())
35    }
36}
37
38impl CtNeg for BoxedUint {
39    fn ct_neg(&self, choice: Choice) -> Self {
40        let mut neg = self.clone();
41        neg.conditional_wrapping_neg_assign(choice);
42        neg
43    }
44
45    fn ct_neg_assign(&mut self, choice: Choice) {
46        self.conditional_wrapping_neg_assign(choice);
47    }
48}
49
50impl CtSelect for BoxedUint {
51    #[inline]
52    fn ct_select(&self, other: &Self, choice: Choice) -> Self {
53        assert_eq!(self.bits_precision(), other.bits_precision());
54        let mut limbs = vec![Limb::ZERO; self.nlimbs()].into_boxed_slice();
55
56        for i in 0..self.nlimbs() {
57            limbs[i] = self.limbs[i].ct_select(&other.limbs[i], choice);
58        }
59
60        Self { limbs }
61    }
62
63    #[inline]
64    fn ct_swap(&mut self, other: &mut Self, choice: Choice) {
65        assert_eq!(self.bits_precision(), other.bits_precision());
66
67        for i in 0..self.nlimbs() {
68            self.limbs[i].ct_swap(&mut other.limbs[i], choice);
69        }
70    }
71}
72
73#[cfg(feature = "subtle")]
74impl subtle::ConditionallyNegatable for BoxedUint {
75    #[inline]
76    fn conditional_negate(&mut self, choice: subtle::Choice) {
77        self.ct_neg_assign(choice.into());
78    }
79}
80
81#[cfg(feature = "subtle")]
82impl subtle::ConstantTimeEq for BoxedUint {
83    #[inline]
84    fn ct_eq(&self, other: &Self) -> subtle::Choice {
85        CtEq::ct_eq(self, other).into()
86    }
87}
88
89#[cfg(feature = "subtle")]
90impl subtle::ConstantTimeGreater for BoxedUint {
91    #[inline]
92    fn ct_gt(&self, other: &Self) -> subtle::Choice {
93        CtGt::ct_gt(self, other).into()
94    }
95}
96
97#[cfg(feature = "subtle")]
98impl subtle::ConstantTimeLess for BoxedUint {
99    #[inline]
100    fn ct_lt(&self, other: &Self) -> subtle::Choice {
101        CtLt::ct_lt(self, other).into()
102    }
103}
104
105#[cfg(test)]
106mod tests {
107    use crate::{BoxedUint, Choice, CtEq, CtGt, CtLt, CtSelect};
108
109    #[test]
110    fn ct_eq() {
111        let a = BoxedUint::zero();
112        let b = BoxedUint::one();
113
114        assert!(a.ct_eq(&a).to_bool());
115        assert!(!a.ct_eq(&b).to_bool());
116        assert!(!b.ct_eq(&a).to_bool());
117        assert!(b.ct_eq(&b).to_bool());
118    }
119
120    #[test]
121    fn ct_gt() {
122        let a = BoxedUint::zero();
123        let b = BoxedUint::one();
124        let c = BoxedUint::max(64);
125
126        assert!(b.ct_gt(&a).to_bool());
127        assert!(c.ct_gt(&a).to_bool());
128        assert!(c.ct_gt(&b).to_bool());
129
130        assert!(!a.ct_gt(&a).to_bool());
131        assert!(!b.ct_gt(&b).to_bool());
132        assert!(!c.ct_gt(&c).to_bool());
133
134        assert!(!a.ct_gt(&b).to_bool());
135        assert!(!a.ct_gt(&c).to_bool());
136        assert!(!b.ct_gt(&c).to_bool());
137    }
138
139    #[test]
140    fn ct_lt() {
141        let a = BoxedUint::zero();
142        let b = BoxedUint::one();
143        let c = BoxedUint::max(64);
144
145        assert!(a.ct_lt(&b).to_bool());
146        assert!(a.ct_lt(&c).to_bool());
147        assert!(b.ct_lt(&c).to_bool());
148
149        assert!(!a.ct_lt(&a).to_bool());
150        assert!(!b.ct_lt(&b).to_bool());
151        assert!(!c.ct_lt(&c).to_bool());
152
153        assert!(!b.ct_lt(&a).to_bool());
154        assert!(!c.ct_lt(&a).to_bool());
155        assert!(!c.ct_lt(&b).to_bool());
156    }
157
158    #[test]
159    fn ct_select() {
160        let a = BoxedUint::zero_with_precision(128);
161        let b = BoxedUint::max(128);
162
163        assert_eq!(a, BoxedUint::ct_select(&a, &b, Choice::FALSE));
164        assert_eq!(b, BoxedUint::ct_select(&a, &b, Choice::TRUE));
165    }
166}