1#![no_std]
8#![doc = include_str!("../README.md")]
9#![deny(missing_docs)]
10#![deny(rustdoc::broken_intra_doc_links)]
11
12extern crate alloc;
13use alloc::vec::Vec;
14
15mod error;
16mod sponge;
17
18pub use error::Error;
19pub use sponge::{Safe, Sponge};
20
21#[cfg(feature = "encryption")]
22mod encryption;
23#[cfg(feature = "encryption")]
24pub use encryption::{decrypt, encrypt, Encryption};
25
26#[derive(Debug, Clone, Copy, PartialEq)]
33pub enum Call {
34 Absorb(usize),
36 Squeeze(usize),
38}
39
40impl Call {
41 pub fn call_len(&self) -> &usize {
43 match self {
44 Call::Absorb(len) => len,
45 Call::Squeeze(len) => len,
46 }
47 }
48}
49
50fn tag_input(
65 iopattern: impl AsRef<[Call]>,
66 domain_sep: u64,
67) -> Result<Vec<u8>, Error> {
68 validate_io_pattern(iopattern.as_ref())?;
71
72 const ABSORB_MASK: u32 = 0x8000_0000;
74
75 let mut input_u32 = Vec::new();
78 input_u32.push(ABSORB_MASK);
79
80 iopattern.as_ref().iter().for_each(|call| {
82 let l = input_u32.len();
85 let prev = &mut input_u32[l - 1];
86 match call {
87 Call::Absorb(len) if *prev & ABSORB_MASK != 0 => {
89 *prev += *len as u32
90 }
91 Call::Absorb(len) => input_u32.push(ABSORB_MASK + *len as u32),
93 Call::Squeeze(len) if *prev & ABSORB_MASK == 0 => {
96 *prev += *len as u32
97 }
98 Call::Squeeze(len) => input_u32.push(*len as u32),
100 }
101 });
102
103 let mut input: Vec<u8> = input_u32
105 .iter()
106 .flat_map(|u32_int| u32_int.to_be_bytes().into_iter())
107 .collect();
108
109 input.extend(domain_sep.to_be_bytes());
111
112 Ok(input)
113}
114
115fn validate_io_pattern(iopattern: impl AsRef<[Call]>) -> Result<(), Error> {
129 match (iopattern.as_ref().first(), iopattern.as_ref().last()) {
132 (Some(Call::Absorb(_)), Some(Call::Squeeze(_))) => {}
133 _ => return Err(Error::InvalidIOPattern),
134 }
135
136 const MAX_LEN: usize = u32::MAX as usize >> 1;
139 if iopattern.as_ref().iter().any(|call| {
140 let call_len = *call.call_len();
141 call_len == 0 || call_len > MAX_LEN
142 }) {
143 Err(Error::InvalidIOPattern)
144 } else {
145 Ok(())
146 }
147}
148
149#[cfg(test)]
150mod tests {
151 extern crate std;
152 use std::vec;
153
154 use super::*;
155
156 #[test]
157 fn test_validate_io_pattern() {
158 let iopattern = vec![Call::Absorb(42), Call::Squeeze(3)];
160 assert!(validate_io_pattern(&iopattern).is_ok());
161
162 let iopattern = vec![
163 Call::Absorb(42),
164 Call::Absorb(5),
165 Call::Squeeze(4),
166 Call::Squeeze(3),
167 ];
168 assert!(validate_io_pattern(&iopattern).is_ok());
169
170 let iopattern = vec![
171 Call::Absorb(42),
172 Call::Absorb(5),
173 Call::Squeeze(4),
174 Call::Absorb(5),
175 Call::Squeeze(3),
176 Call::Squeeze(3),
177 ];
178 assert!(validate_io_pattern(&iopattern).is_ok());
179
180 let iopattern = vec![
181 Call::Absorb(42),
182 Call::Squeeze(4),
183 Call::Absorb(5),
184 Call::Squeeze(4),
185 Call::Absorb(5),
186 Call::Squeeze(3),
187 Call::Absorb(5),
188 Call::Squeeze(3),
189 ];
190 assert!(validate_io_pattern(&iopattern).is_ok());
191
192 let iopattern = vec![];
194 assert!(validate_io_pattern(&iopattern).is_err());
195
196 let iopattern = vec![Call::Absorb(2)];
197 assert!(validate_io_pattern(&iopattern).is_err());
198
199 let iopattern = vec![Call::Squeeze(2)];
200 assert!(validate_io_pattern(&iopattern).is_err());
201
202 let iopattern = vec![Call::Absorb(0), Call::Squeeze(2)];
203 assert!(validate_io_pattern(&iopattern).is_err());
204
205 let iopattern = vec![Call::Absorb(42), Call::Squeeze(0)];
206 assert!(validate_io_pattern(&iopattern).is_err());
207
208 let iopattern =
209 vec![Call::Squeeze(42), Call::Absorb(3), Call::Squeeze(4)];
210 assert!(validate_io_pattern(&iopattern).is_err());
211
212 let iopattern = vec![
213 Call::Absorb(42),
214 Call::Absorb(3),
215 Call::Squeeze(4),
216 Call::Absorb(3),
217 ];
218 assert!(validate_io_pattern(&iopattern).is_err());
219
220 let iopattern = vec![
221 Call::Absorb(42),
222 Call::Absorb(3),
223 Call::Squeeze(0),
224 Call::Absorb(3),
225 Call::Squeeze(4),
226 ];
227 assert!(validate_io_pattern(&iopattern).is_err());
228
229 let iopattern =
230 vec![Call::Absorb(3), Call::Absorb(1 << 31), Call::Squeeze(1)];
231 assert!(validate_io_pattern(&iopattern).is_err());
232 }
233
234 #[test]
235 fn test_tag_input() -> Result<(), Error> {
236 let domain_sep = 42;
237
238 let pattern1 = vec![Call::Absorb(2), Call::Squeeze(10)];
240 let pattern2 = vec![Call::Absorb(2), Call::Squeeze(1)];
241 assert_ne!(
242 tag_input(&pattern1, domain_sep)?,
243 tag_input(&pattern2, domain_sep)?
244 );
245
246 let pattern1 = vec![Call::Absorb(2), Call::Squeeze(1)];
248 let pattern2 = vec![Call::Absorb(2), Call::Squeeze(1)];
249 assert_eq!(
250 tag_input(&pattern1, domain_sep)?,
251 tag_input(&pattern2, domain_sep)?
252 );
253
254 let pattern1 = vec![Call::Absorb(1), Call::Absorb(1), Call::Squeeze(1)];
255 let pattern2 = vec![Call::Absorb(2), Call::Squeeze(1)];
256 assert_eq!(
257 tag_input(&pattern1, domain_sep)?,
258 tag_input(&pattern2, domain_sep)?
259 );
260
261 let pattern1 = vec![Call::Absorb(2), Call::Squeeze(10)];
262 let pattern2 = vec![
263 Call::Absorb(2),
264 Call::Squeeze(1),
265 Call::Squeeze(1),
266 Call::Squeeze(8),
267 ];
268 assert_eq!(
269 tag_input(&pattern1, domain_sep)?,
270 tag_input(&pattern2, domain_sep)?
271 );
272
273 let pattern1 = vec![
274 Call::Absorb(2),
275 Call::Absorb(2),
276 Call::Squeeze(1),
277 Call::Squeeze(1),
278 Call::Squeeze(1),
279 Call::Absorb(2),
280 Call::Absorb(2),
281 Call::Squeeze(1),
282 Call::Squeeze(8),
283 ];
284 let pattern2 = vec![
285 Call::Absorb(3),
286 Call::Absorb(1),
287 Call::Squeeze(2),
288 Call::Squeeze(1),
289 Call::Absorb(1),
290 Call::Absorb(3),
291 Call::Squeeze(5),
292 Call::Squeeze(4),
293 ];
294 assert_eq!(
295 tag_input(&pattern1, domain_sep)?,
296 tag_input(&pattern2, domain_sep)?
297 );
298
299 Ok(())
300 }
301}