Skip to main content

crypto_bigint/uint/ref_type/
ct.rs

1//! Constant-time support: impls of `Ct*` traits and constant-time `const fn` operations.
2
3use super::UintRef;
4use crate::{Choice, CtAssign, CtEq, CtLt};
5
6impl CtAssign for UintRef {
7    #[inline]
8    fn ct_assign(&mut self, other: &Self, choice: Choice) {
9        assert!(self.bits_precision() >= other.bits_precision());
10        let (lo, hi) = self.split_at_mut(other.nlimbs());
11        lo.limbs.ct_assign(&other.limbs, choice);
12        hi.conditional_set_zero(choice);
13    }
14}
15
16impl<Rhs: AsRef<UintRef> + ?Sized> CtEq<Rhs> for UintRef {
17    #[inline]
18    fn ct_eq(&self, other: &Rhs) -> Choice {
19        let rhs = other.as_ref();
20        let overlap = if self.nlimbs() < rhs.nlimbs() {
21            self.nlimbs()
22        } else {
23            rhs.nlimbs()
24        };
25        let (lhs, lhs_over) = self.split_at(overlap);
26        let (rhs, rhs_over) = rhs.split_at(overlap);
27        lhs.limbs
28            .ct_eq(&rhs.limbs)
29            .and(lhs_over.is_zero())
30            .and(rhs_over.is_zero())
31    }
32}
33
34impl CtLt for UintRef {
35    #[inline]
36    fn ct_lt(&self, other: &Self) -> Choice {
37        Self::lt(self, other)
38    }
39}
40
41#[cfg(test)]
42mod tests {
43    use ctutils::CtLt;
44
45    use super::UintRef;
46    use crate::{CtEq, Limb};
47
48    #[test]
49    fn ct_eq() {
50        let z_small = UintRef::new(&[Limb::ZERO, Limb::ZERO]);
51        let z_big = UintRef::new(&[Limb::ZERO, Limb::ZERO, Limb::ZERO]);
52        let a = UintRef::new(&[Limb::ZERO, Limb::ZERO, Limb::ONE]);
53
54        assert!(z_small.ct_eq(z_big).to_bool());
55        assert!(z_big.ct_eq(z_small).to_bool());
56        assert!(a.ct_eq(a).to_bool());
57        assert!(!z_small.ct_eq(a).to_bool());
58        assert!(!a.ct_eq(z_small).to_bool());
59        assert!(!z_big.ct_eq(a).to_bool());
60        assert!(!a.ct_eq(z_big).to_bool());
61    }
62
63    #[test]
64    fn ct_lt() {
65        let lesser = UintRef::new(&[Limb::ZERO, Limb::ZERO, Limb::ZERO]);
66        let greater = UintRef::new(&[Limb::ZERO, Limb::ONE, Limb::ZERO]);
67        assert!(lesser.ct_lt(greater).to_bool());
68        assert!(!greater.ct_lt(lesser).to_bool());
69
70        let smaller = UintRef::new(&[Limb::ZERO, Limb::ZERO]);
71        let bigger = UintRef::new(&[Limb::ZERO, Limb::ZERO, Limb::ONE]);
72        assert!(smaller.ct_lt(bigger).to_bool());
73        assert!(!bigger.ct_lt(smaller).to_bool());
74    }
75}