1use super::{FarfalleConfig, RollFunction};
4use crypto_permutation::{Permutation, PermutationState, WriteTooLargeError, Writer};
5
6#[derive(Clone)]
13#[cfg_attr(feature = "debug", derive(Debug, PartialEq))]
14pub struct Farfalle<C: FarfalleConfig> {
15 pub(super) key: C::State,
16 pub(super) state: C::State,
17 pub(super) config: C,
18}
19
20const PAD_BYTE: u8 = 1;
21
22impl<C: FarfalleConfig> Farfalle<C> {
23 fn key_expand(key: &[u8], p_b: C::PermutationB) -> C::State {
24 assert!(key.len() < C::State::SIZE);
25 let mut key_state = C::State::default();
26 let mut state_writer = key_state.copy_writer();
27 state_writer.write_bytes(key).unwrap();
28 state_writer.write_bytes(&[PAD_BYTE]).unwrap();
29 state_writer.finish();
30 p_b.apply(&mut key_state);
31 key_state
32 }
33
34 pub fn init_custom(key: &[u8], config: C) -> Self {
42 Self {
43 key: Self::key_expand(key, config.perm_b()),
44 state: Default::default(),
45 config,
46 }
47 }
48
49 pub fn init_default(key: &[u8]) -> Self
56 where
57 C: Default,
58 {
59 Self::init_custom(key, C::default())
60 }
61
62 fn roll_c_key(&mut self) {
64 self.config.roll_c().apply(&mut self.key);
65 }
66
67 fn process_block(&mut self, block: &mut C::State) {
71 *block ^= &self.key;
72 self.roll_c_key();
73 self.config.perm_c().apply(block);
74 self.state ^= block;
75 }
76}
77
78pub struct InputWriter<'a, C: FarfalleConfig> {
81 block: C::State,
83 filled: usize,
85 farfalle: &'a mut Farfalle<C>,
87}
88
89impl<'a, C: FarfalleConfig> InputWriter<'a, C> {
90 pub(super) fn new(farfalle: &'a mut Farfalle<C>) -> Self {
92 Self {
93 block: Default::default(),
94 filled: 0,
95 farfalle,
96 }
97 }
98
99 fn process_block(&mut self) {
100 self.farfalle.process_block(&mut self.block);
101 self.filled = 0;
102 }
103}
104
105impl<'a, C: FarfalleConfig> Writer for InputWriter<'a, C> {
106 type Return = ();
107
108 fn capacity(&self) -> usize {
109 usize::MAX
110 }
111
112 fn skip(&mut self, _n: usize) -> Result<(), WriteTooLargeError> {
114 Ok(())
115 }
116
117 fn write_bytes(&mut self, mut data: &[u8]) -> Result<(), WriteTooLargeError> {
118 if self.filled != 0 {
119 let add_partial = core::cmp::min(data.len(), C::State::SIZE - self.filled);
120 let old_filled = self.filled;
121 self.filled += add_partial;
122 let mut block_writer = self.block.copy_writer();
123 block_writer.skip(old_filled).unwrap();
124 block_writer.write_bytes(&data[..add_partial]).unwrap();
125 block_writer.finish();
126 data = &data[add_partial..];
127 if self.filled == C::State::SIZE {
128 self.process_block();
129 }
130 }
131
132 let mut chunks = data.chunks_exact(C::State::SIZE);
133 for chunk in &mut chunks {
134 let mut block_writer = self.block.copy_writer();
135 block_writer.write_bytes(chunk).unwrap();
136 block_writer.finish();
137 self.process_block();
138 }
139
140 let remainder = chunks.remainder();
141 if !remainder.is_empty() {
142 self.filled = remainder.len();
143 let mut block_writer = self.block.copy_writer();
144 block_writer.write_bytes(remainder).unwrap();
145 block_writer.finish();
146 }
147
148 Ok(())
149 }
150
151 fn finish(mut self) {
153 self.write_bytes(&[PAD_BYTE]).unwrap();
154 self.process_block();
155 self.farfalle.roll_c_key();
156 }
157}