1#![no_std]
29#![doc(
30 html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg",
31 html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg",
32 html_root_url = "https://docs.rs/groestl/0.10.1"
33)]
34#![forbid(unsafe_code)]
35#![warn(rust_2018_idioms)]
36
37pub use digest::{self, Digest};
38
39use core::fmt;
40use digest::{
41 block_buffer::Eager,
42 core_api::{
43 AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, CoreWrapper,
44 CtVariableCoreWrapper, OutputSizeUser, RtVariableCoreWrapper, TruncSide, UpdateCore,
45 VariableOutputCore,
46 },
47 typenum::{Unsigned, U128, U28, U32, U48, U64},
48 HashMarker, InvalidOutputSize, Output,
49};
50
51mod compress1024;
52mod compress512;
53mod table;
54
55#[derive(Clone)]
57pub struct GroestlShortVarCore {
58 state: [u64; compress512::COLS],
59 blocks_len: u64,
60}
61
62impl HashMarker for GroestlShortVarCore {}
63
64impl BlockSizeUser for GroestlShortVarCore {
65 type BlockSize = U64;
66}
67
68impl BufferKindUser for GroestlShortVarCore {
69 type BufferKind = Eager;
70}
71
72impl UpdateCore for GroestlShortVarCore {
73 #[inline]
74 fn update_blocks(&mut self, blocks: &[Block<Self>]) {
75 self.blocks_len += blocks.len() as u64;
76 for block in blocks {
77 compress512::compress(&mut self.state, block.as_ref());
78 }
79 }
80}
81
82impl OutputSizeUser for GroestlShortVarCore {
83 type OutputSize = U32;
84}
85
86impl VariableOutputCore for GroestlShortVarCore {
87 const TRUNC_SIDE: TruncSide = TruncSide::Right;
88
89 #[inline]
90 fn new(output_size: usize) -> Result<Self, InvalidOutputSize> {
91 if output_size > Self::OutputSize::USIZE {
92 return Err(InvalidOutputSize);
93 }
94 let mut state = [0; compress512::COLS];
95 state[compress512::COLS - 1] = 8 * output_size as u64;
96 let blocks_len = 0;
97 Ok(Self { state, blocks_len })
98 }
99
100 #[inline]
101 fn finalize_variable_core(&mut self, buffer: &mut Buffer<Self>, out: &mut Output<Self>) {
102 let blocks_len = if buffer.remaining() <= 8 {
103 self.blocks_len + 2
104 } else {
105 self.blocks_len + 1
106 };
107 buffer.len64_padding_be(blocks_len, |block| {
108 compress512::compress(&mut self.state, block.as_ref())
109 });
110 let res = compress512::p(&self.state);
111 let n = compress512::COLS / 2;
112 for (chunk, v) in out.chunks_exact_mut(8).zip(res[n..].iter()) {
113 chunk.copy_from_slice(&v.to_be_bytes());
114 }
115 }
116}
117
118impl AlgorithmName for GroestlShortVarCore {
119 #[inline]
120 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
121 f.write_str("GroestlShort")
122 }
123}
124
125impl fmt::Debug for GroestlShortVarCore {
126 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
127 f.write_str("GroestlShortVarCore { ... }")
128 }
129}
130
131pub type GroestlShortVar = RtVariableCoreWrapper<GroestlShortVarCore>;
133pub type GroestlShortCore<OutSize> = CtVariableCoreWrapper<GroestlShortVarCore, OutSize>;
135pub type GroestlShort<OutSize> = CoreWrapper<GroestlShortCore<OutSize>>;
137
138pub type Groestl224 = CoreWrapper<GroestlShortCore<U28>>;
140pub type Groestl256 = CoreWrapper<GroestlShortCore<U32>>;
142
143#[derive(Clone)]
145pub struct GroestlLongVarCore {
146 state: [u64; compress1024::COLS],
147 blocks_len: u64,
148}
149
150impl HashMarker for GroestlLongVarCore {}
151
152impl BlockSizeUser for GroestlLongVarCore {
153 type BlockSize = U128;
154}
155
156impl BufferKindUser for GroestlLongVarCore {
157 type BufferKind = Eager;
158}
159
160impl UpdateCore for GroestlLongVarCore {
161 #[inline]
162 fn update_blocks(&mut self, blocks: &[Block<Self>]) {
163 self.blocks_len += blocks.len() as u64;
164 for block in blocks {
165 compress1024::compress(&mut self.state, block.as_ref());
166 }
167 }
168}
169
170impl OutputSizeUser for GroestlLongVarCore {
171 type OutputSize = U64;
172}
173
174impl VariableOutputCore for GroestlLongVarCore {
175 const TRUNC_SIDE: TruncSide = TruncSide::Right;
176
177 #[inline]
178 fn new(output_size: usize) -> Result<Self, InvalidOutputSize> {
179 if output_size > Self::OutputSize::USIZE {
180 return Err(InvalidOutputSize);
181 }
182 let mut state = [0; compress1024::COLS];
183 state[compress1024::COLS - 1] = 8 * output_size as u64;
184 let blocks_len = 0;
185 Ok(Self { state, blocks_len })
186 }
187
188 #[inline]
189 fn finalize_variable_core(&mut self, buffer: &mut Buffer<Self>, out: &mut Output<Self>) {
190 let blocks_len = if buffer.remaining() <= 8 {
191 self.blocks_len + 2
192 } else {
193 self.blocks_len + 1
194 };
195 buffer.len64_padding_be(blocks_len, |block| {
196 compress1024::compress(&mut self.state, block.as_ref())
197 });
198 let res = compress1024::p(&self.state);
199 let n = compress1024::COLS / 2;
200 for (chunk, v) in out.chunks_exact_mut(8).zip(res[n..].iter()) {
201 chunk.copy_from_slice(&v.to_be_bytes());
202 }
203 }
204}
205
206impl AlgorithmName for GroestlLongVarCore {
207 #[inline]
208 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
209 f.write_str("GroestlLong")
210 }
211}
212
213impl fmt::Debug for GroestlLongVarCore {
214 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
215 f.write_str("GroestlLongVarCore { ... }")
216 }
217}
218
219pub type GroestlLongVar = RtVariableCoreWrapper<GroestlLongVarCore>;
221pub type GroestlLongCore<OutSize> = CtVariableCoreWrapper<GroestlLongVarCore, OutSize>;
223pub type GroestlLong<OutSize> = CoreWrapper<GroestlLongCore<OutSize>>;
225
226pub type Groestl384 = CoreWrapper<GroestlLongCore<U48>>;
228pub type Groestl512 = CoreWrapper<GroestlLongCore<U64>>;