Skip to main content

blake2/
simd.rs

1use core::ops::{Add, BitXor, Shl, Shr};
2
3#[cfg(feature = "zeroize")]
4use digest::zeroize::Zeroize;
5
6macro_rules! impl_vector4 {
7    ($vec:ident, $word:ident) => {
8        #[derive(Clone, Copy, Debug)]
9        #[repr(C)]
10        pub(crate) struct $vec(
11            pub(crate) $word,
12            pub(crate) $word,
13            pub(crate) $word,
14            pub(crate) $word,
15        );
16
17        impl $vec {
18            #[inline(always)]
19            pub(crate) fn new(e0: $word, e1: $word, e2: $word, e3: $word) -> Self {
20                Self(e0, e1, e2, e3)
21            }
22
23            #[inline(always)]
24            pub(crate) fn gather(
25                src: &[$word],
26                i0: usize,
27                i1: usize,
28                i2: usize,
29                i3: usize,
30            ) -> Self {
31                $vec::new(src[i0], src[i1], src[i2], src[i3])
32            }
33
34            #[cfg(target_endian = "little")]
35            #[inline(always)]
36            #[allow(clippy::wrong_self_convention)]
37            pub(crate) fn from_le(self) -> Self {
38                self
39            }
40
41            #[cfg(not(target_endian = "little"))]
42            #[inline(always)]
43            pub(crate) fn from_le(self) -> Self {
44                $vec::new(
45                    $word::from_le(self.0),
46                    $word::from_le(self.1),
47                    $word::from_le(self.2),
48                    $word::from_le(self.3),
49                )
50            }
51
52            #[cfg(target_endian = "little")]
53            #[inline(always)]
54            pub(crate) fn to_le(self) -> Self {
55                self
56            }
57
58            #[cfg(not(target_endian = "little"))]
59            #[inline(always)]
60            pub(crate) fn to_le(self) -> Self {
61                $vec::new(
62                    self.0.to_le(),
63                    self.1.to_le(),
64                    self.2.to_le(),
65                    self.3.to_le(),
66                )
67            }
68
69            #[inline(always)]
70            pub(crate) fn wrapping_add(self, rhs: Self) -> Self {
71                self + rhs
72            }
73
74            #[inline(always)]
75            pub(crate) fn rotate_right_const(self, n: u32) -> Self {
76                $vec::new(
77                    self.0.rotate_right(n),
78                    self.1.rotate_right(n),
79                    self.2.rotate_right(n),
80                    self.3.rotate_right(n),
81                )
82            }
83
84            #[inline(always)]
85            pub(crate) fn shuffle_left_1(self) -> Self {
86                $vec::new(self.1, self.2, self.3, self.0)
87            }
88
89            #[inline(always)]
90            pub(crate) fn shuffle_left_2(self) -> Self {
91                $vec::new(self.2, self.3, self.0, self.1)
92            }
93
94            #[inline(always)]
95            pub(crate) fn shuffle_left_3(self) -> Self {
96                $vec::new(self.3, self.0, self.1, self.2)
97            }
98
99            #[inline(always)]
100            pub(crate) fn shuffle_right_1(self) -> Self {
101                self.shuffle_left_3()
102            }
103            #[inline(always)]
104            pub(crate) fn shuffle_right_2(self) -> Self {
105                self.shuffle_left_2()
106            }
107            #[inline(always)]
108            pub(crate) fn shuffle_right_3(self) -> Self {
109                self.shuffle_left_1()
110            }
111
112            #[inline(always)]
113            pub(crate) fn as_bytes(&self) -> &[u8] {
114                let p = self as *const Self as *const u8;
115                unsafe { core::slice::from_raw_parts(p, core::mem::size_of::<Self>()) }
116            }
117        }
118
119        impl Add for $vec {
120            type Output = Self;
121
122            #[inline(always)]
123            fn add(self, rhs: Self) -> Self::Output {
124                $vec::new(
125                    self.0.wrapping_add(rhs.0),
126                    self.1.wrapping_add(rhs.1),
127                    self.2.wrapping_add(rhs.2),
128                    self.3.wrapping_add(rhs.3),
129                )
130            }
131        }
132
133        impl BitXor for $vec {
134            type Output = Self;
135
136            #[inline(always)]
137            fn bitxor(self, rhs: Self) -> Self::Output {
138                $vec::new(
139                    self.0 ^ rhs.0,
140                    self.1 ^ rhs.1,
141                    self.2 ^ rhs.2,
142                    self.3 ^ rhs.3,
143                )
144            }
145        }
146
147        impl Shl<$vec> for $vec {
148            type Output = Self;
149
150            #[inline(always)]
151            fn shl(self, rhs: Self) -> Self::Output {
152                $vec::new(
153                    self.0 << rhs.0,
154                    self.1 << rhs.1,
155                    self.2 << rhs.2,
156                    self.3 << rhs.3,
157                )
158            }
159        }
160
161        impl Shr<$vec> for $vec {
162            type Output = Self;
163
164            #[inline(always)]
165            fn shr(self, rhs: Self) -> Self::Output {
166                $vec::new(
167                    self.0 >> rhs.0,
168                    self.1 >> rhs.1,
169                    self.2 >> rhs.2,
170                    self.3 >> rhs.3,
171                )
172            }
173        }
174
175        #[cfg(feature = "zeroize")]
176        impl Zeroize for $vec {
177            fn zeroize(&mut self) {
178                self.0.zeroize();
179                self.1.zeroize();
180                self.2.zeroize();
181                self.3.zeroize();
182            }
183        }
184    };
185}
186
187impl_vector4!(u32x4, u32);
188impl_vector4!(u64x4, u64);