1use crate::SHA2Params;
2use core::slice;
3use bouncycastle_core_interface::errors::HashError;
4use bouncycastle_core_interface::traits::{Hash, SecurityStrength};
5use bouncycastle_utils::min;
6
7const SHA512_K: [u64; 80] = [
8 0x428A2F98D728AE22, 0x7137449123EF65CD, 0xB5C0FBCFEC4D3B2F, 0xE9B5DBA58189DBBC,
9 0x3956C25BF348B538, 0x59F111F1B605D019, 0x923F82A4AF194F9B, 0xAB1C5ED5DA6D8118,
10 0xD807AA98A3030242, 0x12835B0145706FBE, 0x243185BE4EE4B28C, 0x550C7DC3D5FFB4E2,
11 0x72BE5D74F27B896F, 0x80DEB1FE3B1696B1, 0x9BDC06A725C71235, 0xC19BF174CF692694,
12 0xE49B69C19EF14AD2, 0xEFBE4786384F25E3, 0x0FC19DC68B8CD5B5, 0x240CA1CC77AC9C65,
13 0x2DE92C6F592B0275, 0x4A7484AA6EA6E483, 0x5CB0A9DCBD41FBD4, 0x76F988DA831153B5,
14 0x983E5152EE66DFAB, 0xA831C66D2DB43210, 0xB00327C898FB213F, 0xBF597FC7BEEF0EE4,
15 0xC6E00BF33DA88FC2, 0xD5A79147930AA725, 0x06CA6351E003826F, 0x142929670A0E6E70,
16 0x27B70A8546D22FFC, 0x2E1B21385C26C926, 0x4D2C6DFC5AC42AED, 0x53380D139D95B3DF,
17 0x650A73548BAF63DE, 0x766A0ABB3C77B2A8, 0x81C2C92E47EDAEE6, 0x92722C851482353B,
18 0xA2BFE8A14CF10364, 0xA81A664BBC423001, 0xC24B8B70D0F89791, 0xC76C51A30654BE30,
19 0xD192E819D6EF5218, 0xD69906245565A910, 0xF40E35855771202A, 0x106AA07032BBD1B8,
20 0x19A4C116B8D2D0C8, 0x1E376C085141AB53, 0x2748774CDF8EEB99, 0x34B0BCB5E19B48A8,
21 0x391C0CB3C5C95A63, 0x4ED8AA4AE3418ACB, 0x5B9CCA4F7763E373, 0x682E6FF3D6B2B8A3,
22 0x748F82EE5DEFB2FC, 0x78A5636F43172F60, 0x84C87814A1F0AB72, 0x8CC702081A6439EC,
23 0x90BEFFFA23631E28, 0xA4506CEBDE82BDE9, 0xBEF9A3F7B2C67915, 0xC67178F2E372532B,
24 0xCA273ECEEA26619C, 0xD186B8C721C0C207, 0xEADA7DD6CDE0EB1E, 0xF57D4F7FEE6ED178,
25 0x06F067AA72176FBA, 0x0A637DC5A2C898A6, 0x113F9804BEF90DAE, 0x1B710B35131C471B,
26 0x28DB77F523047D84, 0x32CAAB7B40C72493, 0x3C9EBE0A15C9BEBC, 0x431D67C49C100D4C,
27 0x4CC5D4BECB3E42B6, 0x597F299CFC657E2A, 0x5FCB6FAB3AD6FAEC, 0x6C44198C4A475817,
28];
29
30#[inline]
31fn ch(x: u64, y: u64, z: u64) -> u64 {
32 (x & y) ^ (!x & z)
33}
34
35#[inline]
36fn maj(x: u64, y: u64, z: u64) -> u64 {
37 (x & y) | (z & (x ^ y))
38}
39
40#[inline]
41fn sum0(x: u64) -> u64 {
42 x.rotate_right(28) ^ x.rotate_right(34) ^ x.rotate_right(39)
43}
44
45#[inline]
46fn sum1(x: u64) -> u64 {
47 x.rotate_right(14) ^ x.rotate_right(18) ^ x.rotate_right(41)
48}
49
50#[inline]
51fn theta0(x: u64) -> u64 {
52 x.rotate_right(1) ^ x.rotate_right(8) ^ (x >> 7)
53}
54
55#[inline]
56fn theta1(x: u64) -> u64 {
57 x.rotate_right(19) ^ x.rotate_right(61) ^ (x >> 6)
58}
59
60#[derive(Clone)]
63pub(crate) struct Sha512State<PARAMS: SHA2Params> {
64 _params: std::marker::PhantomData<PARAMS>,
65 h: [u64; 8],
66}
67
68impl<PARAMS: SHA2Params> Drop for Sha512State<PARAMS> {
69 fn drop(&mut self) {
70 self.h.fill(0);
71 }
72}
73
74impl<PARAMS: SHA2Params> Sha512State<PARAMS> {
75 pub(crate) fn new() -> Self {
76 match PARAMS::OUTPUT_LEN * 8 {
77 384 => Self {
78 _params: std::marker::PhantomData,
79 h: [
80 0xCBBB9D5DC1059ED8, 0x629A292A367CD507, 0x9159015A3070DD17, 0x152FECD8F70E5939,
81 0x67332667FFC00B31, 0x8EB44A8768581511, 0xDB0C2E0D64F98FA7, 0x47B5481DBEFA4FA4,
82 ],
83 },
84 512 => Self {
85 _params: std::marker::PhantomData,
86 h: [
87 0x6A09E667F3BCC908, 0xBB67AE8584CAA73B, 0x3C6EF372FE94F82B, 0xA54FF53A5F1D36F1,
88 0x510E527FADE682D1, 0x9B05688C2B3E6C1F, 0x1F83D9ABFB41BD6B, 0x5BE0CD19137E2179,
89 ],
90 },
91 _ => panic!("Invalid SHA-2 bit size"),
92 }
93 }
94
95 fn compress(&mut self, blocks: &[[u8; 128]]) {
96 let mut x = [0u64; 80];
97
98 let s = &mut self.h;
99 let &mut [mut a, mut b, mut c, mut d, mut e, mut f, mut g, mut h] = s;
100
101 for block in blocks {
102 let (chunks, _remainder) = block.as_chunks::<8>();
103 for (i, w) in x[..16].iter_mut().zip(chunks) {
104 *i = u64::from_be_bytes(*w);
105 }
106
107 for i in 16..80 {
108 x[i] = theta1(x[i - 2])
109 .wrapping_add(x[i - 7])
110 .wrapping_add(theta0(x[i - 15]))
111 .wrapping_add(x[i - 16]);
112 }
113
114 macro_rules! sha512_round {
115 ($a:ident,$b:ident,$c:ident,$d:ident,$e:ident,$f:ident,$g:ident,$h:ident,$t:ident,$K:ident,$x:ident) => {
116 $h = $h
117 .wrapping_add(sum1($e))
118 .wrapping_add(ch($e, $f, $g))
119 .wrapping_add($K[$t])
120 .wrapping_add($x[$t]);
121 $d = $d.wrapping_add($h);
122 $h = $h.wrapping_add(sum0($a)).wrapping_add(maj($a, $b, $c));
123 $t += 1;
124 };
125 }
126
127 let mut t: usize = 0;
128 for _ in 0..10 {
129 sha512_round!(a, b, c, d, e, f, g, h, t, SHA512_K, x);
130 sha512_round!(h, a, b, c, d, e, f, g, t, SHA512_K, x);
131 sha512_round!(g, h, a, b, c, d, e, f, t, SHA512_K, x);
132 sha512_round!(f, g, h, a, b, c, d, e, t, SHA512_K, x);
133 sha512_round!(e, f, g, h, a, b, c, d, t, SHA512_K, x);
134 sha512_round!(d, e, f, g, h, a, b, c, t, SHA512_K, x);
135 sha512_round!(c, d, e, f, g, h, a, b, t, SHA512_K, x);
136 sha512_round!(b, c, d, e, f, g, h, a, t, SHA512_K, x);
137 }
138
139 a = a.wrapping_add(s[0]);
140 b = b.wrapping_add(s[1]);
141 c = c.wrapping_add(s[2]);
142 d = d.wrapping_add(s[3]);
143 e = e.wrapping_add(s[4]);
144 f = f.wrapping_add(s[5]);
145 g = g.wrapping_add(s[6]);
146 h = h.wrapping_add(s[7]);
147
148 s[0] = a;
149 s[1] = b;
150 s[2] = c;
151 s[3] = d;
152 s[4] = e;
153 s[5] = f;
154 s[6] = g;
155 s[7] = h;
156 }
157 }
158}
159
160#[derive(Clone)]
163pub struct Sha512Internal<PARAMS: SHA2Params> {
164 _params: std::marker::PhantomData<PARAMS>,
165 state: Sha512State<PARAMS>,
166 byte_count: u64, x_buf: [u8; 128],
168 x_buf_off: usize,
169}
170
171impl<PARAMS: SHA2Params> Drop for Sha512Internal<PARAMS> {
172 fn drop(&mut self) {
173 self.x_buf.fill(0);
174 }
175}
176
177impl<PARAMS: SHA2Params> Sha512Internal<PARAMS> {
178 pub fn new() -> Self {
179 Self {
180 _params: std::marker::PhantomData,
181 state: Sha512State::<PARAMS>::new(),
182 byte_count: 0,
183 x_buf: [0; 128],
184 x_buf_off: 0_usize,
185 }
186 }
187}
188
189impl<PARAMS: SHA2Params> Default for Sha512Internal<PARAMS> {
190 fn default() -> Self {
191 Self::new()
192 }
193}
194
195impl<PARAMS: SHA2Params> Hash for Sha512Internal<PARAMS> {
196 fn block_bitlen(&self) -> usize {
198 1024
199 }
200
201 fn output_len(&self) -> usize {
202 PARAMS::OUTPUT_LEN
203 }
204
205 fn hash(self, data: &[u8]) -> Vec<u8> {
206 let mut output = vec![0u8; self.output_len()];
207 self.hash_out(data, &mut output);
208 output
209 }
210
211 fn hash_out(mut self, data: &[u8], output: &mut [u8]) -> usize {
212 self.do_update(data);
213 self.do_final_out(output)
214 }
215
216 fn do_update(&mut self, block: &[u8]) {
217 let len = block.len();
218
219 self.byte_count += len as u64;
222
223 let available = 128 - self.x_buf_off;
224 if len < available {
225 self.x_buf[self.x_buf_off..self.x_buf_off + len].copy_from_slice(block);
226 self.x_buf_off += len;
227 return;
228 }
229
230 let mut block = block;
231 if self.x_buf_off != 0 {
232 self.x_buf[self.x_buf_off..].copy_from_slice(&block[..available]);
233 block = &block[available..];
234
235 self.state.compress(slice::from_ref(&self.x_buf));
236 }
238
239 let (chunks, remainder) = block.as_chunks::<128>();
240
241 self.state.compress(chunks);
242
243 let remaining = remainder.len();
244 self.x_buf[..remaining].copy_from_slice(remainder);
245 self.x_buf_off = remaining;
246 }
247
248 fn do_final(self) -> Vec<u8> {
249 let mut output = vec![0u8; PARAMS::OUTPUT_LEN];
250 self.do_final_out(&mut output);
251 output
252 }
253
254 fn do_final_out(mut self, output: &mut [u8]) -> usize {
255 let n = *min(&output.len(), &PARAMS::OUTPUT_LEN);
256
257 let bit_len_hi: u64 = self.byte_count >> 61;
258 let bit_len_lo: u64 = self.byte_count << 3;
259
260 self.x_buf[self.x_buf_off] = 0x80;
261 self.x_buf_off += 1;
262
263 if self.x_buf_off > 112 {
264 self.x_buf[self.x_buf_off..].fill(0x00);
265 self.state.compress(slice::from_ref(&self.x_buf));
266 self.x_buf_off = 0;
267 }
268
269 self.x_buf[self.x_buf_off..112].fill(0x00);
270 self.x_buf[112..120].copy_from_slice(&bit_len_hi.to_be_bytes());
271 self.x_buf[120..128].copy_from_slice(&bit_len_lo.to_be_bytes());
272 self.state.compress(slice::from_ref(&self.x_buf));
273
274 let h = &self.state.h;
275
276 for i in 0..(n / 8) {
277 output[i * 8..i * 8 + 8].copy_from_slice(&h[i].to_be_bytes());
278 }
279 if !n.is_multiple_of(8) {
280 output[((n / 8) * 8)..((n / 8) * 8) + (n % 8)]
281 .copy_from_slice(&h[n / 8].to_be_bytes()[0..(n % 8)]);
282 }
283
284 n
285 }
286
287 #[allow(unused)]
291 fn do_final_partial_bits(
292 self,
293 partial_byte: u8,
294 num_partial_bits: usize,
295 ) -> Result<Vec<u8>, HashError> {
296 unimplemented!()
297 }
298
299 #[allow(unused)]
303 fn do_final_partial_bits_out(
304 self,
305 partial_byte: u8,
306 num_partial_bits: usize,
307 output: &mut [u8],
308 ) -> Result<usize, HashError> {
309 unimplemented!()
310 }
311
312 fn max_security_strength(&self) -> SecurityStrength {
313 SecurityStrength::from_bytes(PARAMS::OUTPUT_LEN / 2)
314 }
315}