Skip to main content

generic_array/ext_impls/
impl_subtle.rs

1use subtle::{ConditionallySelectable, ConstantTimeEq};
2
3use crate::{ArrayLength, GenericArray};
4
5impl<T, N: ArrayLength> ConstantTimeEq for GenericArray<T, N>
6where
7    T: ConstantTimeEq,
8{
9    #[inline]
10    fn ct_eq(&self, other: &Self) -> subtle::Choice {
11        self.as_slice().ct_eq(other.as_slice())
12    }
13}
14
15impl<T, N: ArrayLength> ConditionallySelectable for GenericArray<T, N>
16where
17    GenericArray<T, N>: Copy,
18    T: ConditionallySelectable,
19{
20    #[inline]
21    fn conditional_select(a: &Self, b: &Self, choice: subtle::Choice) -> Self {
22        let mut out = *a;
23        out.conditional_assign(b, choice);
24        out
25    }
26
27    #[inline]
28    fn conditional_assign(&mut self, other: &Self, choice: subtle::Choice) {
29        for (a, b) in self.iter_mut().zip(other.iter()) {
30            a.conditional_assign(b, choice);
31        }
32    }
33}
34
35#[cfg(test)]
36mod tests {
37    use crate::{arr, typenum::U4, GenericArray};
38    use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
39
40    #[test]
41    fn ct_eq() {
42        let a = arr![1u8, 2, 3, 4];
43        let b = arr![1u8, 2, 3, 4];
44        let c = arr![9u8, 2, 3, 4];
45
46        assert!(bool::from(a.ct_eq(&b)));
47        assert!(!bool::from(a.ct_eq(&c)));
48    }
49
50    #[test]
51    fn conditional_select_and_assign() {
52        let a = arr![1u8, 2, 3, 4];
53        let c = arr![9u8, 8, 7, 6];
54
55        let picked = GenericArray::<u8, U4>::conditional_select(&a, &c, Choice::from(1));
56        assert_eq!(picked, c);
57        let picked = GenericArray::<u8, U4>::conditional_select(&a, &c, Choice::from(0));
58        assert_eq!(picked, a);
59
60        let mut dst = a;
61        dst.conditional_assign(&c, Choice::from(1));
62        assert_eq!(dst, c);
63        dst.conditional_assign(&a, Choice::from(0));
64        assert_eq!(dst, c);
65    }
66}