crypto_bigint/uint/boxed/
ct.rs

1//! Constant-time helper functions.
2
3use super::BoxedUint;
4use crate::{ConstantTimeSelect, Limb};
5use subtle::{Choice, ConditionallySelectable};
6
7/// NOTE: can't impl `subtle`'s [`ConditionallySelectable`] trait due to its `Copy` bound
8impl ConstantTimeSelect for BoxedUint {
9    #[inline]
10    fn ct_select(a: &Self, b: &Self, choice: Choice) -> Self {
11        debug_assert_eq!(a.bits_precision(), b.bits_precision());
12        let mut limbs = vec![Limb::ZERO; a.nlimbs()].into_boxed_slice();
13
14        for i in 0..a.nlimbs() {
15            limbs[i] = Limb::conditional_select(&a.limbs[i], &b.limbs[i], choice);
16        }
17
18        Self { limbs }
19    }
20
21    #[inline]
22    fn ct_assign(&mut self, other: &Self, choice: Choice) {
23        debug_assert_eq!(self.bits_precision(), other.bits_precision());
24
25        for i in 0..self.nlimbs() {
26            self.limbs[i].conditional_assign(&other.limbs[i], choice);
27        }
28    }
29
30    #[inline]
31    fn ct_swap(a: &mut Self, b: &mut Self, choice: Choice) {
32        debug_assert_eq!(a.bits_precision(), b.bits_precision());
33
34        for i in 0..a.nlimbs() {
35            Limb::conditional_swap(&mut a.limbs[i], &mut b.limbs[i], choice);
36        }
37    }
38}
39
40#[cfg(test)]
41mod tests {
42    use super::BoxedUint;
43    use crate::ConstantTimeSelect;
44    use subtle::Choice;
45
46    #[test]
47    fn conditional_select() {
48        let a = BoxedUint::zero_with_precision(128);
49        let b = BoxedUint::max(128);
50
51        assert_eq!(a, BoxedUint::ct_select(&a, &b, Choice::from(0)));
52        assert_eq!(b, BoxedUint::ct_select(&a, &b, Choice::from(1)));
53    }
54}