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