1 use digest::{Input, BlockInput, FixedOutput, Reset}; 2 use digest::generic_array::GenericArray; 3 use digest::generic_array::typenum::{U28, U32, U48, U64, U128}; 4 use block_buffer::BlockBuffer; 5 use block_buffer::byteorder::{BE, ByteOrder}; 6 7 use consts::{STATE_LEN, H384, H512, H512_TRUNC_224, H512_TRUNC_256}; 8 9 #[cfg(any(not(feature = "asm"), feature = "asm-aarch64"))] 10 use sha512_utils::compress512; 11 #[cfg(all(feature = "asm", not(feature = "asm-aarch64")))] 12 use sha2_asm::compress512; 13 14 type BlockSize = U128; 15 type Block = GenericArray<u8, BlockSize>; 16 17 /// A structure that represents that state of a digest computation for the 18 /// SHA-2 512 family of digest functions 19 #[derive(Clone)] 20 struct Engine512State { 21 h: [u64; 8], 22 } 23 24 impl Engine512State { new(h: &[u64; 8]) -> Engine512State25 fn new(h: &[u64; 8]) -> Engine512State { Engine512State { h: *h } } 26 process_block(&mut self, block: &Block)27 pub fn process_block(&mut self, block: &Block) { 28 let block = unsafe { &*(block.as_ptr() as *const [u8; 128])}; 29 compress512(&mut self.h, block); 30 } 31 } 32 33 /// A structure that keeps track of the state of the Sha-512 operation and 34 /// contains the logic necessary to perform the final calculations. 35 #[derive(Clone)] 36 struct Engine512 { 37 len: (u64, u64), // TODO: replace with u128 on MSRV bump 38 buffer: BlockBuffer<BlockSize>, 39 state: Engine512State, 40 } 41 42 impl Engine512 { new(h: &[u64; STATE_LEN]) -> Engine51243 fn new(h: &[u64; STATE_LEN]) -> Engine512 { 44 Engine512 { 45 len: (0, 0), 46 buffer: Default::default(), 47 state: Engine512State::new(h), 48 } 49 } 50 input(&mut self, input: &[u8])51 fn input(&mut self, input: &[u8]) { 52 let (res, over) = self.len.1.overflowing_add((input.len() as u64) << 3); 53 self.len.1 = res; 54 if over { self.len.0 += 1; } 55 let self_state = &mut self.state; 56 self.buffer.input(input, |d| self_state.process_block(d)); 57 } 58 finish(&mut self)59 fn finish(&mut self) { 60 let self_state = &mut self.state; 61 let (hi, lo) = self.len; 62 self.buffer.len128_padding_be(hi, lo, |d| self_state.process_block(d)); 63 } 64 reset(&mut self, h: &[u64; STATE_LEN])65 fn reset(&mut self, h: &[u64; STATE_LEN]) { 66 self.len = (0, 0); 67 self.buffer.reset(); 68 self.state = Engine512State::new(h); 69 } 70 } 71 72 73 /// The SHA-512 hash algorithm with the SHA-512 initial hash value. 74 #[derive(Clone)] 75 pub struct Sha512 { 76 engine: Engine512, 77 } 78 79 impl Default for Sha512 { default() -> Self80 fn default() -> Self { Sha512 { engine: Engine512::new(&H512) } } 81 } 82 83 impl BlockInput for Sha512 { 84 type BlockSize = BlockSize; 85 } 86 87 impl Input for Sha512 { input<B: AsRef<[u8]>>(&mut self, input: B)88 fn input<B: AsRef<[u8]>>(&mut self, input: B) { 89 self.engine.input(input.as_ref()); 90 } 91 } 92 93 impl FixedOutput for Sha512 { 94 type OutputSize = U64; 95 fixed_result(mut self) -> GenericArray<u8, Self::OutputSize>96 fn fixed_result(mut self) -> GenericArray<u8, Self::OutputSize> { 97 self.engine.finish(); 98 99 let mut out = GenericArray::default(); 100 BE::write_u64_into(&self.engine.state.h[..], out.as_mut_slice()); 101 out 102 } 103 } 104 105 impl Reset for Sha512 { reset(&mut self)106 fn reset(&mut self) { 107 self.engine.reset(&H512); 108 } 109 } 110 111 /// The SHA-512 hash algorithm with the SHA-384 initial hash value. The result 112 /// is truncated to 384 bits. 113 #[derive(Clone)] 114 pub struct Sha384 { 115 engine: Engine512, 116 } 117 118 impl Default for Sha384 { default() -> Self119 fn default() -> Self { Sha384 { engine: Engine512::new(&H384) } } 120 } 121 122 impl BlockInput for Sha384 { 123 type BlockSize = BlockSize; 124 } 125 126 impl Input for Sha384 { input<B: AsRef<[u8]>>(&mut self, input: B)127 fn input<B: AsRef<[u8]>>(&mut self, input: B) { 128 self.engine.input(input.as_ref()); 129 } 130 } 131 132 impl FixedOutput for Sha384 { 133 type OutputSize = U48; 134 fixed_result(mut self) -> GenericArray<u8, Self::OutputSize>135 fn fixed_result(mut self) -> GenericArray<u8, Self::OutputSize> { 136 self.engine.finish(); 137 138 let mut out = GenericArray::default(); 139 BE::write_u64_into(&self.engine.state.h[..6], out.as_mut_slice()); 140 out 141 } 142 } 143 144 impl Reset for Sha384 { reset(&mut self)145 fn reset(&mut self) { 146 self.engine.reset(&H384); 147 } 148 } 149 150 /// The SHA-512 hash algorithm with the SHA-512/256 initial hash value. The 151 /// result is truncated to 256 bits. 152 #[derive(Clone)] 153 pub struct Sha512Trunc256 { 154 engine: Engine512, 155 } 156 157 impl Default for Sha512Trunc256 { default() -> Self158 fn default() -> Self { 159 Sha512Trunc256 { engine: Engine512::new(&H512_TRUNC_256) } 160 } 161 } 162 163 impl BlockInput for Sha512Trunc256 { 164 type BlockSize = BlockSize; 165 } 166 167 impl Input for Sha512Trunc256 { input<B: AsRef<[u8]>>(&mut self, input: B)168 fn input<B: AsRef<[u8]>>(&mut self, input: B) { 169 self.engine.input(input.as_ref()); 170 } 171 } 172 173 impl FixedOutput for Sha512Trunc256 { 174 type OutputSize = U32; 175 fixed_result(mut self) -> GenericArray<u8, Self::OutputSize>176 fn fixed_result(mut self) -> GenericArray<u8, Self::OutputSize> { 177 self.engine.finish(); 178 179 let mut out = GenericArray::default(); 180 BE::write_u64_into(&self.engine.state.h[..4], out.as_mut_slice()); 181 out 182 } 183 } 184 185 impl Reset for Sha512Trunc256 { reset(&mut self)186 fn reset(&mut self) { 187 self.engine.reset(&H512_TRUNC_256); 188 } 189 } 190 191 /// The SHA-512 hash algorithm with the SHA-512/224 initial hash value. 192 /// The result is truncated to 224 bits. 193 #[derive(Clone)] 194 pub struct Sha512Trunc224 { 195 engine: Engine512, 196 } 197 198 impl Default for Sha512Trunc224 { default() -> Self199 fn default() -> Self { 200 Sha512Trunc224 { engine: Engine512::new(&H512_TRUNC_224) } 201 } 202 } 203 204 impl BlockInput for Sha512Trunc224 { 205 type BlockSize = BlockSize; 206 } 207 208 impl Input for Sha512Trunc224 { input<B: AsRef<[u8]>>(&mut self, input: B)209 fn input<B: AsRef<[u8]>>(&mut self, input: B) { 210 self.engine.input(input.as_ref()); 211 } 212 } 213 214 impl FixedOutput for Sha512Trunc224 { 215 type OutputSize = U28; 216 fixed_result(mut self) -> GenericArray<u8, Self::OutputSize>217 fn fixed_result(mut self) -> GenericArray<u8, Self::OutputSize> { 218 self.engine.finish(); 219 220 let mut out = GenericArray::default(); 221 BE::write_u64_into(&self.engine.state.h[..3], &mut out[..24]); 222 BE::write_u32(&mut out[24..28], (self.engine.state.h[3] >> 32) as u32); 223 out 224 } 225 } 226 227 impl Reset for Sha512Trunc224 { reset(&mut self)228 fn reset(&mut self) { 229 self.engine.reset(&H512_TRUNC_224); 230 } 231 } 232 233 impl_opaque_debug!(Sha384); 234 impl_opaque_debug!(Sha512); 235 impl_opaque_debug!(Sha512Trunc224); 236 impl_opaque_debug!(Sha512Trunc256); 237 238 impl_write!(Sha384); 239 impl_write!(Sha512); 240 impl_write!(Sha512Trunc224); 241 impl_write!(Sha512Trunc256); 242