1#![no_std]
4
5extern crate block_buffer;
6pub extern crate digest;
7extern crate threefish_cipher;
8
9pub use digest::generic_array::GenericArray;
10pub use digest::Digest;
11
12use block_buffer::block_padding::ZeroPadding;
13use block_buffer::BlockBuffer;
14use digest::generic_array::typenum::{NonZero, PartialDiv, Unsigned, U128, U32, U64, U8};
15use digest::generic_array::ArrayLength;
16use threefish_cipher::{BlockCipher, Threefish1024, Threefish256, Threefish512};
17
18#[derive(Copy, Clone)]
20union Block<N>
21where
22 N: ArrayLength<u8>,
23 N: PartialDiv<U8>,
24 <N as PartialDiv<U8>>::Output: ArrayLength<u64>,
25 N::ArrayType: Copy,
26 <<N as PartialDiv<U8>>::Output as ArrayLength<u64>>::ArrayType: Copy,
27{
28 bytes: GenericArray<u8, N>,
29 words: GenericArray<u64, <N as PartialDiv<U8>>::Output>,
30}
31
32impl<N> Block<N>
33where
34 N: ArrayLength<u8>,
35 N: PartialDiv<U8>,
36 <N as PartialDiv<U8>>::Output: ArrayLength<u64>,
37 N::ArrayType: Copy,
38 <<N as PartialDiv<U8>>::Output as ArrayLength<u64>>::ArrayType: Copy,
39{
40 fn bytes(&mut self) -> &[u8] {
41 self.as_byte_array().as_slice()
42 }
43
44 fn as_byte_array(&self) -> &GenericArray<u8, N> {
45 unsafe { &self.bytes }
46 }
47
48 fn as_byte_array_mut(&mut self) -> &mut GenericArray<u8, N> {
49 unsafe { &mut self.bytes }
50 }
51
52 fn from_byte_array(block: &GenericArray<u8, N>) -> Self {
53 Block { bytes: *block }
54 }
55}
56
57impl<N> Default for Block<N>
58where
59 N: ArrayLength<u8>,
60 N: PartialDiv<U8>,
61 <N as PartialDiv<U8>>::Output: ArrayLength<u64>,
62 N::ArrayType: Copy,
63 <<N as PartialDiv<U8>>::Output as ArrayLength<u64>>::ArrayType: Copy,
64{
65 fn default() -> Self {
66 Block {
67 words: GenericArray::default(),
68 }
69 }
70}
71
72impl<N> core::ops::BitXor<Block<N>> for Block<N>
73where
74 N: ArrayLength<u8>,
75 N: PartialDiv<U8>,
76 <N as PartialDiv<U8>>::Output: ArrayLength<u64>,
77 N::ArrayType: Copy,
78 <<N as PartialDiv<U8>>::Output as ArrayLength<u64>>::ArrayType: Copy,
79{
80 type Output = Block<N>;
81 fn bitxor(mut self, rhs: Block<N>) -> Self::Output {
82 for (s, r) in unsafe { &mut self.words }
84 .iter_mut()
85 .zip(unsafe { &rhs.words })
86 {
87 *s ^= *r;
88 }
89 self
90 }
91}
92
93#[derive(Clone)]
94struct State<X> {
95 t: (u64, u64),
96 x: X,
97}
98
99impl<X> State<X> {
100 fn new(t1: u64, x: X) -> Self {
101 let t = (0, t1);
102 State { t, x }
103 }
104}
105
106impl<X> core::fmt::Debug for State<X> {
107 fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
108 f.debug_struct("State<X>")
109 .field("t", &"(unknown)")
110 .field("x", &"(unknown)")
111 .finish()
112 }
113}
114
115const VERSION: u64 = 1;
116const ID_STRING_LE: u64 = 0x3341_4853;
117const SCHEMA_VER: u64 = (VERSION << 32) | ID_STRING_LE;
118const CFG_TREE_INFO_SEQUENTIAL: u64 = 0;
119const T1_FLAG_FIRST: u64 = 1 << 62;
120const T1_FLAG_FINAL: u64 = 1 << 63;
121const T1_BLK_TYPE_CFG: u64 = 4 << 56;
122const T1_BLK_TYPE_MSG: u64 = 48 << 56;
123const T1_BLK_TYPE_OUT: u64 = 63 << 56;
124const CFG_STR_LEN: usize = 4 * 8;
125
126macro_rules! define_hasher {
127 ($name:ident, $threefish:ident, $state_bytes:ty, $state_bits:expr) => {
128 #[derive(Clone)]
129 pub struct $name<N: Unsigned + ArrayLength<u8> + NonZero + Default> {
130 state: State<Block<$state_bytes>>,
131 buffer: BlockBuffer<$state_bytes>,
132 _output: core::marker::PhantomData<GenericArray<u8, N>>,
133 }
134
135 impl<N> core::fmt::Debug for $name<N>
136 where
137 N: Unsigned + ArrayLength<u8> + NonZero + Default,
138 {
139 fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
140 f.debug_struct("Skein")
141 .field("state", &self.state)
142 .field("buffer.position()", &self.buffer.position())
143 .finish()
144 }
145 }
146
147 impl<N> $name<N>
148 where
149 N: Unsigned + ArrayLength<u8> + NonZero + Default,
150 {
151 fn process_block(
152 state: &mut State<Block<$state_bytes>>,
153 block: &GenericArray<u8, $state_bytes>,
154 byte_count_add: usize,
155 ) {
156 let block = Block::from_byte_array(block);
157 state.t.0 += byte_count_add as u64;
158 let fish = $threefish::with_tweak(state.x.as_byte_array(), state.t.0, state.t.1);
159 let mut x = block.clone();
160 fish.encrypt_block(x.as_byte_array_mut());
161 state.x = x ^ block;
162 state.t.1 &= !T1_FLAG_FIRST;
163 }
164 }
165
166 impl<N> Default for $name<N>
167 where
168 N: Unsigned + ArrayLength<u8> + NonZero + Default,
169 {
170 fn default() -> Self {
171 let mut state = State::new(
173 T1_FLAG_FIRST | T1_BLK_TYPE_CFG | T1_FLAG_FINAL,
174 Block::default(),
175 );
176 let mut cfg = GenericArray::<u8, $state_bytes>::default();
177 cfg[..8].copy_from_slice(&SCHEMA_VER.to_le_bytes());
178 cfg[8..16].copy_from_slice(&(N::to_u64() * 8).to_le_bytes());
179 cfg[16..24].copy_from_slice(&CFG_TREE_INFO_SEQUENTIAL.to_le_bytes());
180 Self::process_block(&mut state, &cfg, CFG_STR_LEN);
181
182 state.t = Default::default();
185 state.t.1 = T1_FLAG_FIRST | T1_BLK_TYPE_MSG;
186 Self {
187 state,
188 buffer: Default::default(),
189 _output: Default::default(),
190 }
191 }
192 }
193
194 impl<N> digest::BlockInput for $name<N>
195 where
196 N: Unsigned + ArrayLength<u8> + NonZero + Default,
197 {
198 type BlockSize = <$threefish as BlockCipher>::BlockSize;
199 }
200
201 impl<N> digest::Update for $name<N>
202 where
203 N: Unsigned + ArrayLength<u8> + NonZero + Default,
204 {
205 fn update(&mut self, data: impl AsRef<[u8]>) {
206 let buffer = &mut self.buffer;
207 let state = &mut self.state;
208 buffer.input_lazy(data.as_ref(), |block| {
209 Self::process_block(state, block, $state_bits / 8)
210 });
211 }
212 }
213
214 impl<N> digest::FixedOutputDirty for $name<N>
215 where
216 N: Unsigned + ArrayLength<u8> + NonZero + Default,
217 {
218 type OutputSize = N;
219
220 fn finalize_into_dirty(&mut self, output: &mut GenericArray<u8, Self::OutputSize>) {
221 self.state.t.1 |= T1_FLAG_FINAL;
222 let pos = self.buffer.position();
223 let final_block = self.buffer.pad_with::<ZeroPadding>().unwrap();
224 Self::process_block(&mut self.state, final_block, pos);
225
226 for (i, chunk) in output.chunks_mut($state_bits / 8).enumerate() {
228 let mut ctr = State::new(
229 T1_FLAG_FIRST | T1_BLK_TYPE_OUT | T1_FLAG_FINAL,
230 self.state.x,
231 );
232 let mut b = GenericArray::<u8, $state_bytes>::default();
233 b[..8].copy_from_slice(&(i as u64).to_le_bytes());
234 Self::process_block(&mut ctr, &b, 8);
235 let n = chunk.len();
236 chunk.copy_from_slice(&ctr.x.bytes()[..n]);
237 }
238 }
239 }
240
241 impl<N> digest::Reset for $name<N>
242 where
243 N: Unsigned + ArrayLength<u8> + NonZero + Default,
244 {
245 fn reset(&mut self) {
246 *self = Self::default();
247 }
248 }
249 };
250}
251
252#[rustfmt::skip]
253define_hasher!(Skein256, Threefish256, U32, 256);
254#[rustfmt::skip]
255define_hasher!(Skein512, Threefish512, U64, 512);
256#[rustfmt::skip]
257define_hasher!(Skein1024, Threefish1024, U128, 1024);