1use super::blake2::{EngineS as Engine, LastBlock};
32use crate::cryptoutil::{write_u32v_le, zero};
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
36pub struct Blake2s<const BITS: usize>;
37
38impl<const BITS: usize> Blake2s<BITS> {
39 pub const OUTPUT_BITS: usize = BITS;
41 pub const BLOCK_BYTES: usize = Engine::BLOCK_BYTES;
44
45 pub fn new() -> Context<BITS> {
47 Context::new()
48 }
49 pub fn new_keyed(key: &[u8]) -> Context<BITS> {
51 Context::new_keyed(key)
52 }
53}
54
55#[derive(Clone)]
57pub struct Context<const BITS: usize> {
58 eng: Engine,
59 buf: [u8; Engine::BLOCK_BYTES],
60 buflen: usize,
61}
62
63#[derive(Clone)]
65pub struct ContextDyn {
66 eng: Engine,
67 buf: [u8; Engine::BLOCK_BYTES],
68 buflen: usize,
69 outlen: usize,
70}
71
72impl<const BITS: usize> Context<BITS> {
73 pub fn new() -> Self {
78 assert!(BITS > 0 && ((BITS + 7) / 8) <= Engine::MAX_OUTLEN);
79 Self::new_keyed(&[])
80 }
81
82 pub fn new_keyed(key: &[u8]) -> Self {
85 assert!(BITS > 0 && ((BITS + 7) / 8) <= Engine::MAX_OUTLEN);
86 assert!(key.len() <= Engine::MAX_KEYLEN);
87
88 let mut buf = [0u8; Engine::BLOCK_BYTES];
89
90 let eng = Engine::new((BITS + 7) / 8, key.len());
91 let buflen = if !key.is_empty() {
92 buf[0..key.len()].copy_from_slice(key);
93 Engine::BLOCK_BYTES
94 } else {
95 0
96 };
97
98 Self { eng, buf, buflen }
99 }
100
101 pub fn update(mut self, input: &[u8]) -> Self {
103 self.update_mut(input);
104 self
105 }
106
107 pub fn update_mut(&mut self, mut input: &[u8]) {
111 if input.is_empty() {
112 return;
113 }
114 let fill = Engine::BLOCK_BYTES - self.buflen;
115
116 if input.len() > fill {
117 self.buf[self.buflen..self.buflen + fill].copy_from_slice(&input[0..fill]);
118 self.buflen = 0;
119 self.eng.increment_counter(Engine::BLOCK_BYTES_NATIVE);
120 self.eng
121 .compress(&self.buf[0..Engine::BLOCK_BYTES], LastBlock::No);
122
123 input = &input[fill..];
124
125 while input.len() > Engine::BLOCK_BYTES {
126 self.eng.increment_counter(Engine::BLOCK_BYTES_NATIVE);
127 self.eng
128 .compress(&input[0..Engine::BLOCK_BYTES], LastBlock::No);
129 input = &input[Engine::BLOCK_BYTES..];
130 }
131 }
132 self.buf[self.buflen..self.buflen + input.len()].copy_from_slice(input);
133 self.buflen += input.len();
134 }
135
136 fn internal_final(&mut self) {
137 self.eng.increment_counter(self.buflen as u32);
138 zero(&mut self.buf[self.buflen..]);
139 self.eng
140 .compress(&self.buf[0..Engine::BLOCK_BYTES], LastBlock::Yes);
141
142 write_u32v_le(&mut self.buf[0..32], &self.eng.h);
143 }
144
145 pub fn finalize_at(mut self, out: &mut [u8]) {
152 assert!(out.len() == ((BITS + 7) / 8));
153 self.internal_final();
154 out.copy_from_slice(&self.buf[0..out.len()]);
155 }
156
157 pub fn finalize_reset_at(&mut self, out: &mut [u8]) {
160 assert!(out.len() == ((BITS + 7) / 8));
161 self.internal_final();
162 out.copy_from_slice(&self.buf[0..out.len()]);
163 self.reset();
164 }
165
166 pub fn finalize_reset_with_key_at(&mut self, key: &[u8], out: &mut [u8]) {
168 assert!(out.len() == ((BITS + 7) / 8));
169 self.internal_final();
170 out.copy_from_slice(&self.buf[0..out.len()]);
171 self.reset_with_key(key);
172 }
173
174 pub fn reset(&mut self) {
176 self.eng.reset((BITS + 7) / 8, 0);
177 self.buflen = 0;
178 zero(&mut self.buf[..]);
179 }
180
181 pub fn reset_with_key(&mut self, key: &[u8]) {
183 assert!(key.len() <= Engine::MAX_KEYLEN);
184
185 self.eng.reset((BITS + 7) / 8, key.len());
186 zero(&mut self.buf[..]);
187
188 if !key.is_empty() {
189 self.buf[0..key.len()].copy_from_slice(key);
190 self.buflen = Engine::BLOCK_BYTES;
191 } else {
192 self.buf = [0; Engine::BLOCK_BYTES];
193 self.buflen = 0;
194 }
195 }
196}
197
198impl ContextDyn {
199 pub fn new(output_bytes: usize) -> Self {
204 assert!(output_bytes > 0 && output_bytes <= Engine::MAX_OUTLEN);
205 Self::new_keyed(output_bytes, &[])
206 }
207
208 pub fn new_keyed(output_bytes: usize, key: &[u8]) -> Self {
211 assert!(output_bytes > 0 && output_bytes <= Engine::MAX_OUTLEN);
212 assert!(key.len() <= Engine::MAX_KEYLEN);
213
214 let mut buf = [0u8; Engine::BLOCK_BYTES];
215
216 let eng = Engine::new(output_bytes, key.len());
217 let buflen = if !key.is_empty() {
218 buf[0..key.len()].copy_from_slice(key);
219 Engine::BLOCK_BYTES
220 } else {
221 0
222 };
223
224 Self {
225 eng,
226 buf,
227 buflen,
228 outlen: output_bytes,
229 }
230 }
231
232 pub fn update(mut self, input: &[u8]) -> Self {
234 self.update_mut(input);
235 self
236 }
237
238 pub fn update_mut(&mut self, mut input: &[u8]) {
242 if input.is_empty() {
243 return;
244 }
245 let fill = Engine::BLOCK_BYTES - self.buflen;
246
247 if input.len() > fill {
248 self.buf[self.buflen..self.buflen + fill].copy_from_slice(&input[0..fill]);
249 self.buflen = 0;
250 self.eng.increment_counter(Engine::BLOCK_BYTES_NATIVE);
251 self.eng
252 .compress(&self.buf[0..Engine::BLOCK_BYTES], LastBlock::No);
253
254 input = &input[fill..];
255
256 while input.len() > Engine::BLOCK_BYTES {
257 self.eng.increment_counter(Engine::BLOCK_BYTES_NATIVE);
258 self.eng
259 .compress(&input[0..Engine::BLOCK_BYTES], LastBlock::No);
260 input = &input[Engine::BLOCK_BYTES..];
261 }
262 }
263 self.buf[self.buflen..self.buflen + input.len()].copy_from_slice(input);
264 self.buflen += input.len();
265 }
266
267 fn internal_final(&mut self) {
268 self.eng.increment_counter(self.buflen as u32);
269 zero(&mut self.buf[self.buflen..]);
270 self.eng
271 .compress(&self.buf[0..Engine::BLOCK_BYTES], LastBlock::Yes);
272
273 write_u32v_le(&mut self.buf[0..32], &self.eng.h);
274 }
275
276 pub fn finalize_at(mut self, out: &mut [u8]) {
283 assert!(out.len() == self.outlen);
284 self.internal_final();
285 out.copy_from_slice(&self.buf[0..out.len()]);
286 }
287
288 pub fn finalize_reset_at(&mut self, out: &mut [u8]) {
291 assert!(out.len() == self.outlen);
292 self.internal_final();
293 out.copy_from_slice(&self.buf[0..out.len()]);
294 self.reset();
295 }
296
297 pub fn finalize_reset_with_key_at(&mut self, key: &[u8], out: &mut [u8]) {
299 assert!(out.len() == self.outlen);
300 self.internal_final();
301 out.copy_from_slice(&self.buf[0..out.len()]);
302 self.reset_with_key(key);
303 }
304
305 pub fn reset(&mut self) {
307 self.eng.reset(self.outlen, 0);
308 self.buflen = 0;
309 zero(&mut self.buf[..]);
310 }
311
312 pub fn reset_with_key(&mut self, key: &[u8]) {
314 assert!(key.len() <= Engine::MAX_KEYLEN);
315
316 self.eng.reset(self.outlen, key.len());
317 zero(&mut self.buf[..]);
318
319 if !key.is_empty() {
320 self.buf[0..key.len()].copy_from_slice(key);
321 self.buflen = Engine::BLOCK_BYTES;
322 } else {
323 self.buf = [0; Engine::BLOCK_BYTES];
324 self.buflen = 0;
325 }
326 }
327
328 pub fn output_bits(&self) -> usize {
330 self.outlen * 8
331 }
332}
333
334macro_rules! context_finalize {
337 ($size:literal) => {
338 impl Context<$size> {
339 pub fn finalize(self) -> [u8; $size / 8] {
345 let mut out = [0; $size / 8];
346 self.finalize_at(&mut out);
347 out
348 }
349
350 pub fn finalize_reset(&mut self) -> [u8; $size / 8] {
353 let mut out = [0; $size / 8];
354 self.finalize_reset_at(&mut out);
355 out
356 }
357
358 pub fn finalize_reset_with_key(&mut self, key: &[u8]) -> [u8; $size / 8] {
360 let mut out = [0; $size / 8];
361 self.finalize_reset_with_key_at(key, &mut out);
362 out
363 }
364 }
365 };
366}
367context_finalize!(224);
368context_finalize!(256);
369
370#[cfg(test)]
371mod digest_tests {
372 use super::super::tests::{test_hashing, Test};
373 use super::{Blake2s, Context};
374
375 #[test]
376 fn test_vector() {
377 let tests = [Test {
378 input: b"abc",
379 output: [
380 80, 140, 94, 140, 50, 124, 20, 226, 225, 167, 43, 163, 78, 235, 69, 47, 55, 69,
381 139, 32, 158, 214, 58, 41, 77, 153, 155, 76, 134, 103, 89, 130,
382 ],
383 }];
384
385 test_hashing(
386 &tests,
387 Blake2s::<256>,
388 |_| Context::<256>::new(),
389 |ctx, input| ctx.update(input),
390 |ctx, input| ctx.update_mut(input),
391 |ctx| ctx.finalize(),
392 |ctx| ctx.finalize_reset(),
393 |ctx| ctx.reset(),
394 )
395 }
396}
397
398#[cfg(test)]
399mod mac_tests {
400 use super::super::tests::{test_hashing_keyed, TestKey};
401 use super::{Blake2s, Context};
402
403 #[test]
404 fn test_mac() {
405 let tests = [
406 TestKey {
407 input: &[1, 2, 4, 8],
408 key: &[
409 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
410 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
411 ],
412 output: [
413 0x0e, 0x88, 0xf6, 0x8a, 0xaa, 0x5c, 0x4e, 0xd8, 0xf7, 0xed, 0x28, 0xf8, 0x04,
414 0x45, 0x01, 0x9c, 0x7e, 0xf9, 0x76, 0x2b, 0x4f, 0xf1, 0xad, 0x7e, 0x05, 0x5b,
415 0xa8, 0xc8, 0x82, 0x9e, 0xe2, 0x49,
416 ],
417 },
418 TestKey {
419 input: &[0x00, 0x01, 0x02, 0x03, 0x04, 0x05],
420 key: &[
421 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
422 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
423 ],
424 output: [
425 0xfd, 0xd8, 0x99, 0x3d, 0xcd, 0x43, 0xf6, 0x96, 0xd4, 0x4f, 0x3c, 0xea, 0x0f,
426 0xf3, 0x53, 0x45, 0x23, 0x4e, 0xc8, 0xee, 0x08, 0x3e, 0xb3, 0xca, 0xda, 0x01,
427 0x7c, 0x7f, 0x78, 0xc1, 0x71, 0x43,
428 ],
429 },
430 ];
431
432 test_hashing_keyed(
433 &tests,
434 Blake2s::<256>,
435 |_, k| Context::<256>::new_keyed(k),
436 |ctx, input| ctx.update(input),
437 |ctx, input| ctx.update_mut(input),
438 |ctx| ctx.finalize(),
439 |ctx, key| ctx.finalize_reset_with_key(key),
440 |ctx, key| ctx.reset_with_key(key),
441 )
442 }
443}
444
445#[cfg(all(test, feature = "with-bench"))]
446mod bench {
447 use test::Bencher;
448
449 use super::Blake2s;
450
451 #[bench]
452 pub fn blake2s_10(bh: &mut Bencher) {
453 let mut sh = Blake2s::<256>::new();
454 let bytes = [1u8; 10];
455 bh.iter(|| {
456 sh.update_mut(&bytes);
457 });
458 bh.bytes = bytes.len() as u64;
459 }
460
461 #[bench]
462 pub fn blake2s_1k(bh: &mut Bencher) {
463 let mut sh = Blake2s::<256>::new();
464 let bytes = [1u8; 1024];
465 bh.iter(|| {
466 sh.update_mut(&bytes);
467 });
468 bh.bytes = bytes.len() as u64;
469 }
470
471 #[bench]
472 pub fn blake2s_64k(bh: &mut Bencher) {
473 let mut sh = Blake2s::<256>::new();
474 let bytes = [1u8; 65536];
475 bh.iter(|| {
476 sh.update_mut(&bytes);
477 });
478 bh.bytes = bytes.len() as u64;
479 }
480}