1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
use rawbytes::RawBytes;
use zeroize::Zeroize;
#[cfg(not(target_arch = "x86_64"))]
mod impl_portable;
#[cfg(target_arch = "x86_64")]
mod impl_x86_64;
const ROUND_KEYS: [u32; 12] = [
0x058, 0x038, 0x3c0, 0x0d0, 0x120, 0x014, 0x060, 0x02c, 0x380, 0x0f0, 0x1a0, 0x012,
];
#[derive(Clone, Debug, Default)]
#[repr(C)]
pub struct Xoodoo {
st: [u32; 12],
}
impl Xoodoo {
#[inline(always)]
fn bytes_view(&self) -> &[u8] {
let view = RawBytes::bytes_view(&self.st);
debug_assert_eq!(view.len(), 48);
view
}
#[inline(always)]
fn bytes_view_mut(&mut self) -> &mut [u8] {
let view = RawBytes::bytes_view_mut(&mut self.st);
debug_assert_eq!(view.len(), 48);
view
}
#[inline(always)]
fn endian_swap(&mut self) {
for word in self.st.iter_mut() {
*word = (*word).to_le()
}
}
#[inline]
pub fn from_bytes(bytes: [u8; 48]) -> Self {
let mut st = Xoodoo::default();
let st_bytes = st.bytes_view_mut();
st_bytes.copy_from_slice(&bytes);
st
}
#[inline(always)]
pub fn bytes(&self, out: &mut [u8; 48]) {
let st_bytes = self.bytes_view();
out.copy_from_slice(st_bytes);
}
#[inline(always)]
pub fn add_byte(&mut self, byte: u8, offset: usize) {
self.endian_swap();
let st_bytes = self.bytes_view_mut();
st_bytes[offset] ^= byte;
self.endian_swap();
}
#[inline(always)]
pub fn add_bytes(&mut self, bytes: &[u8]) {
self.endian_swap();
let st_bytes = self.bytes_view_mut();
for (st_byte, byte) in st_bytes.iter_mut().zip(bytes) {
*st_byte ^= byte;
}
self.endian_swap();
}
#[inline(always)]
pub fn extract_bytes(&mut self, out: &mut [u8]) {
self.endian_swap();
let st_bytes = self.bytes_view();
out.copy_from_slice(&st_bytes[..out.len()]);
self.endian_swap();
}
}
impl Drop for Xoodoo {
fn drop(&mut self) {
self.st.zeroize()
}
}