1use core::cell::Cell;
30use core::{cmp, mem};
31use kernel::deferred_call::{DeferredCall, DeferredCallClient};
32use kernel::hil::hasher::{Client, Hasher, SipHash};
33use kernel::utilities::cells::{OptionalCell, TakeCell};
34use kernel::utilities::leasable_buffer::SubSlice;
35use kernel::utilities::leasable_buffer::SubSliceMut;
36use kernel::utilities::leasable_buffer::SubSliceMutImmut;
37use kernel::ErrorCode;
38
39pub struct SipHasher24<'a> {
40 client: OptionalCell<&'a dyn Client<8>>,
41
42 hasher: Cell<SipHasher>,
43
44 add_data_deferred_call: Cell<bool>,
45 complete_deferred_call: Cell<bool>,
46 deferred_call: DeferredCall,
47
48 data_buffer: Cell<Option<SubSliceMutImmut<'static, u8>>>,
49 out_buffer: TakeCell<'static, [u8; 8]>,
50}
51
52#[derive(Debug, Clone, Copy)]
53struct SipHasher {
54 k0: u64,
55 k1: u64,
56 length: usize, state: State, tail: u64, ntail: usize, }
61
62#[derive(Debug, Clone, Copy)]
63struct State {
64 v0: u64,
69 v2: u64,
70 v1: u64,
71 v3: u64,
72}
73
74impl SipHasher24<'_> {
75 pub fn new() -> Self {
76 let hasher = SipHasher {
77 k0: 0,
78 k1: 0,
79 length: 0,
80 state: State {
81 v0: 0x736f6d6570736575,
82 v1: 0x646f72616e646f6d,
83 v2: 0x6c7967656e657261,
84 v3: 0x7465646279746573,
85 },
86 ntail: 0,
87 tail: 0,
88 };
89
90 Self {
91 client: OptionalCell::empty(),
92 hasher: Cell::new(hasher),
93 add_data_deferred_call: Cell::new(false),
94 complete_deferred_call: Cell::new(false),
95 deferred_call: DeferredCall::new(),
96 data_buffer: Cell::new(None),
97 out_buffer: TakeCell::empty(),
98 }
99 }
100
101 pub fn new_with_keys(k0: u64, k1: u64) -> Self {
102 let hasher = SipHasher {
103 k0,
104 k1,
105 length: 0,
106 state: State {
107 v0: 0x736f6d6570736575,
108 v1: 0x646f72616e646f6d,
109 v2: 0x6c7967656e657261,
110 v3: 0x7465646279746573,
111 },
112 ntail: 0,
113 tail: 0,
114 };
115
116 Self {
117 client: OptionalCell::empty(),
118 hasher: Cell::new(hasher),
119 add_data_deferred_call: Cell::new(false),
120 complete_deferred_call: Cell::new(false),
121 deferred_call: DeferredCall::new(),
122 data_buffer: Cell::new(None),
123 out_buffer: TakeCell::empty(),
124 }
125 }
126}
127
128macro_rules! compress {
129 ($state:expr) => {{
130 compress!($state.v0, $state.v1, $state.v2, $state.v3)
131 }};
132 ($v0:expr, $v1:expr, $v2:expr, $v3:expr) => {{
133 $v0 = $v0.wrapping_add($v1);
134 $v1 = $v1.rotate_left(13);
135 $v1 ^= $v0;
136 $v0 = $v0.rotate_left(32);
137 $v2 = $v2.wrapping_add($v3);
138 $v3 = $v3.rotate_left(16);
139 $v3 ^= $v2;
140 $v0 = $v0.wrapping_add($v3);
141 $v3 = $v3.rotate_left(21);
142 $v3 ^= $v0;
143 $v2 = $v2.wrapping_add($v1);
144 $v1 = $v1.rotate_left(17);
145 $v1 ^= $v2;
146 $v2 = $v2.rotate_left(32);
147 }};
148}
149
150fn read_le_u64(input: &[u8]) -> u64 {
151 let mut eight_buf: [u8; 8] = [0; 8];
152 for i in 0..8 {
153 eight_buf[i] = *input.get(i).unwrap_or(&0);
154 }
155 u64::from_le_bytes(eight_buf)
156}
157
158fn read_le_u16(input: &[u8]) -> u16 {
159 let (int_bytes, _rest) = input.split_at(mem::size_of::<u16>());
160 u16::from_le_bytes(int_bytes.try_into().unwrap())
161}
162
163#[inline]
164fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 {
165 debug_assert!(len < 8);
166 let mut i = 0; let mut out = 0;
168 if i + 3 < len {
169 out = read_le_u64(&buf[start + i..]);
170 i += 4;
171 }
172 if i + 1 < len {
173 out |= (read_le_u16(&buf[start + i..]) as u64) << (i * 8);
174 i += 2
175 }
176 if i < len {
177 out |= (buf[start + i] as u64) << (i * 8);
178 i += 1;
179 }
180 debug_assert_eq!(i, len);
181 out
182}
183
184impl<'a> Hasher<'a, 8> for SipHasher24<'a> {
185 fn set_client(&'a self, client: &'a dyn Client<8>) {
186 self.client.set(client);
187 }
188
189 fn add_data(
190 &self,
191 data: SubSlice<'static, u8>,
192 ) -> Result<usize, (ErrorCode, SubSlice<'static, u8>)> {
193 let length = data.len();
194 let mut hasher = self.hasher.get();
195
196 hasher.length += length;
197
198 let mut needed = 0;
199
200 if hasher.ntail != 0 {
201 needed = 8 - hasher.ntail;
202 hasher.tail |=
203 u8to64_le(data.as_slice(), 0, cmp::min(length, needed)) << (8 * hasher.ntail);
204 if length < needed {
205 hasher.ntail += length;
206 return Ok(length);
207 } else {
208 hasher.state.v3 ^= hasher.tail;
209 compress!(&mut hasher.state);
210 compress!(&mut hasher.state);
211 hasher.state.v0 ^= hasher.tail;
212 hasher.ntail = 0;
213 }
214 }
215
216 let len = length - needed;
218 let left = len & 0x7;
219
220 let mut i = needed;
221 while i < len - left {
222 let mi = read_le_u64(&data[i..]);
223
224 hasher.state.v3 ^= mi;
225 compress!(&mut hasher.state);
226 compress!(&mut hasher.state);
227 hasher.state.v0 ^= mi;
228
229 i += 8;
230 }
231
232 hasher.tail = u8to64_le(data.as_slice(), i, left);
233 hasher.ntail = left;
234
235 self.hasher.set(hasher);
236 self.data_buffer
237 .set(Some(SubSliceMutImmut::Immutable(data)));
238
239 self.add_data_deferred_call.set(true);
240 self.deferred_call.set();
241
242 Ok(length)
243 }
244
245 fn add_mut_data(
246 &self,
247 mut data: SubSliceMut<'static, u8>,
248 ) -> Result<usize, (ErrorCode, SubSliceMut<'static, u8>)> {
249 let length = data.len();
250 let mut hasher = self.hasher.get();
251
252 hasher.length += length;
253
254 let mut needed = 0;
255
256 if hasher.ntail != 0 {
257 needed = 8 - hasher.ntail;
258 hasher.tail |=
259 u8to64_le(data.as_slice(), 0, cmp::min(length, needed)) << (8 * hasher.ntail);
260 if length < needed {
261 hasher.ntail += length;
262 return Ok(length);
263 } else {
264 hasher.state.v3 ^= hasher.tail;
265 compress!(&mut hasher.state);
266 compress!(&mut hasher.state);
267 hasher.state.v0 ^= hasher.tail;
268 hasher.ntail = 0;
269 }
270 }
271
272 let len = length - needed;
274 let left = len & 0x7;
275
276 let mut i = needed;
277 while i < len - left {
278 let mi = read_le_u64(&data[i..]);
279
280 hasher.state.v3 ^= mi;
281 compress!(&mut hasher.state);
282 compress!(&mut hasher.state);
283 hasher.state.v0 ^= mi;
284
285 i += 8;
286 }
287
288 hasher.tail = u8to64_le(data.as_slice(), i, left);
289 hasher.ntail = left;
290
291 self.hasher.set(hasher);
292 self.data_buffer.set(Some(SubSliceMutImmut::Mutable(data)));
293
294 self.add_data_deferred_call.set(true);
295 self.deferred_call.set();
296
297 Ok(length)
298 }
299
300 fn run(
301 &'a self,
302 digest: &'static mut [u8; 8],
303 ) -> Result<(), (ErrorCode, &'static mut [u8; 8])> {
304 let mut hasher = self.hasher.get();
305
306 let b: u64 = ((hasher.length as u64 & 0xff) << 56) | hasher.tail;
307
308 hasher.state.v3 ^= b;
309 compress!(&mut hasher.state);
310 compress!(&mut hasher.state);
311 hasher.state.v0 ^= b;
312
313 hasher.state.v2 ^= 0xff;
314 compress!(&mut hasher.state);
315 compress!(&mut hasher.state);
316 compress!(&mut hasher.state);
317 compress!(&mut hasher.state);
318
319 self.hasher.set(hasher);
320 self.out_buffer.replace(digest);
321
322 self.complete_deferred_call.set(true);
323 self.deferred_call.set();
324
325 Ok(())
326 }
327
328 fn clear_data(&self) {
329 let mut hasher = self.hasher.get();
330
331 hasher.length = 0;
332 hasher.state.v0 = hasher.k0 ^ 0x736f6d6570736575;
333 hasher.state.v1 = hasher.k1 ^ 0x646f72616e646f6d;
334 hasher.state.v2 = hasher.k0 ^ 0x6c7967656e657261;
335 hasher.state.v3 = hasher.k1 ^ 0x7465646279746573;
336 hasher.ntail = 0;
337
338 self.hasher.set(hasher);
339 }
340}
341
342impl SipHash for SipHasher24<'_> {
343 fn set_keys(&self, k0: u64, k1: u64) -> Result<(), ErrorCode> {
344 let mut hasher = self.hasher.get();
345
346 hasher.k0 = k0;
347 hasher.k1 = k1;
348
349 self.hasher.set(hasher);
350 self.clear_data();
351
352 Ok(())
353 }
354}
355
356impl DeferredCallClient for SipHasher24<'_> {
357 fn handle_deferred_call(&self) {
358 if self.add_data_deferred_call.get() {
359 self.add_data_deferred_call.set(false);
360
361 self.client.map(|client| {
362 self.data_buffer.take().map(|buffer| match buffer {
363 SubSliceMutImmut::Immutable(b) => client.add_data_done(Ok(()), b),
364 SubSliceMutImmut::Mutable(b) => client.add_mut_data_done(Ok(()), b),
365 });
366 });
367 }
368
369 if self.complete_deferred_call.get() {
370 self.complete_deferred_call.set(false);
371
372 self.client.map(|client| {
373 self.out_buffer.take().map(|buffer| {
374 let state = self.hasher.get().state;
375
376 let result = state.v0 ^ state.v1 ^ state.v2 ^ state.v3;
377 buffer.copy_from_slice(&result.to_le_bytes());
378
379 client.hash_done(Ok(()), buffer);
380 });
381 });
382 }
383 }
384
385 fn register(&'static self) {
386 self.deferred_call.register(self);
387 }
388}