1mod eng256;
49mod eng512;
50mod impl256;
51mod impl512;
52mod initials;
53
54use crate::cryptoutil::FixedBuffer;
55use initials::*;
56
57macro_rules! digest {
58 (256 $name:ident, $ctxname:ident, $output_fn: ident, $output_bits:expr, $state:ident) => {
59 digest!(
60 @internal
61 $name,
62 $ctxname,
63 Engine256,
64 $output_fn,
65 $output_bits,
66 64,
67 $state
68 );
69 };
70 (512 $name:ident, $ctxname:ident, $output_fn:ident, $output_bits:expr, $state:ident) => {
71 digest!(
72 @internal
73 $name,
74 $ctxname,
75 Engine512,
76 $output_fn,
77 $output_bits,
78 128,
79 $state
80 );
81 };
82 (@internal $name:ident, $ctxname:ident, $init:ident, $output_fn:ident, $output_bits:expr, $block_size:literal, $state: ident) => {
83 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
85 pub struct $name;
86
87 impl $name {
88 pub const OUTPUT_BITS: usize = $output_bits;
90
91 pub const BLOCK_BYTES: usize = $block_size;
94
95 pub fn new() -> $ctxname {
97 $ctxname::new()
98 }
99 }
100
101 #[derive(Clone)]
103 pub struct $ctxname {
104 engine: $init,
105 }
106
107 impl $ctxname {
108 pub const fn new() -> Self {
110 Self {
111 engine: $init::new(&$state),
112 }
113 }
114
115 pub fn update_mut(&mut self, input: &[u8]) {
119 self.engine.input(input)
120 }
121
122 pub fn update(mut self, input: &[u8]) -> Self {
124 self.engine.input(input);
125 self
126 }
127
128 pub fn finalize(mut self) -> [u8; $output_bits / 8] {
134 let mut out = [0; $output_bits / 8];
135 self.engine.finish();
136 self.engine.state.$output_fn(&mut out);
137 out
138 }
139
140 pub fn finalize_reset(&mut self) -> [u8; $output_bits / 8] {
143 let mut out = [0; $output_bits / 8];
144 self.engine.finish();
145 self.engine.state.$output_fn(&mut out);
146 self.reset();
147 out
148 }
149
150 pub fn reset(&mut self) {
152 self.engine.reset(&$state);
153 }
154 }
155 };
156}
157
158#[derive(Clone)]
161struct Engine512 {
162 processed_bytes: u128,
163 buffer: FixedBuffer<128>,
164 state: eng512::Engine,
165}
166
167impl Engine512 {
168 const fn new(h: &[u64; eng512::STATE_LEN]) -> Engine512 {
169 Engine512 {
170 processed_bytes: 0,
171 buffer: FixedBuffer::new(),
172 state: eng512::Engine::new(h),
173 }
174 }
175
176 fn reset(&mut self, h: &[u64; eng512::STATE_LEN]) {
177 self.processed_bytes = 0;
178 self.buffer.reset();
179 self.state.reset(h);
180 }
181
182 fn input(&mut self, input: &[u8]) {
183 self.processed_bytes += input.len() as u128;
184 let self_state = &mut self.state;
185 self.buffer.input(input, |input| self_state.blocks(input));
186 }
187
188 fn finish(&mut self) {
189 let self_state = &mut self.state;
190 self.buffer
191 .standard_padding(16, |input| self_state.blocks(input));
192 *self.buffer.next::<16>() = (self.processed_bytes << 3).to_be_bytes();
193 self.state.blocks(self.buffer.full_buffer());
194 }
195}
196
197#[derive(Clone)]
200struct Engine256 {
201 processed_bytes: u64,
202 buffer: FixedBuffer<64>,
203 state: eng256::Engine,
204 finished: bool,
205}
206
207impl Engine256 {
208 const fn new(h: &[u32; eng256::STATE_LEN]) -> Engine256 {
209 Engine256 {
210 processed_bytes: 0,
211 buffer: FixedBuffer::new(),
212 state: eng256::Engine::new(h),
213 finished: false,
214 }
215 }
216
217 fn reset(&mut self, h: &[u32; eng256::STATE_LEN]) {
218 self.processed_bytes = 0;
219 self.buffer.reset();
220 self.state.reset(h);
221 self.finished = false;
222 }
223
224 fn input(&mut self, input: &[u8]) {
225 assert!(!self.finished);
226 self.processed_bytes += input.len() as u64;
227 let self_state = &mut self.state;
228 self.buffer.input(input, |input| self_state.blocks(input));
229 }
230
231 fn finish(&mut self) {
232 if self.finished {
233 return;
234 }
235
236 let self_state = &mut self.state;
237 self.buffer
238 .standard_padding(8, |input| self_state.blocks(input));
239 *self.buffer.next::<8>() = (self.processed_bytes << 3).to_be_bytes();
240 self.state.blocks(self.buffer.full_buffer());
241
242 self.finished = true;
243 }
244}
245
246digest!(512 Sha512, Context512, output_512bits_at, 512, H512);
247digest!(512 Sha384, Context384, output_384bits_at, 384, H384);
248digest!(
249 512
250 Sha512Trunc256,
251 Context512_256,
252 output_256bits_at,
253 256,
254 H512_TRUNC_256
255);
256digest!(
257 512
258 Sha512Trunc224,
259 Context512_224,
260 output_224bits_at,
261 224,
262 H512_TRUNC_224
263);
264digest!(256 Sha256, Context256, output_256bits_at, 256, H256);
265digest!(256 Sha224, Context224, output_224bits_at, 224, H224);
266
267#[cfg(test)]
268mod tests {
269 use super::super::tests::{test_hashing, Test};
270 use super::*;
271
272 #[test]
273 fn test_sha512() {
274 let tests = [
276 Test {
277 input: b"",
278 output: [
279 0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd, 0xf1, 0x54, 0x28, 0x50, 0xd6,
280 0x6d, 0x80, 0x07, 0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc, 0x83, 0xf4,
281 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce, 0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2,
282 0xb0, 0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f, 0x63, 0xb9, 0x31, 0xbd,
283 0x47, 0x41, 0x7a, 0x81, 0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e,
284 ],
285 },
286 Test {
287 input: b"The quick brown fox jumps over the lazy dog",
288 output: [
289 0x07, 0xe5, 0x47, 0xd9, 0x58, 0x6f, 0x6a, 0x73, 0xf7, 0x3f, 0xba, 0xc0, 0x43,
290 0x5e, 0xd7, 0x69, 0x51, 0x21, 0x8f, 0xb7, 0xd0, 0xc8, 0xd7, 0x88, 0xa3, 0x09,
291 0xd7, 0x85, 0x43, 0x6b, 0xbb, 0x64, 0x2e, 0x93, 0xa2, 0x52, 0xa9, 0x54, 0xf2,
292 0x39, 0x12, 0x54, 0x7d, 0x1e, 0x8a, 0x3b, 0x5e, 0xd6, 0xe1, 0xbf, 0xd7, 0x09,
293 0x78, 0x21, 0x23, 0x3f, 0xa0, 0x53, 0x8f, 0x3d, 0xb8, 0x54, 0xfe, 0xe6,
294 ],
295 },
296 Test {
297 input: b"The quick brown fox jumps over the lazy dog.",
298 output: [
299 0x91, 0xea, 0x12, 0x45, 0xf2, 0x0d, 0x46, 0xae, 0x9a, 0x03, 0x7a, 0x98, 0x9f,
300 0x54, 0xf1, 0xf7, 0x90, 0xf0, 0xa4, 0x76, 0x07, 0xee, 0xb8, 0xa1, 0x4d, 0x12,
301 0x89, 0x0c, 0xea, 0x77, 0xa1, 0xbb, 0xc6, 0xc7, 0xed, 0x9c, 0xf2, 0x05, 0xe6,
302 0x7b, 0x7f, 0x2b, 0x8f, 0xd4, 0xc7, 0xdf, 0xd3, 0xa7, 0xa8, 0x61, 0x7e, 0x45,
303 0xf3, 0xc4, 0x63, 0xd4, 0x81, 0xc7, 0xe5, 0x86, 0xc3, 0x9a, 0xc1, 0xed,
304 ],
305 },
306 ];
307 test_hashing(
308 &tests,
309 Sha512,
310 |_| Context512::new(),
311 |ctx, input| ctx.update(input),
312 |ctx, input| ctx.update_mut(input),
313 |ctx| ctx.finalize(),
314 |ctx| ctx.finalize_reset(),
315 |ctx| ctx.reset(),
316 )
317 }
318
319 #[test]
320 fn test_sha384() {
321 let tests = [
323 Test {
324 input: b"",
325 output: [
326 0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38, 0x4c, 0xd9, 0x32, 0x7e, 0xb1,
327 0xb1, 0xe3, 0x6a, 0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43, 0x4c, 0x0c,
328 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda, 0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65,
329 0xfb, 0xd5, 0x1a, 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b,
330 ],
331 },
332 Test {
333 input: b"The quick brown fox jumps over the lazy dog",
334 output: [
335 0xca, 0x73, 0x7f, 0x10, 0x14, 0xa4, 0x8f, 0x4c, 0x0b, 0x6d, 0xd4, 0x3c, 0xb1,
336 0x77, 0xb0, 0xaf, 0xd9, 0xe5, 0x16, 0x93, 0x67, 0x54, 0x4c, 0x49, 0x40, 0x11,
337 0xe3, 0x31, 0x7d, 0xbf, 0x9a, 0x50, 0x9c, 0xb1, 0xe5, 0xdc, 0x1e, 0x85, 0xa9,
338 0x41, 0xbb, 0xee, 0x3d, 0x7f, 0x2a, 0xfb, 0xc9, 0xb1,
339 ],
340 },
341 Test {
342 input: b"The quick brown fox jumps over the lazy dog.",
343 output: [
344 0xed, 0x89, 0x24, 0x81, 0xd8, 0x27, 0x2c, 0xa6, 0xdf, 0x37, 0x0b, 0xf7, 0x06,
345 0xe4, 0xd7, 0xbc, 0x1b, 0x57, 0x39, 0xfa, 0x21, 0x77, 0xaa, 0xe6, 0xc5, 0x0e,
346 0x94, 0x66, 0x78, 0x71, 0x8f, 0xc6, 0x7a, 0x7a, 0xf2, 0x81, 0x9a, 0x02, 0x1c,
347 0x2f, 0xc3, 0x4e, 0x91, 0xbd, 0xb6, 0x34, 0x09, 0xd7,
348 ],
349 },
350 ];
351 test_hashing(
352 &tests,
353 Sha384,
354 |_| Context384::new(),
355 |ctx, input| ctx.update(input),
356 |ctx, input| ctx.update_mut(input),
357 |ctx| ctx.finalize(),
358 |ctx| ctx.finalize_reset(),
359 |ctx| ctx.reset(),
360 )
361 }
362
363 #[test]
364 fn test_sha512_256() {
365 let tests = [
367 Test {
368 input: b"",
369 output: [
370 0xc6, 0x72, 0xb8, 0xd1, 0xef, 0x56, 0xed, 0x28, 0xab, 0x87, 0xc3, 0x62, 0x2c,
371 0x51, 0x14, 0x06, 0x9b, 0xdd, 0x3a, 0xd7, 0xb8, 0xf9, 0x73, 0x74, 0x98, 0xd0,
372 0xc0, 0x1e, 0xce, 0xf0, 0x96, 0x7a,
373 ],
374 },
375 Test {
376 input: b"The quick brown fox jumps over the lazy dog",
377 output: [
378 0xdd, 0x9d, 0x67, 0xb3, 0x71, 0x51, 0x9c, 0x33, 0x9e, 0xd8, 0xdb, 0xd2, 0x5a,
379 0xf9, 0x0e, 0x97, 0x6a, 0x1e, 0xee, 0xfd, 0x4a, 0xd3, 0xd8, 0x89, 0x00, 0x5e,
380 0x53, 0x2f, 0xc5, 0xbe, 0xf0, 0x4d,
381 ],
382 },
383 Test {
384 input: b"The quick brown fox jumps over the lazy dog.",
385 output: [
386 0x15, 0x46, 0x74, 0x18, 0x40, 0xf8, 0xa4, 0x92, 0xb9, 0x59, 0xd9, 0xb8, 0xb2,
387 0x34, 0x4b, 0x9b, 0x0e, 0xb5, 0x1b, 0x00, 0x4b, 0xba, 0x35, 0xc0, 0xae, 0xba,
388 0xac, 0x86, 0xd4, 0x52, 0x64, 0xc3,
389 ],
390 },
391 ];
392 test_hashing(
393 &tests,
394 Sha512Trunc256,
395 |_| Context512_256::new(),
396 |ctx, input| ctx.update(input),
397 |ctx, input| ctx.update_mut(input),
398 |ctx| ctx.finalize(),
399 |ctx| ctx.finalize_reset(),
400 |ctx| ctx.reset(),
401 )
402 }
403
404 #[test]
405 fn test_sha512_224() {
406 let tests = [
408 Test {
409 input: b"",
410 output: [
411 0x6e, 0xd0, 0xdd, 0x02, 0x80, 0x6f, 0xa8, 0x9e, 0x25, 0xde, 0x06, 0x0c, 0x19,
412 0xd3, 0xac, 0x86, 0xca, 0xbb, 0x87, 0xd6, 0xa0, 0xdd, 0xd0, 0x5c, 0x33, 0x3b,
413 0x84, 0xf4,
414 ],
415 },
416 Test {
417 input: b"The quick brown fox jumps over the lazy dog",
418 output: [
419 0x94, 0x4c, 0xd2, 0x84, 0x7f, 0xb5, 0x45, 0x58, 0xd4, 0x77, 0x5d, 0xb0, 0x48,
420 0x5a, 0x50, 0x00, 0x31, 0x11, 0xc8, 0xe5, 0xda, 0xa6, 0x3f, 0xe7, 0x22, 0xc6,
421 0xaa, 0x37,
422 ],
423 },
424 Test {
425 input: b"The quick brown fox jumps over the lazy dog.",
426 output: [
427 0x6d, 0x6a, 0x92, 0x79, 0x49, 0x5e, 0xc4, 0x06, 0x17, 0x69, 0x75, 0x2e, 0x7f,
428 0xf9, 0xc6, 0x8b, 0x6b, 0x0b, 0x3c, 0x5a, 0x28, 0x1b, 0x79, 0x17, 0xce, 0x05,
429 0x72, 0xde,
430 ],
431 },
432 ];
433 test_hashing(
434 &tests,
435 Sha512Trunc224,
436 |_| Context512_224::new(),
437 |ctx, input| ctx.update(input),
438 |ctx, input| ctx.update_mut(input),
439 |ctx| ctx.finalize(),
440 |ctx| ctx.finalize_reset(),
441 |ctx| ctx.reset(),
442 )
443 }
444
445 #[test]
446 fn test_sha256() {
447 let tests = [
449 Test {
450 input: b"",
451 output: [
452 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99,
453 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95,
454 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55,
455 ],
456 },
457 Test {
458 input: b"The quick brown fox jumps over the lazy dog",
459 output: [
460 0xd7, 0xa8, 0xfb, 0xb3, 0x07, 0xd7, 0x80, 0x94, 0x69, 0xca, 0x9a, 0xbc, 0xb0,
461 0x08, 0x2e, 0x4f, 0x8d, 0x56, 0x51, 0xe4, 0x6d, 0x3c, 0xdb, 0x76, 0x2d, 0x02,
462 0xd0, 0xbf, 0x37, 0xc9, 0xe5, 0x92,
463 ],
464 },
465 Test {
466 input: b"The quick brown fox jumps over the lazy dog.",
467 output: [
468 0xef, 0x53, 0x7f, 0x25, 0xc8, 0x95, 0xbf, 0xa7, 0x82, 0x52, 0x65, 0x29, 0xa9,
469 0xb6, 0x3d, 0x97, 0xaa, 0x63, 0x15, 0x64, 0xd5, 0xd7, 0x89, 0xc2, 0xb7, 0x65,
470 0x44, 0x8c, 0x86, 0x35, 0xfb, 0x6c,
471 ],
472 },
473 ];
474 test_hashing(
475 &tests,
476 Sha256,
477 |_| Context256::new(),
478 |ctx, input| ctx.update(input),
479 |ctx, input| ctx.update_mut(input),
480 |ctx| ctx.finalize(),
481 |ctx| ctx.finalize_reset(),
482 |ctx| ctx.reset(),
483 )
484 }
485
486 #[test]
487 fn test_sha224() {
488 let tests = [
490 Test {
491 input: b"",
492 output: [
493 0xd1, 0x4a, 0x02, 0x8c, 0x2a, 0x3a, 0x2b, 0xc9, 0x47, 0x61, 0x02, 0xbb, 0x28,
494 0x82, 0x34, 0xc4, 0x15, 0xa2, 0xb0, 0x1f, 0x82, 0x8e, 0xa6, 0x2a, 0xc5, 0xb3,
495 0xe4, 0x2f,
496 ],
497 },
498 Test {
499 input: b"The quick brown fox jumps over the lazy dog",
500 output: [
501 0x73, 0x0e, 0x10, 0x9b, 0xd7, 0xa8, 0xa3, 0x2b, 0x1c, 0xb9, 0xd9, 0xa0, 0x9a,
502 0xa2, 0x32, 0x5d, 0x24, 0x30, 0x58, 0x7d, 0xdb, 0xc0, 0xc3, 0x8b, 0xad, 0x91,
503 0x15, 0x25,
504 ],
505 },
506 Test {
507 input: b"The quick brown fox jumps over the lazy dog.",
508 output: [
509 0x61, 0x9c, 0xba, 0x8e, 0x8e, 0x05, 0x82, 0x6e, 0x9b, 0x8c, 0x51, 0x9c, 0x0a,
510 0x5c, 0x68, 0xf4, 0xfb, 0x65, 0x3e, 0x8a, 0x3d, 0x8a, 0xa0, 0x4b, 0xb2, 0xc8,
511 0xcd, 0x4c,
512 ],
513 },
514 ];
515 test_hashing(
516 &tests,
517 Sha224,
518 |_| Context224::new(),
519 |ctx, input| ctx.update(input),
520 |ctx, input| ctx.update_mut(input),
521 |ctx| ctx.finalize(),
522 |ctx| ctx.finalize_reset(),
523 |ctx| ctx.reset(),
524 )
525 }
526}
527
528#[cfg(all(test, feature = "with-bench"))]
529mod bench {
530 use super::eng256;
531 use super::eng512;
532 use super::{Sha256, Sha512};
533 use test::Bencher;
534
535 #[bench]
536 pub fn sha256_block(bh: &mut Bencher) {
537 let mut state = eng256::Engine::new(&[0u32; eng256::STATE_LEN]);
538 let block = [1u8; 64];
539 bh.iter(|| {
540 state.blocks(&block);
541 });
542 bh.bytes = 64u64;
543 }
544
545 #[bench]
546 pub fn sha512_block(bh: &mut Bencher) {
547 let mut state = eng512::Engine::new(&[0u64; eng512::STATE_LEN]);
548 let block = [1u8; 128];
549 bh.iter(|| {
550 state.blocks(&block);
551 });
552 bh.bytes = 128u64;
553 }
554
555 #[bench]
556 pub fn sha256_10(bh: &mut Bencher) {
557 let mut sh = Sha256::new();
558 let bytes = [1u8; 10];
559 bh.iter(|| {
560 sh.update_mut(&bytes);
561 });
562 bh.bytes = bytes.len() as u64;
563 }
564
565 #[bench]
566 pub fn sha256_1k(bh: &mut Bencher) {
567 let mut sh = Sha256::new();
568 let bytes = [1u8; 1000];
569 bh.iter(|| {
570 sh.update_mut(&bytes);
571 });
572 bh.bytes = bytes.len() as u64;
573 }
574
575 #[bench]
576 pub fn sha256_64k(bh: &mut Bencher) {
577 let mut sh = Sha256::new();
578 let bytes = [1u8; 65536];
579 bh.iter(|| {
580 sh.update_mut(&bytes);
581 });
582 bh.bytes = bytes.len() as u64;
583 }
584
585 #[bench]
586 pub fn sha512_10(bh: &mut Bencher) {
587 let mut sh = Sha512::new();
588 let bytes = [1u8; 10];
589 bh.iter(|| {
590 sh.update_mut(&bytes);
591 });
592 bh.bytes = bytes.len() as u64;
593 }
594
595 #[bench]
596 pub fn sha512_1k(bh: &mut Bencher) {
597 let mut sh = Sha512::new();
598 let bytes = [1u8; 1024];
599 bh.iter(|| {
600 sh.update_mut(&bytes);
601 });
602 bh.bytes = bytes.len() as u64;
603 }
604
605 #[bench]
606 pub fn sha512_64k(bh: &mut Bencher) {
607 let mut sh = Sha512::new();
608 let bytes = [1u8; 65536];
609 bh.iter(|| {
610 sh.update_mut(&bytes);
611 });
612 bh.bytes = bytes.len() as u64;
613 }
614}