1#[cfg(feature = "alloc")]
7use crate::alloc_prelude::*;
8
9use crate::error::{validate, Error, Result};
10use crate::hash::{HashAlgorithm, HashFunction};
11use crate::types::Digest;
12use dcrypt_internal::zeroing::{Zeroize, Zeroizing};
13
14use core::sync::atomic::{compiler_fence, Ordering};
16use dcrypt_common::security::{EphemeralSecret, SecureZeroingType, ZeroizeGuard};
17
18use dcrypt_params::utils::hash::{
19 SHA224_OUTPUT_SIZE, SHA256_BLOCK_SIZE, SHA256_OUTPUT_SIZE, SHA384_OUTPUT_SIZE,
20 SHA512_BLOCK_SIZE, SHA512_OUTPUT_SIZE,
21};
22
23const K256: [u32; 64] = [
25 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
26 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
27 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
28 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
29 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
30 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
31 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
32 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
33];
34
35const K512: [u64; 80] = [
37 0x428a2f98d728ae22,
38 0x7137449123ef65cd,
39 0xb5c0fbcfec4d3b2f,
40 0xe9b5dba58189dbbc,
41 0x3956c25bf348b538,
42 0x59f111f1b605d019,
43 0x923f82a4af194f9b,
44 0xab1c5ed5da6d8118,
45 0xd807aa98a3030242,
46 0x12835b0145706fbe,
47 0x243185be4ee4b28c,
48 0x550c7dc3d5ffb4e2,
49 0x72be5d74f27b896f,
50 0x80deb1fe3b1696b1,
51 0x9bdc06a725c71235,
52 0xc19bf174cf692694,
53 0xe49b69c19ef14ad2,
54 0xefbe4786384f25e3,
55 0x0fc19dc68b8cd5b5,
56 0x240ca1cc77ac9c65,
57 0x2de92c6f592b0275,
58 0x4a7484aa6ea6e483,
59 0x5cb0a9dcbd41fbd4,
60 0x76f988da831153b5,
61 0x983e5152ee66dfab,
62 0xa831c66d2db43210,
63 0xb00327c898fb213f,
64 0xbf597fc7beef0ee4,
65 0xc6e00bf33da88fc2,
66 0xd5a79147930aa725,
67 0x06ca6351e003826f,
68 0x142929670a0e6e70,
69 0x27b70a8546d22ffc,
70 0x2e1b21385c26c926,
71 0x4d2c6dfc5ac42aed,
72 0x53380d139d95b3df,
73 0x650a73548baf63de,
74 0x766a0abb3c77b2a8,
75 0x81c2c92e47edaee6,
76 0x92722c851482353b,
77 0xa2bfe8a14cf10364,
78 0xa81a664bbc423001,
79 0xc24b8b70d0f89791,
80 0xc76c51a30654be30,
81 0xd192e819d6ef5218,
82 0xd69906245565a910,
83 0xf40e35855771202a,
84 0x106aa07032bbd1b8,
85 0x19a4c116b8d2d0c8,
86 0x1e376c085141ab53,
87 0x2748774cdf8eeb99,
88 0x34b0bcb5e19b48a8,
89 0x391c0cb3c5c95a63,
90 0x4ed8aa4ae3418acb,
91 0x5b9cca4f7763e373,
92 0x682e6ff3d6b2b8a3,
93 0x748f82ee5defb2fc,
94 0x78a5636f43172f60,
95 0x84c87814a1f0ab72,
96 0x8cc702081a6439ec,
97 0x90befffa23631e28,
98 0xa4506cebde82bde9,
99 0xbef9a3f7b2c67915,
100 0xc67178f2e372532b,
101 0xca273eceea26619c,
102 0xd186b8c721c0c207,
103 0xeada7dd6cde0eb1e,
104 0xf57d4f7fee6ed178,
105 0x06f067aa72176fba,
106 0x0a637dc5a2c898a6,
107 0x113f9804bef90dae,
108 0x1b710b35131c471b,
109 0x28db77f523047d84,
110 0x32caab7b40c72493,
111 0x3c9ebe0a15c9bebc,
112 0x431d67c49c100d4c,
113 0x4cc5d4becb3e42b6,
114 0x597f299cfc657e2a,
115 0x5fcb6fab3ad6faec,
116 0x6c44198c4a475817,
117];
118
119fn split_bit_message(data: &[u8], bit_len: usize) -> Result<(&[u8], Option<(u8, u8)>)> {
124 let expected_bytes = bit_len.div_ceil(8);
125 validate::length("SHA-2 bit string", data.len(), expected_bytes)?;
126
127 let whole_bytes = bit_len / 8;
128 let trailing_bits = (bit_len % 8) as u8;
129 if trailing_bits == 0 {
130 return Ok((data, None));
131 }
132
133 let final_byte = data[whole_bytes];
134 let unused_mask = (1u8 << (8 - trailing_bits)) - 1;
135 validate::parameter(
136 final_byte & unused_mask == 0,
137 "data",
138 "unused low bits in the final SHA-2 input byte must be zero",
139 )?;
140
141 Ok((&data[..whole_bytes], Some((final_byte, trailing_bits))))
142}
143
144pub enum Sha256Algorithm {}
147
148impl HashAlgorithm for Sha256Algorithm {
149 const OUTPUT_SIZE: usize = SHA256_OUTPUT_SIZE;
150 const BLOCK_SIZE: usize = SHA256_BLOCK_SIZE;
151 const ALGORITHM_ID: &'static str = "SHA-256";
152}
153
154pub enum Sha224Algorithm {}
156
157impl HashAlgorithm for Sha224Algorithm {
158 const OUTPUT_SIZE: usize = SHA224_OUTPUT_SIZE;
159 const BLOCK_SIZE: usize = SHA256_BLOCK_SIZE;
160 const ALGORITHM_ID: &'static str = "SHA-224";
161}
162
163pub enum Sha384Algorithm {}
165
166impl HashAlgorithm for Sha384Algorithm {
167 const OUTPUT_SIZE: usize = SHA384_OUTPUT_SIZE;
168 const BLOCK_SIZE: usize = SHA512_BLOCK_SIZE;
169 const ALGORITHM_ID: &'static str = "SHA-384";
170}
171
172pub enum Sha512Algorithm {}
174
175impl HashAlgorithm for Sha512Algorithm {
176 const OUTPUT_SIZE: usize = SHA512_OUTPUT_SIZE;
177 const BLOCK_SIZE: usize = SHA512_BLOCK_SIZE;
178 const ALGORITHM_ID: &'static str = "SHA-512";
179}
180
181pub enum Sha512_224Algorithm {}
183
184impl HashAlgorithm for Sha512_224Algorithm {
185 const OUTPUT_SIZE: usize = SHA224_OUTPUT_SIZE;
186 const BLOCK_SIZE: usize = SHA512_BLOCK_SIZE;
187 const ALGORITHM_ID: &'static str = "SHA-512/224";
188}
189
190pub enum Sha512_256Algorithm {}
192
193impl HashAlgorithm for Sha512_256Algorithm {
194 const OUTPUT_SIZE: usize = SHA256_OUTPUT_SIZE;
195 const BLOCK_SIZE: usize = SHA512_BLOCK_SIZE;
196 const ALGORITHM_ID: &'static str = "SHA-512/256";
197}
198
199#[derive(Clone)]
201pub struct Sha224 {
202 state: [u32; 8],
203 buffer: [u8; SHA256_BLOCK_SIZE],
204 buffer_idx: usize,
205 total_bytes: u64,
206}
207
208impl Drop for Sha224 {
209 fn drop(&mut self) {
210 self.zeroize();
211 }
212}
213
214#[derive(Clone)]
216pub struct Sha256 {
217 state: [u32; 8],
218 buffer: [u8; SHA256_BLOCK_SIZE],
219 buffer_idx: usize,
220 total_bytes: u64,
221}
222
223impl Drop for Sha256 {
224 fn drop(&mut self) {
225 self.zeroize();
226 }
227}
228
229#[derive(Clone)]
231pub struct Sha384 {
232 state: [u64; 8],
233 buffer: [u8; SHA512_BLOCK_SIZE],
234 buffer_idx: usize,
235 total_bytes: u128, }
237
238impl Drop for Sha384 {
239 fn drop(&mut self) {
240 self.zeroize();
241 }
242}
243
244#[derive(Clone)]
246pub struct Sha512 {
247 state: [u64; 8],
248 buffer: [u8; SHA512_BLOCK_SIZE],
249 buffer_idx: usize,
250 total_bytes: u128,
251}
252
253impl Drop for Sha512 {
254 fn drop(&mut self) {
255 self.zeroize();
256 }
257}
258
259#[derive(Clone)]
261pub struct Sha512_224 {
262 state: [u64; 8],
263 buffer: [u8; SHA512_BLOCK_SIZE],
264 buffer_idx: usize,
265 total_bytes: u128,
266}
267
268impl Drop for Sha512_224 {
269 fn drop(&mut self) {
270 self.zeroize();
271 }
272}
273
274#[derive(Clone)]
276pub struct Sha512_256 {
277 state: [u64; 8],
278 buffer: [u8; SHA512_BLOCK_SIZE],
279 buffer_idx: usize,
280 total_bytes: u128,
281}
282
283macro_rules! impl_sha2_zeroize {
284 ($name:ident) => {
285 impl Zeroize for $name {
286 fn zeroize(&mut self) {
287 self.state.zeroize();
288 self.buffer.zeroize();
289 self.buffer_idx.zeroize();
290 self.total_bytes.zeroize();
291 }
292 }
293 };
294}
295
296impl_sha2_zeroize!(Sha224);
297impl_sha2_zeroize!(Sha256);
298impl_sha2_zeroize!(Sha384);
299impl_sha2_zeroize!(Sha512);
300impl_sha2_zeroize!(Sha512_224);
301impl_sha2_zeroize!(Sha512_256);
302
303impl Drop for Sha512_256 {
304 fn drop(&mut self) {
305 self.zeroize();
306 }
307}
308
309impl Sha256 {
311 fn init_state() -> [u32; 8] {
312 [
313 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab,
314 0x5be0cd19,
315 ]
316 }
317
318 fn new() -> Self {
319 Sha256 {
320 state: Self::init_state(),
321 buffer: [0u8; SHA256_BLOCK_SIZE],
322 buffer_idx: 0,
323 total_bytes: 0,
324 }
325 }
326
327 fn compress(state: &mut [u32; 8], block: &[u8; SHA256_BLOCK_SIZE]) -> Result<()> {
328 let mut w = EphemeralSecret::new([0u32; 64]);
330
331 compiler_fence(Ordering::SeqCst);
333
334 for i in 0..16 {
335 let start = i * 4;
336 validate::max_length("SHA-256 block read", start + 4, SHA256_BLOCK_SIZE)?;
337 w[i] = (u32::from(block[start]) << 24)
338 | (u32::from(block[start + 1]) << 16)
339 | (u32::from(block[start + 2]) << 8)
340 | u32::from(block[start + 3]);
341 }
342
343 for i in 16..64 {
344 let s0 = w[i - 15].rotate_right(7) ^ w[i - 15].rotate_right(18) ^ (w[i - 15] >> 3);
345 let s1 = w[i - 2].rotate_right(17) ^ w[i - 2].rotate_right(19) ^ (w[i - 2] >> 10);
346 w[i] = w[i - 16]
347 .wrapping_add(s0)
348 .wrapping_add(w[i - 7])
349 .wrapping_add(s1);
350 }
351
352 let mut working_vars = [
354 state[0], state[1], state[2], state[3], state[4], state[5], state[6], state[7],
355 ];
356 let mut guard = ZeroizeGuard::new(&mut working_vars);
357
358 let mut a = guard[0];
360 let mut b = guard[1];
361 let mut c = guard[2];
362 let mut d = guard[3];
363 let mut e = guard[4];
364 let mut f = guard[5];
365 let mut g = guard[6];
366 let mut h = guard[7];
367
368 for i in 0..64 {
369 let s1 = e.rotate_right(6) ^ e.rotate_right(11) ^ e.rotate_right(25);
370 let ch = (e & f) ^ ((!e) & g);
371 let temp1 = h
372 .wrapping_add(s1)
373 .wrapping_add(ch)
374 .wrapping_add(K256[i])
375 .wrapping_add(w[i]);
376 let s0 = a.rotate_right(2) ^ a.rotate_right(13) ^ a.rotate_right(22);
377 let maj = (a & b) ^ (a & c) ^ (b & c);
378 let temp2 = s0.wrapping_add(maj);
379
380 h = g;
381 g = f;
382 f = e;
383 e = d.wrapping_add(temp1);
384 d = c;
385 c = b;
386 b = a;
387 a = temp1.wrapping_add(temp2);
388 }
389
390 guard[0] = a;
392 guard[1] = b;
393 guard[2] = c;
394 guard[3] = d;
395 guard[4] = e;
396 guard[5] = f;
397 guard[6] = g;
398 guard[7] = h;
399
400 state[0] = state[0].wrapping_add(guard[0]);
402 state[1] = state[1].wrapping_add(guard[1]);
403 state[2] = state[2].wrapping_add(guard[2]);
404 state[3] = state[3].wrapping_add(guard[3]);
405 state[4] = state[4].wrapping_add(guard[4]);
406 state[5] = state[5].wrapping_add(guard[5]);
407 state[6] = state[6].wrapping_add(guard[6]);
408 state[7] = state[7].wrapping_add(guard[7]);
409
410 a.zeroize();
411 b.zeroize();
412 c.zeroize();
413 d.zeroize();
414 e.zeroize();
415 f.zeroize();
416 g.zeroize();
417 h.zeroize();
418
419 compiler_fence(Ordering::SeqCst);
421
422 Ok(())
423 }
424
425 fn update_internal(&mut self, mut input: &[u8]) -> Result<()> {
426 while !input.is_empty() {
427 let fill = core::cmp::min(input.len(), SHA256_BLOCK_SIZE - self.buffer_idx);
428 self.buffer[self.buffer_idx..self.buffer_idx + fill].copy_from_slice(&input[..fill]);
429 self.buffer_idx += fill;
430 input = &input[fill..];
431 if self.buffer_idx == SHA256_BLOCK_SIZE {
432 let mut block = Zeroizing::new([0u8; SHA256_BLOCK_SIZE]);
433 block.copy_from_slice(&self.buffer);
434 Self::compress(&mut self.state, &block)?;
435 self.total_bytes += SHA256_BLOCK_SIZE as u64;
436 self.buffer.zeroize();
437 self.buffer_idx = 0;
438 }
439 }
440 Ok(())
441 }
442
443 fn finalize_internal(&mut self) -> Result<Zeroizing<[u8; SHA256_OUTPUT_SIZE]>> {
444 self.finalize_internal_bits(None)
445 }
446
447 fn finalize_internal_bits(
448 &mut self,
449 trailing: Option<(u8, u8)>,
450 ) -> Result<Zeroizing<[u8; SHA256_OUTPUT_SIZE]>> {
451 let trailing_bits = trailing.map_or(0, |(_, bits)| bits);
452 let bit_len = self
453 .total_bytes
454 .checked_add(self.buffer_idx as u64)
455 .and_then(|bytes| bytes.checked_mul(8))
456 .and_then(|bits| bits.checked_add(u64::from(trailing_bits)))
457 .ok_or(Error::Processing {
458 operation: "SHA-256 finalization",
459 details: "message bit length overflow",
460 })?;
461
462 let occupied = if let Some((final_byte, bits)) = trailing {
465 debug_assert!((1..=7).contains(&bits));
466 self.buffer[self.buffer_idx] = final_byte | (0x80 >> bits);
467 self.buffer_idx + 1
468 } else {
469 self.buffer[self.buffer_idx] = 0x80;
470 self.buffer_idx + 1
471 };
472 self.buffer[occupied..].zeroize();
473
474 if occupied > 56 {
475 let mut block = Zeroizing::new([0u8; SHA256_BLOCK_SIZE]);
476 block.copy_from_slice(&self.buffer);
477 Self::compress(&mut self.state, &block)?;
478 self.buffer.zeroize();
479 }
480
481 for (index, byte) in self.buffer[56..].iter_mut().enumerate() {
482 *byte = (bit_len >> (56 - 8 * index)) as u8;
483 }
484 let mut block = Zeroizing::new([0u8; SHA256_BLOCK_SIZE]);
485 block.copy_from_slice(&self.buffer);
486 Self::compress(&mut self.state, &block)?;
487
488 let mut out = Zeroizing::new([0u8; SHA256_OUTPUT_SIZE]);
489 for (word_index, &word) in self.state.iter().enumerate() {
490 for byte in 0..4 {
491 out[word_index * 4 + byte] = (word >> (24 - byte * 8)) as u8;
492 }
493 }
494 self.zeroize();
495 Ok(out)
496 }
497}
498
499impl Sha224 {
501 fn init_state() -> [u32; 8] {
502 [
503 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7,
504 0xbefa4fa4,
505 ]
506 }
507
508 fn new() -> Self {
509 Sha224 {
510 state: Self::init_state(),
511 buffer: [0u8; SHA256_BLOCK_SIZE],
512 buffer_idx: 0,
513 total_bytes: 0,
514 }
515 }
516
517 pub fn digest_bits(data: &[u8], bit_len: usize) -> Result<Digest<SHA224_OUTPUT_SIZE>> {
522 let full = sha256_digest_bits_with_state(data, bit_len, Self::init_state())?;
523 let mut digest = Digest::<SHA224_OUTPUT_SIZE>::zeroed();
524 digest.as_mut().copy_from_slice(&full[..SHA224_OUTPUT_SIZE]);
525 Ok(digest)
526 }
527}
528
529impl Sha256 {
530 pub fn digest_bits(data: &[u8], bit_len: usize) -> Result<Digest<SHA256_OUTPUT_SIZE>> {
532 let full = sha256_digest_bits_with_state(data, bit_len, Self::init_state())?;
533 let mut digest = Digest::<SHA256_OUTPUT_SIZE>::zeroed();
534 digest.as_mut().copy_from_slice(&full[..]);
535 Ok(digest)
536 }
537}
538
539impl Sha512 {
541 fn init_state() -> [u64; 8] {
542 [
543 0x6a09e667f3bcc908,
544 0xbb67ae8584caa73b,
545 0x3c6ef372fe94f82b,
546 0xa54ff53a5f1d36f1,
547 0x510e527fade682d1,
548 0x9b05688c2b3e6c1f,
549 0x1f83d9abfb41bd6b,
550 0x5be0cd19137e2179,
551 ]
552 }
553
554 fn new() -> Self {
555 Sha512 {
556 state: Self::init_state(),
557 buffer: [0u8; SHA512_BLOCK_SIZE],
558 buffer_idx: 0,
559 total_bytes: 0,
560 }
561 }
562
563 fn compress(state: &mut [u64; 8], block: &[u8; SHA512_BLOCK_SIZE]) -> Result<()> {
564 let mut w = EphemeralSecret::new([0u64; 80]);
566
567 compiler_fence(Ordering::SeqCst);
569
570 for i in 0..16 {
571 let start = i * 8;
572 validate::max_length("SHA-512 block read", start + 8, SHA512_BLOCK_SIZE)?;
573 let mut word = 0u64;
574 for byte in 0..8 {
575 word |= u64::from(block[start + byte]) << (56 - byte * 8);
576 }
577 w[i] = word;
578 word.zeroize();
579 }
580
581 for i in 16..80 {
582 let s0 = w[i - 15].rotate_right(1) ^ w[i - 15].rotate_right(8) ^ (w[i - 15] >> 7);
583 let s1 = w[i - 2].rotate_right(19) ^ w[i - 2].rotate_right(61) ^ (w[i - 2] >> 6);
584 w[i] = w[i - 16]
585 .wrapping_add(s0)
586 .wrapping_add(w[i - 7])
587 .wrapping_add(s1);
588 }
589
590 let mut working_vars = [
592 state[0], state[1], state[2], state[3], state[4], state[5], state[6], state[7],
593 ];
594 let mut guard = ZeroizeGuard::new(&mut working_vars);
595
596 let mut a = guard[0];
598 let mut b = guard[1];
599 let mut c = guard[2];
600 let mut d = guard[3];
601 let mut e = guard[4];
602 let mut f = guard[5];
603 let mut g = guard[6];
604 let mut h = guard[7];
605
606 for i in 0..80 {
607 let s1 = e.rotate_right(14) ^ e.rotate_right(18) ^ e.rotate_right(41);
608 let ch = (e & f) ^ ((!e) & g);
609 let temp1 = h
610 .wrapping_add(s1)
611 .wrapping_add(ch)
612 .wrapping_add(K512[i])
613 .wrapping_add(w[i]);
614 let s0 = a.rotate_right(28) ^ a.rotate_right(34) ^ a.rotate_right(39);
615 let maj = (a & b) ^ (a & c) ^ (b & c);
616 let temp2 = s0.wrapping_add(maj);
617
618 h = g;
619 g = f;
620 f = e;
621 e = d.wrapping_add(temp1);
622 d = c;
623 c = b;
624 b = a;
625 a = temp1.wrapping_add(temp2);
626 }
627
628 guard[0] = a;
630 guard[1] = b;
631 guard[2] = c;
632 guard[3] = d;
633 guard[4] = e;
634 guard[5] = f;
635 guard[6] = g;
636 guard[7] = h;
637
638 state[0] = state[0].wrapping_add(guard[0]);
640 state[1] = state[1].wrapping_add(guard[1]);
641 state[2] = state[2].wrapping_add(guard[2]);
642 state[3] = state[3].wrapping_add(guard[3]);
643 state[4] = state[4].wrapping_add(guard[4]);
644 state[5] = state[5].wrapping_add(guard[5]);
645 state[6] = state[6].wrapping_add(guard[6]);
646 state[7] = state[7].wrapping_add(guard[7]);
647
648 a.zeroize();
649 b.zeroize();
650 c.zeroize();
651 d.zeroize();
652 e.zeroize();
653 f.zeroize();
654 g.zeroize();
655 h.zeroize();
656
657 compiler_fence(Ordering::SeqCst);
659
660 Ok(())
661 }
662
663 fn update_internal_u128(&mut self, mut input: &[u8]) -> Result<()> {
664 while !input.is_empty() {
665 let fill = core::cmp::min(input.len(), SHA512_BLOCK_SIZE - self.buffer_idx);
666 self.buffer[self.buffer_idx..self.buffer_idx + fill].copy_from_slice(&input[..fill]);
667 self.buffer_idx += fill;
668 input = &input[fill..];
669 if self.buffer_idx == SHA512_BLOCK_SIZE {
670 let mut block = Zeroizing::new([0u8; SHA512_BLOCK_SIZE]);
671 block.copy_from_slice(&self.buffer);
672 Self::compress(&mut self.state, &block)?;
673 self.total_bytes = self.total_bytes.wrapping_add(SHA512_BLOCK_SIZE as u128);
674 self.buffer.zeroize();
675 self.buffer_idx = 0;
676 }
677 }
678 Ok(())
679 }
680
681 fn finalize_internal_u128(&mut self) -> Result<Zeroizing<[u8; SHA512_OUTPUT_SIZE]>> {
682 self.finalize_internal_bits_u128(None)
683 }
684
685 fn finalize_internal_bits_u128(
686 &mut self,
687 trailing: Option<(u8, u8)>,
688 ) -> Result<Zeroizing<[u8; SHA512_OUTPUT_SIZE]>> {
689 let trailing_bits = trailing.map_or(0, |(_, bits)| bits);
690 let bit_len = self
691 .total_bytes
692 .checked_add(self.buffer_idx as u128)
693 .and_then(|bytes| bytes.checked_mul(8))
694 .and_then(|bits| bits.checked_add(u128::from(trailing_bits)))
695 .ok_or(Error::Processing {
696 operation: "SHA-512 finalization",
697 details: "message bit length overflow",
698 })?;
699
700 let occupied = if let Some((final_byte, bits)) = trailing {
701 debug_assert!((1..=7).contains(&bits));
702 self.buffer[self.buffer_idx] = final_byte | (0x80 >> bits);
703 self.buffer_idx + 1
704 } else {
705 self.buffer[self.buffer_idx] = 0x80;
706 self.buffer_idx + 1
707 };
708 self.buffer[occupied..].zeroize();
709
710 if occupied > SHA512_BLOCK_SIZE - 16 {
711 let mut block = Zeroizing::new([0u8; SHA512_BLOCK_SIZE]);
712 block.copy_from_slice(&self.buffer);
713 Self::compress(&mut self.state, &block)?;
714 self.buffer.zeroize();
715 }
716
717 for (index, byte) in self.buffer[SHA512_BLOCK_SIZE - 16..].iter_mut().enumerate() {
718 *byte = (bit_len >> (120 - index * 8)) as u8;
719 }
720 let mut block = Zeroizing::new([0u8; SHA512_BLOCK_SIZE]);
721 block.copy_from_slice(&self.buffer);
722 Self::compress(&mut self.state, &block)?;
723
724 let mut out = Zeroizing::new([0u8; SHA512_OUTPUT_SIZE]);
725 for (word_index, &word) in self.state.iter().enumerate() {
726 for byte in 0..8 {
727 out[word_index * 8 + byte] = (word >> (56 - byte * 8)) as u8;
728 }
729 }
730 self.zeroize();
731 Ok(out)
732 }
733}
734
735impl Sha512_224 {
737 fn init_state() -> [u64; 8] {
738 [
739 0x8c3d37c819544da2,
740 0x73e1996689dcd4d6,
741 0x1dfab7ae32ff9c82,
742 0x679dd514582f9fcf,
743 0x0f6d2b697bd44da8,
744 0x77e36f7304c48942,
745 0x3f9d85a86a1d36c8,
746 0x1112e6ad91d692a1,
747 ]
748 }
749
750 fn new() -> Self {
751 Sha512_224 {
752 state: Self::init_state(),
753 buffer: [0u8; SHA512_BLOCK_SIZE],
754 buffer_idx: 0,
755 total_bytes: 0,
756 }
757 }
758}
759
760impl Sha512_256 {
762 fn init_state() -> [u64; 8] {
763 [
764 0x22312194fc2bf72c,
765 0x9f555fa3c84c64c2,
766 0x2393b86b6f53b151,
767 0x963877195940eabd,
768 0x96283ee2a88effe3,
769 0xbe5e1e2553863992,
770 0x2b0199fc2c85b8aa,
771 0x0eb72ddc81c52ca2,
772 ]
773 }
774
775 fn new() -> Self {
776 Sha512_256 {
777 state: Self::init_state(),
778 buffer: [0u8; SHA512_BLOCK_SIZE],
779 buffer_idx: 0,
780 total_bytes: 0,
781 }
782 }
783}
784
785impl Sha384 {
786 fn init_state() -> [u64; 8] {
787 [
788 0xcbbb9d5dc1059ed8,
789 0x629a292a367cd507,
790 0x9159015a3070dd17,
791 0x152fecd8f70e5939,
792 0x67332667ffc00b31,
793 0x8eb44a8768581511,
794 0xdb0c2e0d64f98fa7,
795 0x47b5481dbefa4fa4,
796 ]
797 }
798
799 pub fn digest_bits(data: &[u8], bit_len: usize) -> Result<Digest<SHA384_OUTPUT_SIZE>> {
801 let full = sha512_digest_bits_with_state(data, bit_len, Self::init_state())?;
802 let mut digest = Digest::<SHA384_OUTPUT_SIZE>::zeroed();
803 digest.as_mut().copy_from_slice(&full[..SHA384_OUTPUT_SIZE]);
804 Ok(digest)
805 }
806}
807
808impl Sha512 {
809 pub fn digest_bits(data: &[u8], bit_len: usize) -> Result<Digest<SHA512_OUTPUT_SIZE>> {
811 let full = sha512_digest_bits_with_state(data, bit_len, Self::init_state())?;
812 let mut digest = Digest::<SHA512_OUTPUT_SIZE>::zeroed();
813 digest.as_mut().copy_from_slice(&full[..]);
814 Ok(digest)
815 }
816}
817
818impl Sha512_224 {
819 pub fn digest_bits(data: &[u8], bit_len: usize) -> Result<Digest<SHA224_OUTPUT_SIZE>> {
821 let full = sha512_digest_bits_with_state(data, bit_len, Self::init_state())?;
822 let mut digest = Digest::<SHA224_OUTPUT_SIZE>::zeroed();
823 digest.as_mut().copy_from_slice(&full[..SHA224_OUTPUT_SIZE]);
824 Ok(digest)
825 }
826}
827
828impl Sha512_256 {
829 pub fn digest_bits(data: &[u8], bit_len: usize) -> Result<Digest<SHA256_OUTPUT_SIZE>> {
831 let full = sha512_digest_bits_with_state(data, bit_len, Self::init_state())?;
832 let mut digest = Digest::<SHA256_OUTPUT_SIZE>::zeroed();
833 digest.as_mut().copy_from_slice(&full[..SHA256_OUTPUT_SIZE]);
834 Ok(digest)
835 }
836}
837
838fn sha256_digest_bits_with_state(
839 data: &[u8],
840 bit_len: usize,
841 state: [u32; 8],
842) -> Result<Zeroizing<[u8; SHA256_OUTPUT_SIZE]>> {
843 let (whole_bytes, trailing) = split_bit_message(data, bit_len)?;
844 let mut hash = Sha256::new();
845 hash.state = state;
846 hash.update_internal(whole_bytes)?;
847 hash.finalize_internal_bits(trailing)
848}
849
850fn sha512_digest_bits_with_state(
851 data: &[u8],
852 bit_len: usize,
853 state: [u64; 8],
854) -> Result<Zeroizing<[u8; SHA512_OUTPUT_SIZE]>> {
855 let (whole_bytes, trailing) = split_bit_message(data, bit_len)?;
856 let mut hash = Sha512::new();
857 hash.state = state;
858 hash.update_internal_u128(whole_bytes)?;
859 hash.finalize_internal_bits_u128(trailing)
860}
861
862impl SecureZeroingType for Sha256 {
864 fn zeroed() -> Self {
865 Self::new()
866 }
867}
868
869impl HashFunction for Sha256 {
870 type Algorithm = Sha256Algorithm;
871 type Output = Digest<SHA256_OUTPUT_SIZE>;
872
873 fn new() -> Self {
874 Sha256::new()
875 }
876
877 fn update(&mut self, data: &[u8]) -> Result<&mut Self> {
878 self.update_internal(data)?;
879 Ok(self)
880 }
881
882 fn finalize(&mut self) -> Result<Self::Output> {
883 let hash = self.finalize_internal()?;
884 let mut digest = Digest::<SHA256_OUTPUT_SIZE>::zeroed();
885 digest.as_mut().copy_from_slice(&hash[..]);
886 Ok(digest)
887 }
888
889 fn output_size() -> usize {
890 SHA256_OUTPUT_SIZE
891 }
892
893 fn block_size() -> usize {
894 SHA256_BLOCK_SIZE
895 }
896
897 fn name() -> String {
898 "SHA-256".to_string()
899 }
900}
901
902impl SecureZeroingType for Sha224 {
903 fn zeroed() -> Self {
904 Self::new()
905 }
906}
907
908impl HashFunction for Sha224 {
909 type Algorithm = Sha224Algorithm;
910 type Output = Digest<SHA224_OUTPUT_SIZE>;
911
912 fn new() -> Self {
913 Sha224::new()
914 }
915
916 fn update(&mut self, data: &[u8]) -> Result<&mut Self> {
917 let mut tmp = Sha256::new();
918 tmp.state = self.state;
919 tmp.buffer = self.buffer;
920 tmp.buffer_idx = self.buffer_idx;
921 tmp.total_bytes = self.total_bytes;
922 tmp.update_internal(data)?;
923 self.state = tmp.state;
924 self.buffer = tmp.buffer;
925 self.buffer_idx = tmp.buffer_idx;
926 self.total_bytes = tmp.total_bytes;
927 Ok(self)
928 }
929
930 fn finalize(&mut self) -> Result<Self::Output> {
931 let mut tmp = Sha256::new();
932 tmp.state = self.state;
933 tmp.buffer = self.buffer;
934 tmp.buffer_idx = self.buffer_idx;
935 tmp.total_bytes = self.total_bytes;
936 let full = tmp.finalize_internal()?;
937 let mut digest = Digest::<SHA224_OUTPUT_SIZE>::zeroed();
938 digest.as_mut().copy_from_slice(&full[..SHA224_OUTPUT_SIZE]);
939 Ok(digest)
940 }
941
942 fn output_size() -> usize {
943 SHA224_OUTPUT_SIZE
944 }
945
946 fn block_size() -> usize {
947 SHA256_BLOCK_SIZE
948 }
949
950 fn name() -> String {
951 "SHA-224".to_string()
952 }
953}
954
955impl SecureZeroingType for Sha384 {
956 fn zeroed() -> Self {
957 Sha384 {
958 state: Self::init_state(),
959 buffer: [0u8; SHA512_BLOCK_SIZE],
960 buffer_idx: 0,
961 total_bytes: 0,
962 }
963 }
964}
965
966impl HashFunction for Sha384 {
967 type Algorithm = Sha384Algorithm;
968 type Output = Digest<SHA384_OUTPUT_SIZE>;
969
970 fn new() -> Self {
971 SecureZeroingType::zeroed()
972 }
973
974 fn update(&mut self, data: &[u8]) -> Result<&mut Self> {
975 let mut tmp = Sha512::new();
976 tmp.state = self.state;
977 tmp.buffer = self.buffer;
978 tmp.buffer_idx = self.buffer_idx;
979 tmp.total_bytes = self.total_bytes;
980 tmp.update_internal_u128(data)?;
981 self.state = tmp.state;
982 self.buffer = tmp.buffer;
983 self.buffer_idx = tmp.buffer_idx;
984 self.total_bytes = tmp.total_bytes;
985 Ok(self)
986 }
987
988 fn finalize(&mut self) -> Result<Self::Output> {
989 let mut tmp = Sha512::new();
990 tmp.state = self.state;
991 tmp.buffer = self.buffer;
992 tmp.buffer_idx = self.buffer_idx;
993 tmp.total_bytes = self.total_bytes;
994 let full = tmp.finalize_internal_u128()?;
995 let mut digest = Digest::<SHA384_OUTPUT_SIZE>::zeroed();
996 digest.as_mut().copy_from_slice(&full[..SHA384_OUTPUT_SIZE]);
997 Ok(digest)
998 }
999
1000 fn output_size() -> usize {
1001 SHA384_OUTPUT_SIZE
1002 }
1003
1004 fn block_size() -> usize {
1005 SHA512_BLOCK_SIZE
1006 }
1007
1008 fn name() -> String {
1009 "SHA-384".to_string()
1010 }
1011}
1012
1013impl SecureZeroingType for Sha512 {
1014 fn zeroed() -> Self {
1015 Self::new()
1016 }
1017}
1018
1019impl HashFunction for Sha512 {
1020 type Algorithm = Sha512Algorithm;
1021 type Output = Digest<SHA512_OUTPUT_SIZE>;
1022
1023 fn new() -> Self {
1024 Sha512::new()
1025 }
1026
1027 fn update(&mut self, data: &[u8]) -> Result<&mut Self> {
1028 self.update_internal_u128(data)?;
1029 Ok(self)
1030 }
1031
1032 fn finalize(&mut self) -> Result<Self::Output> {
1033 let hash = self.finalize_internal_u128()?;
1034 let mut digest = Digest::<SHA512_OUTPUT_SIZE>::zeroed();
1035 digest.as_mut().copy_from_slice(&hash[..]);
1036 Ok(digest)
1037 }
1038
1039 fn output_size() -> usize {
1040 SHA512_OUTPUT_SIZE
1041 }
1042
1043 fn block_size() -> usize {
1044 SHA512_BLOCK_SIZE
1045 }
1046
1047 fn name() -> String {
1048 "SHA-512".to_string()
1049 }
1050}
1051
1052impl SecureZeroingType for Sha512_224 {
1053 fn zeroed() -> Self {
1054 Self::new()
1055 }
1056}
1057
1058impl HashFunction for Sha512_224 {
1059 type Algorithm = Sha512_224Algorithm;
1060 type Output = Digest<SHA224_OUTPUT_SIZE>;
1061
1062 fn new() -> Self {
1063 Sha512_224::new()
1064 }
1065
1066 fn update(&mut self, data: &[u8]) -> Result<&mut Self> {
1067 let mut tmp = Sha512::new();
1068 tmp.state = self.state;
1069 tmp.buffer = self.buffer;
1070 tmp.buffer_idx = self.buffer_idx;
1071 tmp.total_bytes = self.total_bytes;
1072 tmp.update_internal_u128(data)?;
1073 self.state = tmp.state;
1074 self.buffer = tmp.buffer;
1075 self.buffer_idx = tmp.buffer_idx;
1076 self.total_bytes = tmp.total_bytes;
1077 Ok(self)
1078 }
1079
1080 fn finalize(&mut self) -> Result<Self::Output> {
1081 let mut tmp = Sha512::new();
1082 tmp.state = self.state;
1083 tmp.buffer = self.buffer;
1084 tmp.buffer_idx = self.buffer_idx;
1085 tmp.total_bytes = self.total_bytes;
1086 let full = tmp.finalize_internal_u128()?;
1087 let mut digest = Digest::<SHA224_OUTPUT_SIZE>::zeroed();
1088 digest.as_mut().copy_from_slice(&full[..SHA224_OUTPUT_SIZE]);
1089 Ok(digest)
1090 }
1091
1092 fn output_size() -> usize {
1093 SHA224_OUTPUT_SIZE
1094 }
1095
1096 fn block_size() -> usize {
1097 SHA512_BLOCK_SIZE
1098 }
1099
1100 fn name() -> String {
1101 "SHA-512/224".to_string()
1102 }
1103}
1104
1105impl SecureZeroingType for Sha512_256 {
1106 fn zeroed() -> Self {
1107 Self::new()
1108 }
1109}
1110
1111impl HashFunction for Sha512_256 {
1112 type Algorithm = Sha512_256Algorithm;
1113 type Output = Digest<SHA256_OUTPUT_SIZE>;
1114
1115 fn new() -> Self {
1116 Sha512_256::new()
1117 }
1118
1119 fn update(&mut self, data: &[u8]) -> Result<&mut Self> {
1120 let mut tmp = Sha512::new();
1121 tmp.state = self.state;
1122 tmp.buffer = self.buffer;
1123 tmp.buffer_idx = self.buffer_idx;
1124 tmp.total_bytes = self.total_bytes;
1125 tmp.update_internal_u128(data)?;
1126 self.state = tmp.state;
1127 self.buffer = tmp.buffer;
1128 self.buffer_idx = tmp.buffer_idx;
1129 self.total_bytes = tmp.total_bytes;
1130 Ok(self)
1131 }
1132
1133 fn finalize(&mut self) -> Result<Self::Output> {
1134 let mut tmp = Sha512::new();
1135 tmp.state = self.state;
1136 tmp.buffer = self.buffer;
1137 tmp.buffer_idx = self.buffer_idx;
1138 tmp.total_bytes = self.total_bytes;
1139 let full = tmp.finalize_internal_u128()?;
1140 let mut digest = Digest::<SHA256_OUTPUT_SIZE>::zeroed();
1141 digest.as_mut().copy_from_slice(&full[..SHA256_OUTPUT_SIZE]);
1142 Ok(digest)
1143 }
1144
1145 fn output_size() -> usize {
1146 SHA256_OUTPUT_SIZE
1147 }
1148
1149 fn block_size() -> usize {
1150 SHA512_BLOCK_SIZE
1151 }
1152
1153 fn name() -> String {
1154 "SHA-512/256".to_string()
1155 }
1156}
1157
1158#[cfg(test)]
1159mod tests;