bouncycastle_sha3/
shake.rs1use bouncycastle_core_interface::errors::{HashError, KDFError};
2use bouncycastle_core_interface::key_material::{KeyMaterialInternal, KeyType};
3use bouncycastle_core_interface::traits::{Algorithm, KeyMaterial, SecurityStrength, KDF, XOF};
4use bouncycastle_utils::{max, min};
5use crate::keccak::KeccakDigest;
6use crate::SHAKEParams;
7
8
9#[derive(Clone)]
24pub struct SHAKE<PARAMS: SHAKEParams> {
25 _phantomdata: std::marker::PhantomData<PARAMS>,
26 keccak: KeccakDigest,
27 kdf_key_type: KeyType,
28 kdf_security_strength: SecurityStrength,
29 kdf_entropy: usize,
30}
31
32impl<PARAMS: SHAKEParams> Algorithm for SHAKE<PARAMS> {
35 const ALG_NAME: &'static str = PARAMS::ALG_NAME;
36 const MAX_SECURITY_STRENGTH: SecurityStrength = PARAMS::MAX_SECURITY_STRENGTH;
37}
38
39impl<PARAMS: SHAKEParams> SHAKE<PARAMS> {
40 pub fn new() -> Self {
41 Self {
42 _phantomdata: std::marker::PhantomData,
43 keccak: KeccakDigest::new(PARAMS::SIZE),
44 kdf_key_type: KeyType::Zeroized,
45 kdf_security_strength: SecurityStrength::None,
46 kdf_entropy: 0,
47 }
48 }
49
50 fn hash_internal(mut self, data: &[u8], result_len: usize) -> Vec<u8> {
52 self.absorb(data).expect("Should be infallible.");
53 self.squeeze(result_len).expect(".squeeze() should be infallible.") }
55
56 fn hash_internal_out(mut self, data: &[u8], output: &mut [u8]) -> usize {
57 self.absorb(data).expect("Should be infallible.");
58 self.squeeze_out(output).expect(".squeeze_out() should be infallible.")
59 }
60
61 fn mix_key_internal(&mut self, key: &impl KeyMaterial) -> Result<(), HashError> {
62 self.kdf_key_type = *max(&self.kdf_key_type, &key.key_type());
64
65 if key.is_full_entropy() {
67 self.kdf_entropy += key.key_len();
68 self.kdf_security_strength =
69 max(&self.kdf_security_strength, &key.security_strength()).clone();
70 self.kdf_security_strength =
71 min(&self.kdf_security_strength, &SecurityStrength::from_bits(PARAMS::SIZE as usize))
72 .clone();
73 }
74
75 self.absorb(key.ref_to_bytes())
76 }
77
78 fn derive_key_final_internal(
79 mut self,
80 additional_input: &[u8],
81 ) -> Result<Box<dyn KeyMaterial>, KDFError> {
82 let mut output_key = KeyMaterialInternal::<64>::new();
85 self.derive_key_out_final_internal(additional_input, &mut output_key)?;
86
87 output_key.truncate(2 * (PARAMS::SIZE as usize) / 8)?;
89 Ok(Box::new(output_key))
90 }
91
92 fn derive_key_out_final_internal(
93 &mut self,
94 additional_input: &[u8],
95 output_key: &mut impl KeyMaterial,
96 ) -> Result<usize, KDFError> {
97 if self.kdf_entropy < 2 * (PARAMS::SIZE as usize) / 8 {
103 self.kdf_key_type = min(&self.kdf_key_type, &KeyType::BytesLowEntropy).clone();
104 self.kdf_security_strength = SecurityStrength::None; }
106
107 self.absorb(additional_input)?;
108
109 output_key.allow_hazardous_operations();
111 let bytes_written = self.squeeze_out(output_key.mut_ref_to_bytes().expect("We just set .allow_hazardous_operations(), so this should be fine."))?;
112 output_key.set_key_len(bytes_written)?;
113
114 if self.kdf_key_type == KeyType::Zeroized {
116 self.kdf_key_type = KeyType::BytesLowEntropy;
117 }
118 output_key.set_key_type(self.kdf_key_type)?;
119 output_key.set_security_strength(
120 min(&self.kdf_security_strength, &SecurityStrength::from_bits(bytes_written * 8))
121 .clone(),
122 )?;
123 output_key.drop_hazardous_operations();
124 Ok(bytes_written)
125 }
126}
127
128impl<PARAMS: SHAKEParams> KDF for SHAKE<PARAMS> {
129 fn derive_key(
137 mut self,
138 key: &impl KeyMaterial,
139 additional_input: &[u8],
140 ) -> Result<Box<dyn KeyMaterial>, KDFError> {
141 self.mix_key_internal(key)?;
143 self.derive_key_final_internal(additional_input)
144 }
145
146 fn derive_key_out(
147 mut self,
148 key: &impl KeyMaterial,
149 additional_input: &[u8],
150 output_key: &mut impl KeyMaterial,
151 ) -> Result<usize, KDFError> {
152 self.mix_key_internal(key)?;
154 self.derive_key_out_final_internal(additional_input, output_key)
155 }
156
157 fn derive_key_from_multiple(
164 mut self,
165 keys: &[&impl KeyMaterial],
166 additional_input: &[u8],
167 ) -> Result<Box<dyn KeyMaterial>, KDFError> {
168 for key in keys {
169 self.mix_key_internal(*key)?;
170 }
171 self.derive_key_final_internal(additional_input)
172 }
173
174 fn derive_key_from_multiple_out(
175 mut self,
176 keys: &[&impl KeyMaterial],
177 additional_input: &[u8],
178 output_key: &mut impl KeyMaterial,
179 ) -> Result<usize, KDFError> {
180 for key in keys {
181 self.mix_key_internal(*key)?;
182 }
183 self.derive_key_out_final_internal(additional_input, output_key)
184 }
185
186 fn max_security_strength(&self) -> SecurityStrength {
187 SecurityStrength::from_bits(PARAMS::SIZE as usize)
188 }
189}
190
191impl<PARAMS: SHAKEParams> Default for SHAKE<PARAMS> {
192 fn default() -> Self {
193 Self::new()
194 }
195}
196
197impl<PARAMS: SHAKEParams> XOF for SHAKE<PARAMS> {
198 fn hash_xof(self, data: &[u8], result_len: usize) -> Vec<u8> {
199 self.hash_internal(data, result_len)
200 }
201
202 fn hash_xof_out(self, data: &[u8], output: &mut [u8]) -> usize {
203 self.hash_internal_out(data, output)
204 }
205
206 fn absorb(&mut self, data: &[u8]) -> Result<(), HashError> {
207 Ok(self.keccak.absorb(data))
208 }
209
210 fn absorb_last_partial_byte(
212 &mut self,
213 partial_byte: u8,
214 num_partial_bits: usize,
215 ) -> Result<(), HashError> {
216 if !(1..=7).contains(&num_partial_bits) {
217 return Err(HashError::InvalidLength("must be in the range [0,7]"));
218 }
219 let mut final_input: u16 =
221 ((partial_byte as u16) & ((1 << num_partial_bits) - 1)) | (0x0F << num_partial_bits);
222 let mut final_bits = num_partial_bits + 4;
223
224 if final_bits >= 8 {
225 self.keccak.absorb(&[final_input as u8]);
226 final_bits -= 8;
227 final_input >>= 8;
228 }
229
230 self.keccak.absorb_bits(final_input as u8, final_bits).expect("Absorb failed.");
231
232 Ok(())
233 }
234
235 fn squeeze(&mut self, num_bytes: usize) -> Result<Vec<u8>, HashError> {
237 let mut out: Vec<u8> = vec![0u8; num_bytes];
238 self.squeeze_out(&mut out)?;
239 Ok(out)
240 }
241
242 fn squeeze_out(&mut self, output: &mut [u8]) -> Result<usize, HashError> {
244 if !self.keccak.squeezing {
245 self.keccak.absorb_bits(0x0F, 4).expect("Absorb_bits failed");
246 };
247
248 Ok(self.keccak.squeeze(output))
249 }
250
251 fn squeeze_partial_byte_final(self, num_bits: usize) -> Result<u8, HashError> {
252 let mut output: u8 = 0;
253 self.squeeze_partial_byte_final_out(num_bits, &mut output)?;
254 Ok(output)
255 }
256
257 fn squeeze_partial_byte_final_out(
259 mut self,
260 num_bits: usize,
261 output: &mut u8,
262 ) -> Result<(), HashError> {
263 if !(1..=7).contains(&num_bits) {
264 return Err(HashError::InvalidLength("must be in the range [0,7]"));
265 }
266
267 let mut buf = [0u8; 1];
268 self.keccak.squeeze(&mut buf);
269 *output = buf[0] >> 8 - num_bits;
270 Ok(())
271 }
272
273 fn max_security_strength(&self) -> SecurityStrength {
274 SecurityStrength::from_bits(PARAMS::SIZE as usize)
275 }
276}