bouncycastle_sha3/
sha3.rs1use bouncycastle_core::errors::{HashError, KDFError};
2use bouncycastle_core::key_material::{KeyMaterial, KeyMaterialTrait, KeyType};
3use bouncycastle_core::traits::{Hash, SecurityStrength, KDF};
4use bouncycastle_utils::{max, min};
5use crate::keccak::KeccakDigest;
6use crate::SHA3Params;
7
8#[derive(Clone)]
9pub struct SHA3<PARAMS: SHA3Params> {
10 _params: std::marker::PhantomData<PARAMS>,
11 keccak: KeccakDigest,
12 kdf_key_type: KeyType,
13 kdf_security_strength: SecurityStrength,
14 kdf_entropy: usize,
15}
16
17impl<PARAMS: SHA3Params> SHA3<PARAMS> {
20 pub fn new() -> Self {
21 Self {
22 _params: std::marker::PhantomData,
23 keccak: KeccakDigest::new(PARAMS::SIZE),
24 kdf_key_type: KeyType::Zeroized,
25 kdf_security_strength: SecurityStrength::None,
26 kdf_entropy: 0,
27 }
28 }
29
30 fn hash_internal(mut self, data: &[u8], output: &mut [u8]) -> usize {
32 self.do_update(data);
33 self.do_final_out(output)
34 }
35
36 fn mix_key_internal(&mut self, key: &impl KeyMaterialTrait) {
37 self.kdf_key_type = *max(&self.kdf_key_type, &key.key_type());
39
40 if key.is_full_entropy() {
42 self.kdf_entropy += key.key_len();
43 self.kdf_security_strength =
44 max(&self.kdf_security_strength, &key.security_strength()).clone();
45 self.kdf_security_strength = min(
46 &self.kdf_security_strength,
47 &SecurityStrength::from_bits(PARAMS::OUTPUT_LEN * 8 / 2),
48 )
49 .clone();
50 }
51
52 self.do_update(key.ref_to_bytes())
53 }
54
55 fn derive_key_final_internal(
56 self,
57 additional_input: &[u8],
58 ) -> Result<Box<dyn KeyMaterialTrait>, KDFError> {
59 let mut output_key = KeyMaterial::<64>::new();
60 self.derive_key_out_final_internal(additional_input, &mut output_key)?;
61
62 Ok(Box::new(output_key))
63 }
64
65 fn derive_key_out_final_internal(
66 mut self,
67 additional_input: &[u8],
68 output_key: &mut impl KeyMaterialTrait,
69 ) -> Result<usize, KDFError> {
70 if self.kdf_entropy < PARAMS::OUTPUT_LEN {
74 self.kdf_key_type = min(&self.kdf_key_type, &KeyType::BytesLowEntropy).clone();
75 self.kdf_security_strength = SecurityStrength::None; }
77
78 self.do_update(additional_input);
79
80 let mut key_type = self.kdf_key_type.clone();
81 let output_security_strength = self.kdf_security_strength.clone();
82 output_key.allow_hazardous_operations();
83 let bytes_written = self.do_final_out(output_key.mut_ref_to_bytes()?);
84 output_key.set_key_len(bytes_written)?;
85
86 if key_type == KeyType::Zeroized {
88 key_type = KeyType::BytesLowEntropy;
89 }
90 output_key.set_key_type(key_type)?;
91 output_key.set_security_strength(
92 min(&output_security_strength, &SecurityStrength::from_bits(bytes_written * 8)).clone(),
93 )?;
94 output_key.drop_hazardous_operations();
95 output_key.truncate(min(&output_key.key_len(), &PARAMS::OUTPUT_LEN).clone())?;
96 Ok(bytes_written)
97 }
98}
99
100impl<PARAMS: SHA3Params> Default for SHA3<PARAMS> {
101 fn default() -> Self {
102 Self::new()
103 }
104}
105
106impl<PARAMS: SHA3Params> Hash for SHA3<PARAMS> {
107 fn block_bitlen(&self) -> usize {
110 PARAMS::BLOCK_LEN * 8
111 }
112
113 fn output_len(&self) -> usize {
114 PARAMS::OUTPUT_LEN
115 }
116
117 fn hash(self, data: &[u8]) -> Vec<u8> {
118 let mut output: Vec<u8> = vec![0u8; PARAMS::OUTPUT_LEN];
119 _ = self.hash_internal(data, &mut output[..]);
120 output
121 }
122
123 fn hash_out(self, data: &[u8], mut output: &mut [u8]) -> usize {
124 self.hash_internal(data, &mut output)
125 }
126
127 fn do_update(&mut self, data: &[u8]) {
128 self.keccak.absorb(data)
129 }
130
131 fn do_final(self) -> Vec<u8> {
132 let dbg_rslt_len = self.output_len();
133 let mut output: Vec<u8> = vec![0u8; self.output_len()];
134 let bytes_written = self.do_final_out(output.as_mut_slice());
135 debug_assert_eq!(bytes_written, dbg_rslt_len);
136
137 output
138 }
139
140 fn do_final_out(mut self, output: &mut [u8]) -> usize {
143 self.keccak.absorb_bits(0x02, 2).expect("do_final_out: keccak.absorb_bits failed."); let bytes_written = if output.len() <= self.output_len() {
146 self.keccak.squeeze(output)
147 } else {
148 let min =
149 if output.len() >= self.output_len() { self.output_len() } else { output.len() };
150 self.keccak.squeeze(&mut output[..min])
151 };
152 bytes_written
153 }
154
155 fn do_final_partial_bits(
156 self,
157 partial_byte: u8,
158 num_partial_bits: usize,
159 ) -> Result<Vec<u8>, HashError> {
160 let dbg_rslt_len = self.output_len();
161 let mut output: Vec<u8> = vec![0u8; self.output_len()];
162 let bytes_written =
163 self.do_final_partial_bits_out(partial_byte, num_partial_bits, output.as_mut_slice())?;
164 debug_assert_eq!(bytes_written, dbg_rslt_len);
165
166 Ok(output)
167 }
168
169 fn do_final_partial_bits_out(
170 mut self,
171 partial_byte: u8,
172 num_partial_bits: usize,
173 output: &mut [u8],
174 ) -> Result<usize, HashError> {
175 let mut final_input: u16 =
177 ((partial_byte as u16) & ((1 << num_partial_bits) - 1)) | (0x02 << num_partial_bits);
178 let mut final_bits = num_partial_bits + 2;
179
180 if final_bits >= 8 {
181 self.keccak.absorb(&[final_input as u8]);
182 final_bits -= 8;
183 final_input >>= 8;
184 }
185
186 self.keccak.absorb_bits(final_input as u8, final_bits)?;
187
188 let min = if output.len() >= self.output_len() { self.output_len() } else { output.len() };
189 Ok(self.keccak.squeeze(&mut output[..min]))
190 }
191
192 fn max_security_strength(&self) -> SecurityStrength {
193 SecurityStrength::from_bytes(PARAMS::OUTPUT_LEN / 2)
194 }
195}
196
197impl<PARAMS: SHA3Params> KDF for SHA3<PARAMS> {
199 fn derive_key(
203 mut self,
204 key: &impl KeyMaterialTrait,
205 additional_input: &[u8],
206 ) -> Result<Box<dyn KeyMaterialTrait>, KDFError> {
207 self.mix_key_internal(key);
208 self.derive_key_final_internal(additional_input)
209 }
210
211 fn derive_key_out(
212 mut self,
213 key: &impl KeyMaterialTrait,
214 additional_input: &[u8],
215 output_key: &mut impl KeyMaterialTrait,
216 ) -> Result<usize, KDFError> {
217 self.mix_key_internal(key);
219 self.derive_key_out_final_internal(additional_input, output_key)
220 }
221
222 fn derive_key_from_multiple(
223 mut self,
224 keys: &[&impl KeyMaterialTrait],
225 additional_input: &[u8],
226 ) -> Result<Box<dyn KeyMaterialTrait>, KDFError> {
227 for key in keys {
228 self.mix_key_internal(*key);
229 }
230 self.derive_key_final_internal(additional_input)
231 }
232
233 fn derive_key_from_multiple_out(
234 mut self,
235 keys: &[&impl KeyMaterialTrait],
236 additional_input: &[u8],
237 output_key: &mut impl KeyMaterialTrait,
238 ) -> Result<usize, KDFError> {
239 for key in keys {
241 self.mix_key_internal(*key);
242 }
243 self.derive_key_out_final_internal(additional_input, output_key)
244 }
245
246 fn max_security_strength(&self) -> SecurityStrength {
247 SecurityStrength::from_bytes(PARAMS::OUTPUT_LEN / 2)
248 }
249}