1use crate::SHAKEParams;
2use crate::keccak::{
3 KeccakInternal, KeccakSize, SHA3_FAMILY_STATE_LEN, SUSPENDED_SHA3_STATE_LEN,
4 deserialize_sha3_family_state, serialize_sha3_family_state,
5};
6use bouncycastle_core::errors::{HashError, KDFError, SuspendableError};
7use bouncycastle_core::key_material;
8use bouncycastle_core::key_material::{KeyMaterial, KeyMaterialTrait, KeyType};
9use bouncycastle_core::suspendable_state::{add_lib_ver, check_lib_ver};
10use bouncycastle_core::traits::{Algorithm, KDF, SecurityStrength, Suspendable, XOF};
11use bouncycastle_utils::{max, min};
12
13#[derive(Clone)]
31pub struct SHAKEInternal<PARAMS: SHAKEParams> {
32 _phantomdata: core::marker::PhantomData<PARAMS>,
33 keccak: KeccakInternal,
34 kdf_key_type: KeyType,
35 kdf_security_strength: SecurityStrength,
36 kdf_entropy: usize,
37}
38
39impl<PARAMS: SHAKEParams> Algorithm for SHAKEInternal<PARAMS> {
40 const ALG_NAME: &'static str = PARAMS::ALG_NAME;
41 const MAX_SECURITY_STRENGTH: SecurityStrength = PARAMS::MAX_SECURITY_STRENGTH;
42}
43
44impl<PARAMS: SHAKEParams> SHAKEInternal<PARAMS> {
45 pub fn new() -> Self {
47 Self {
48 _phantomdata: core::marker::PhantomData,
49 keccak: KeccakInternal::new(PARAMS::SIZE),
50 kdf_key_type: KeyType::Zeroized,
51 kdf_security_strength: SecurityStrength::None,
52 kdf_entropy: 0,
53 }
54 }
55
56 fn hash_internal(mut self, data: &[u8], result_len: usize) -> Vec<u8> {
58 self.absorb(data).expect("absorb precedes squeeze on a fresh SHAKE");
60 self.squeeze(result_len)
61 }
62
63 fn hash_internal_out(mut self, data: &[u8], output: &mut [u8]) -> usize {
64 output.fill(0);
65
66 self.absorb(data).expect("absorb precedes squeeze on a fresh SHAKE");
68 self.squeeze_out(output)
69 }
70
71 fn mix_key_internal(&mut self, key: &impl KeyMaterialTrait) {
72 self.kdf_key_type = *max(&self.kdf_key_type, &key.key_type());
74
75 if key.is_full_entropy() {
77 self.kdf_entropy += key.key_len();
78 self.kdf_security_strength =
79 max(&self.kdf_security_strength, &key.security_strength()).clone();
80 self.kdf_security_strength = min(
81 &self.kdf_security_strength,
82 &SecurityStrength::from_bits(PARAMS::SIZE as usize),
83 )
84 .clone();
85 }
86
87 self.absorb(key.ref_to_bytes()).expect("absorb precedes squeeze during key mixing");
89 }
90
91 fn derive_key_final_internal(
92 mut self,
93 additional_input: &[u8],
94 ) -> Result<Box<dyn KeyMaterialTrait>, KDFError> {
95 let mut output_key = KeyMaterial::<64>::new();
97 self.derive_key_out_final_internal(additional_input, &mut output_key)?;
98
99 match PARAMS::SIZE {
102 KeccakSize::_128 => output_key.set_key_len(32).expect("truncate should be infallible"),
103 KeccakSize::_256 => output_key.set_key_len(64).expect("truncate should be infallible"),
104 _ => unreachable!(),
105 }
106 Ok(Box::new(output_key))
107 }
108
109 fn derive_key_out_final_internal(
110 &mut self,
111 additional_input: &[u8],
112 output_key: &mut impl KeyMaterialTrait,
113 ) -> Result<usize, KDFError> {
114 if self.kdf_entropy < 2 * (PARAMS::SIZE as usize) / 8 {
120 self.kdf_key_type = min(&self.kdf_key_type, &KeyType::Unknown).clone();
121 self.kdf_security_strength = SecurityStrength::None; }
123
124 self.absorb(additional_input).expect("absorb precedes squeeze during key derivation");
127
128 let mut bytes_written: usize = 0;
129 key_material::do_hazardous_operations(output_key, |output_key| {
130 bytes_written = self.squeeze_out(
131 output_key.ref_to_bytes_mut().expect("Infallible within do_hazardous_operations"),
132 );
133 output_key.set_key_len(bytes_written)
134 })?;
135
136 if self.kdf_key_type == KeyType::Zeroized {
138 self.kdf_key_type = KeyType::Unknown;
139 }
140 key_material::do_hazardous_operations(output_key, |output_key| {
141 output_key.set_key_type(self.kdf_key_type)?;
142 output_key.set_security_strength(
143 min(&self.kdf_security_strength, &SecurityStrength::from_bits(bytes_written * 8))
144 .clone(),
145 )
146 })?;
147 Ok(bytes_written)
148 }
149}
150
151impl<PARAMS: SHAKEParams> Suspendable<SUSPENDED_SHA3_STATE_LEN> for SHAKEInternal<PARAMS> {
152 fn suspend(self) -> [u8; SUSPENDED_SHA3_STATE_LEN] {
153 let mut out_to_return = [0u8; SUSPENDED_SHA3_STATE_LEN];
154
155 let out: &mut [u8; SHA3_FAMILY_STATE_LEN] =
157 add_lib_ver(&mut out_to_return).try_into().unwrap();
158
159 serialize_sha3_family_state(
160 out,
161 PARAMS::STATE_TAG,
162 &self.keccak,
163 self.kdf_key_type,
164 self.kdf_security_strength,
165 self.kdf_entropy,
166 );
167
168 out_to_return
169 }
170
171 fn from_suspended(
172 serialized_state: [u8; SUSPENDED_SHA3_STATE_LEN],
173 ) -> Result<Self, SuspendableError> {
174 let input: &[u8; SHA3_FAMILY_STATE_LEN] =
176 check_lib_ver(&serialized_state, None)?.try_into().unwrap();
177
178 let rate = 1600 - ((PARAMS::SIZE as usize) << 1);
181 let (keccak, kdf_key_type, kdf_security_strength, kdf_entropy) =
182 deserialize_sha3_family_state(input, PARAMS::STATE_TAG, rate)?;
183
184 Ok(SHAKEInternal {
185 _phantomdata: core::marker::PhantomData,
186 keccak,
187 kdf_key_type,
188 kdf_security_strength,
189 kdf_entropy,
190 })
191 }
192}
193
194impl<PARAMS: SHAKEParams> KDF for SHAKEInternal<PARAMS> {
195 fn derive_key(
204 mut self,
205 key: &impl KeyMaterialTrait,
206 additional_input: &[u8],
207 ) -> Result<Box<dyn KeyMaterialTrait>, KDFError> {
208 self.mix_key_internal(key);
210 self.derive_key_final_internal(additional_input)
211 }
212
213 fn derive_key_out(
214 mut self,
215 key: &impl KeyMaterialTrait,
216 additional_input: &[u8],
217 output_key: &mut impl KeyMaterialTrait,
218 ) -> Result<usize, KDFError> {
219 self.mix_key_internal(key);
221 self.derive_key_out_final_internal(additional_input, output_key)
222 }
223
224 fn derive_key_from_multiple(
234 mut self,
235 keys: &[&impl KeyMaterialTrait],
236 additional_input: &[u8],
237 ) -> Result<Box<dyn KeyMaterialTrait>, KDFError> {
238 for key in keys {
239 self.mix_key_internal(*key);
240 }
241 self.derive_key_final_internal(additional_input)
242 }
243
244 fn derive_key_from_multiple_out(
245 mut self,
246 keys: &[&impl KeyMaterialTrait],
247 additional_input: &[u8],
248 output_key: &mut impl KeyMaterialTrait,
249 ) -> Result<usize, KDFError> {
250 for key in keys {
251 self.mix_key_internal(*key);
252 }
253 self.derive_key_out_final_internal(additional_input, output_key)
254 }
255
256 fn max_security_strength(&self) -> SecurityStrength {
257 SecurityStrength::from_bits(PARAMS::SIZE as usize)
258 }
259}
260
261impl<PARAMS: SHAKEParams> Default for SHAKEInternal<PARAMS> {
262 fn default() -> Self {
263 Self::new()
264 }
265}
266
267impl<PARAMS: SHAKEParams> XOF for SHAKEInternal<PARAMS> {
268 fn hash_xof(self, data: &[u8], result_len: usize) -> Vec<u8> {
269 self.hash_internal(data, result_len)
270 }
271
272 fn hash_xof_out(self, data: &[u8], output: &mut [u8]) -> usize {
273 output.fill(0);
274
275 self.hash_internal_out(data, output)
276 }
277
278 fn absorb(&mut self, data: &[u8]) -> Result<(), HashError> {
287 if self.keccak.squeezing {
290 return Err(HashError::InvalidState("cannot absorb after squeezing has begun"));
291 }
292 self.keccak.absorb(data);
293 Ok(())
294 }
295
296 fn absorb_last_partial_byte(
298 &mut self,
299 partial_byte: u8,
300 num_partial_bits: usize,
301 ) -> Result<(), HashError> {
302 if self.keccak.squeezing {
305 return Err(HashError::InvalidState("cannot absorb after squeezing has begun"));
306 }
307 if !(1..=7).contains(&num_partial_bits) {
308 return Err(HashError::InvalidLength("must be in the range [0,7]"));
309 }
310 let mut final_input: u16 =
313 ((partial_byte as u16) & ((1 << num_partial_bits) - 1)) | (0x0F << num_partial_bits);
314 let mut final_bits = num_partial_bits + 4;
315
316 if final_bits >= 8 {
317 self.keccak.absorb(&[final_input as u8]);
318 final_bits -= 8;
319 final_input >>= 8;
320 }
321
322 self.keccak.absorb_bits(final_input as u8, final_bits).expect("Absorb failed.");
325
326 Ok(())
327 }
328
329 fn squeeze(&mut self, num_bytes: usize) -> Vec<u8> {
330 let mut out: Vec<u8> = vec![0u8; num_bytes];
331 self.squeeze_out(&mut out);
332 out
333 }
334
335 fn squeeze_out(&mut self, output: &mut [u8]) -> usize {
336 output.fill(0);
337
338 if !self.keccak.squeezing {
339 self.keccak.absorb_bits(0x0F, 4).expect("Absorb_bits failed");
340 };
341
342 self.keccak.squeeze(output)
343 }
344
345 fn squeeze_partial_byte_final(self, num_bits: usize) -> Result<u8, HashError> {
346 let mut output: u8 = 0;
347 self.squeeze_partial_byte_final_out(num_bits, &mut output)?;
348 Ok(output)
349 }
350
351 fn squeeze_partial_byte_final_out(
353 mut self,
354 num_bits: usize,
355 output: &mut u8,
356 ) -> Result<(), HashError> {
357 if !(1..=7).contains(&num_bits) {
358 return Err(HashError::InvalidLength("must be in the range [0,7]"));
359 }
360
361 *output = 0;
362
363 let mut buf = [0u8; 1];
364 self.keccak.squeeze(&mut buf);
365 *output = buf[0] >> 8 - num_bits;
366 Ok(())
367 }
368
369 fn max_security_strength(&self) -> SecurityStrength {
370 SecurityStrength::from_bits(PARAMS::SIZE as usize)
371 }
372}