1use bouncycastle_core::errors::{HashError, SuspendableError};
2use bouncycastle_core::key_material::KeyType;
3use bouncycastle_core::traits::SecurityStrength;
4use bouncycastle_utils::secret::Secret;
5
6const KECCAK_ROUND_CONSTANTS: [u64; 24] = [
7 0x0000000000000001, 0x0000000000008082, 0x800000000000808A, 0x8000000080008000,
8 0x000000000000808B, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009,
9 0x000000000000008A, 0x0000000000000088, 0x0000000080008009, 0x000000008000000A,
10 0x000000008000808B, 0x800000000000008B, 0x8000000000008089, 0x8000000000008003,
11 0x8000000000008002, 0x8000000000000080, 0x000000000000800A, 0x800000008000000A,
12 0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008,
13];
14
15#[derive(Clone)]
16pub(crate) struct KeccakState {
17 buf: Secret<[u64; 25]>,
18 rate: usize,
19}
20
21impl KeccakState {
22 fn new(rate: usize) -> Self {
23 Self { buf: Secret::new(), rate }
24 }
25
26 fn absorb(&mut self, data: &[u8]) {
27 let count = self.rate >> 6;
28 for i in 0..count {
29 let mut tmp = [0u8; 8];
30 tmp.copy_from_slice(&data[i * 8..(i + 1) * 8]);
31 self.buf[i] ^= u64::from_le_bytes(tmp);
32 }
33
34 Self::permute(self);
35 }
36
37 pub fn permute(a: &mut Self) {
38 let [
39 mut a00,
40 mut a01,
41 mut a02,
42 mut a03,
43 mut a04,
44 mut a05,
45 mut a06,
46 mut a07,
47 mut a08,
48 mut a09,
49 mut a10,
50 mut a11,
51 mut a12,
52 mut a13,
53 mut a14,
54 mut a15,
55 mut a16,
56 mut a17,
57 mut a18,
58 mut a19,
59 mut a20,
60 mut a21,
61 mut a22,
62 mut a23,
63 mut a24,
64 ] = *a.buf;
65
66 for round_constant in KECCAK_ROUND_CONSTANTS {
67 let mut c0 = a00 ^ a05 ^ a10 ^ a15 ^ a20;
69 let mut c1 = a01 ^ a06 ^ a11 ^ a16 ^ a21;
70 let c2 = a02 ^ a07 ^ a12 ^ a17 ^ a22;
71 let c3 = a03 ^ a08 ^ a13 ^ a18 ^ a23;
72 let c4 = a04 ^ a09 ^ a14 ^ a19 ^ a24;
73
74 let d0 = c0.rotate_left(1) ^ c3;
75 let d1 = c1.rotate_left(1) ^ c4;
76 let d2 = c2.rotate_left(1) ^ c0;
77 let d3 = c3.rotate_left(1) ^ c1;
78 let d4 = c4.rotate_left(1) ^ c2;
79
80 a00 ^= d1;
81 a05 ^= d1;
82 a10 ^= d1;
83 a15 ^= d1;
84 a20 ^= d1;
85 a01 ^= d2;
86 a06 ^= d2;
87 a11 ^= d2;
88 a16 ^= d2;
89 a21 ^= d2;
90 a02 ^= d3;
91 a07 ^= d3;
92 a12 ^= d3;
93 a17 ^= d3;
94 a22 ^= d3;
95 a03 ^= d4;
96 a08 ^= d4;
97 a13 ^= d4;
98 a18 ^= d4;
99 a23 ^= d4;
100 a04 ^= d0;
101 a09 ^= d0;
102 a14 ^= d0;
103 a19 ^= d0;
104 a24 ^= d0;
105
106 c1 = a01.rotate_left(1);
108 a01 = a06.rotate_left(44);
109 a06 = a09.rotate_left(20);
110 a09 = a22.rotate_left(61);
111 a22 = a14.rotate_left(39);
112 a14 = a20.rotate_left(18);
113 a20 = a02.rotate_left(62);
114 a02 = a12.rotate_left(43);
115 a12 = a13.rotate_left(25);
116 a13 = a19.rotate_left(8);
117 a19 = a23.rotate_left(56);
118 a23 = a15.rotate_left(41);
119 a15 = a04.rotate_left(27);
120 a04 = a24.rotate_left(14);
121 a24 = a21.rotate_left(2);
122 a21 = a08.rotate_left(55);
123 a08 = a16.rotate_left(45);
124 a16 = a05.rotate_left(36);
125 a05 = a03.rotate_left(28);
126 a03 = a18.rotate_left(21);
127 a18 = a17.rotate_left(15);
128 a17 = a11.rotate_left(10);
129 a11 = a07.rotate_left(6);
130 a07 = a10.rotate_left(3);
131 a10 = c1;
132
133 c0 = a00 ^ (!a01 & a02);
135 c1 = a01 ^ (!a02 & a03);
136 a02 ^= !a03 & a04;
137 a03 ^= !a04 & a00;
138 a04 ^= !a00 & a01;
139 a00 = c0;
140 a01 = c1;
141
142 c0 = a05 ^ (!a06 & a07);
143 c1 = a06 ^ (!a07 & a08);
144 a07 ^= !a08 & a09;
145 a08 ^= !a09 & a05;
146 a09 ^= !a05 & a06;
147 a05 = c0;
148 a06 = c1;
149
150 c0 = a10 ^ (!a11 & a12);
151 c1 = a11 ^ (!a12 & a13);
152 a12 ^= !a13 & a14;
153 a13 ^= !a14 & a10;
154 a14 ^= !a10 & a11;
155 a10 = c0;
156 a11 = c1;
157
158 c0 = a15 ^ (!a16 & a17);
159 c1 = a16 ^ (!a17 & a18);
160 a17 ^= !a18 & a19;
161 a18 ^= !a19 & a15;
162 a19 ^= !a15 & a16;
163 a15 = c0;
164 a16 = c1;
165
166 c0 = a20 ^ (!a21 & a22);
167 c1 = a21 ^ (!a22 & a23);
168 a22 ^= !a23 & a24;
169 a23 ^= !a24 & a20;
170 a24 ^= !a20 & a21;
171 a20 = c0;
172 a21 = c1;
173
174 a00 ^= round_constant;
176 }
177
178 *a.buf = [
179 a00, a01, a02, a03, a04, a05, a06, a07, a08, a09, a10, a11, a12, a13, a14, a15, a16,
180 a17, a18, a19, a20, a21, a22, a23, a24,
181 ];
182 }
183}
184
185#[derive(Clone)]
187pub(crate) struct KeccakInternal {
188 state: KeccakState,
189 pub data_queue: Secret<[u8; 192]>,
190 rate: usize,
191 pub bits_in_queue: usize,
192 pub squeezing: bool,
193}
194
195#[derive(Clone)]
196pub(crate) enum KeccakSize {
197 _128 = 128,
198 _224 = 224,
199 _256 = 256,
200 _288 = 288,
201 _384 = 384,
202 _512 = 512,
203}
204
205impl KeccakInternal {
206 pub(super) fn new(size: KeccakSize) -> Self {
207 let rate = 1600 - ((size as usize) << 1);
208
209 Self {
210 state: KeccakState::new(rate),
211 data_queue: Secret::new(),
212 rate,
213 bits_in_queue: 0,
214 squeezing: false,
215 }
216 }
217
218 pub(super) fn absorb(&mut self, data: &[u8]) {
236 debug_assert!(self.bits_in_queue & 7 == 0, "attempt to absorb with odd length queue");
240 debug_assert!(!self.squeezing, "attempt to absorb while squeezing");
241
242 for byte in data {
243 self.data_queue[self.bits_in_queue >> 3] = *byte;
244 self.bits_in_queue += 8;
245
246 if self.bits_in_queue == self.rate {
247 self.state.absorb(&*self.data_queue);
248 self.bits_in_queue = 0;
249 }
250 }
251 }
252
253 pub(super) fn absorb_bits(&mut self, data: u8, bits: usize) -> Result<(), HashError> {
254 if bits == 0 {
255 return Ok(());
256 }
257 if !(1..=7).contains(&bits) {
258 return Err(HashError::InvalidLength("bits must be in the range 1 to 7"));
259 }
260 if (self.bits_in_queue & 7) != 0 {
261 return Err(HashError::InvalidState("attempt to absorb with odd length queue"));
262 }
263 if self.squeezing {
264 return Err(HashError::InvalidState("attempt to absorb while squeezing"));
265 }
266
267 let mask = (1 << bits) - 1;
268 self.data_queue[self.bits_in_queue >> 3] = data & mask;
269
270 self.bits_in_queue += bits;
272 self.pad_and_switch_to_squeezing_phase();
273 Ok(())
274 }
275
276 pub(super) fn squeeze(&mut self, out: &mut [u8]) -> usize {
279 out.fill(0);
280
281 if !self.squeezing {
282 self.pad_and_switch_to_squeezing_phase();
283 }
284 let output_length = out.len() << 3;
285
286 let mut i = 0;
287 while i < output_length {
288 if self.bits_in_queue == 0 {
289 self.keccak_extract();
290 }
291 let partial_block = self.bits_in_queue.min(output_length - i);
292
293 let length = partial_block >> 3;
294 let start_data_queue = (self.rate - self.bits_in_queue) >> 3;
295 let start_output = i >> 3;
296 out[start_output..(start_output + length)]
297 .copy_from_slice(&self.data_queue[start_data_queue..(start_data_queue + length)]);
298
299 self.bits_in_queue -= partial_block;
300 i += partial_block;
301 }
302 output_length >> 3
303 }
304
305 #[inline(always)]
306 fn keccak_extract(&mut self) {
307 KeccakState::permute(&mut self.state);
308
309 let (chunks, _) = self.data_queue.as_chunks_mut::<8>();
310
311 for (i, chunk) in chunks.iter_mut().enumerate() {
312 *chunk = self.state.buf[i].to_le_bytes();
313 }
314
315 self.bits_in_queue = self.rate;
316 }
317
318 pub(super) fn pad_and_switch_to_squeezing_phase(&mut self) {
319 debug_assert!(self.bits_in_queue < self.rate);
320 self.data_queue[self.bits_in_queue >> 3] |= (1 << (self.bits_in_queue & 7)) as u8;
321
322 self.bits_in_queue += 1;
323 if self.bits_in_queue == self.rate {
324 self.state.absorb(&*self.data_queue);
325 } else {
326 let full = self.bits_in_queue >> 6;
327 let partial = self.bits_in_queue & 63;
328 let mut off = 0;
329
330 for i in 0..full {
331 let mut tmp = [0u8; 8];
332 tmp.copy_from_slice(&self.data_queue[off..off + 8]);
333 self.state.buf[i] ^= u64::from_le_bytes(tmp);
334 off += 8;
335 }
336
337 let mask = (1 << partial) - 1;
338
339 let mut tmp = [0u8; 8];
340 tmp.copy_from_slice(&self.data_queue[off..off + 8]);
341 self.state.buf[full] ^= u64::from_le_bytes(tmp) & mask;
342 }
343
344 self.state.buf[(self.rate - 1) >> 6] ^= 1 << 63;
345
346 self.bits_in_queue = 0;
347 self.squeezing = true;
348 }
349}
350
351const KECCAK_SERIALIZED_LEN: usize = 200 + 192 + 8 + 1;
368
369pub(crate) const SHA3_FAMILY_STATE_LEN: usize = 1 + KECCAK_SERIALIZED_LEN + 10;
383
384pub const SUSPENDED_SHA3_STATE_LEN: usize = 3 + SHA3_FAMILY_STATE_LEN;
386
387impl KeccakInternal {
388 fn serialize_state(&self, out: &mut [u8; KECCAK_SERIALIZED_LEN]) {
391 for i in 0..25 {
393 out[i * 8..(i * 8) + 8].copy_from_slice(&self.state.buf[i].to_le_bytes());
394 }
395
396 out[200..392].copy_from_slice(&*self.data_queue);
398
399 out[392..400].copy_from_slice(&(self.bits_in_queue as u64).to_le_bytes());
401
402 out[400] = self.squeezing as u8;
404 }
405
406 fn from_serialized_state(
413 input: &[u8; KECCAK_SERIALIZED_LEN],
414 rate: usize,
415 ) -> Result<Self, SuspendableError> {
416 let mut buf = Secret::<[u64; 25]>::new();
418 for i in 0..25 {
419 buf[i] = u64::from_le_bytes(input[i * 8..(i * 8) + 8].try_into().unwrap());
420 }
421
422 let mut data_queue = Secret::<[u8; 192]>::new();
424 data_queue.copy_from_slice(&input[200..392]);
425
426 let bits_in_queue = u64::from_le_bytes(input[392..400].try_into().unwrap()) as usize;
432 if bits_in_queue >= rate || (bits_in_queue & 7) != 0 {
433 return Err(SuspendableError::InvalidData);
434 }
435
436 let squeezing = match input[400] {
438 0 => false,
439 1 => true,
440 _ => return Err(SuspendableError::InvalidData),
441 };
442
443 Ok(Self { state: KeccakState { buf, rate }, data_queue, rate, bits_in_queue, squeezing })
444 }
445}
446
447pub(crate) fn serialize_sha3_family_state(
450 out: &mut [u8; SHA3_FAMILY_STATE_LEN],
451 variant_tag: u8,
452 keccak: &KeccakInternal,
453 kdf_key_type: KeyType,
454 kdf_security_strength: SecurityStrength,
455 kdf_entropy: usize,
456) {
457 out[0] = variant_tag;
458
459 let keccak_out: &mut [u8; KECCAK_SERIALIZED_LEN] =
460 (&mut out[1..1 + KECCAK_SERIALIZED_LEN]).try_into().unwrap();
461 keccak.serialize_state(keccak_out);
462
463 out[1 + KECCAK_SERIALIZED_LEN] = kdf_key_type as u8;
464 out[1 + KECCAK_SERIALIZED_LEN + 1] = kdf_security_strength as u8;
465 out[1 + KECCAK_SERIALIZED_LEN + 2..1 + KECCAK_SERIALIZED_LEN + 10]
466 .copy_from_slice(&(kdf_entropy as u64).to_le_bytes());
467}
468
469pub(crate) fn deserialize_sha3_family_state(
476 input: &[u8; SHA3_FAMILY_STATE_LEN],
477 expected_variant_tag: u8,
478 rate: usize,
479) -> Result<(KeccakInternal, KeyType, SecurityStrength, usize), SuspendableError> {
480 if input[0] != expected_variant_tag {
481 return Err(SuspendableError::InvalidData);
482 }
483
484 let keccak_in: &[u8; KECCAK_SERIALIZED_LEN] =
485 input[1..1 + KECCAK_SERIALIZED_LEN].try_into().unwrap();
486 let keccak = KeccakInternal::from_serialized_state(keccak_in, rate)?;
487
488 let kdf_key_type = KeyType::try_from(input[1 + KECCAK_SERIALIZED_LEN])?;
490 let kdf_security_strength = SecurityStrength::try_from(input[1 + KECCAK_SERIALIZED_LEN + 1])?;
491 let kdf_entropy = u64::from_le_bytes(
492 input[1 + KECCAK_SERIALIZED_LEN + 2..1 + KECCAK_SERIALIZED_LEN + 10].try_into().unwrap(),
493 ) as usize;
494
495 Ok((keccak, kdf_key_type, kdf_security_strength, kdf_entropy))
496}
497
498#[cfg(test)]
499mod keccak_tests {
500 use super::*;
501 use bouncycastle_hex as hex;
502
503 #[test]
504 fn test_keccak() {
505 let mut d = KeccakInternal::new(KeccakSize::_256);
506 let m_vec = hex::decode("6d657373616765").unwrap();
507 d.absorb(&m_vec);
508
509 let mut out = [0u8; 32];
510 d.squeeze(&mut out);
511 println!("n1: {:x?}", &out);
512
513 d.squeeze(&mut out);
514 println!("n2: {:x?}", &out);
515 }
516
517 #[test]
522 fn from_serialized_state_rejects_corrupt_bits_in_queue() {
523 let rate = 1600 - ((KeccakSize::_256 as usize) << 1);
524
525 let mut d = KeccakInternal::new(KeccakSize::_256);
527 d.absorb(b"message");
528 assert!(!d.squeezing);
529 let mut good = [0u8; KECCAK_SERIALIZED_LEN];
530 d.serialize_state(&mut good);
531 assert!(KeccakInternal::from_serialized_state(&good, rate).is_ok());
532
533 assert_eq!(good[400], 0, "test setup expects a non-squeezing state");
535 let set_biq = |state: &mut [u8; KECCAK_SERIALIZED_LEN], v: u64| {
536 state[392..400].copy_from_slice(&v.to_le_bytes());
537 };
538
539 let mut corrupt = good;
541 set_biq(&mut corrupt, rate as u64 + 8);
542 assert!(matches!(
543 KeccakInternal::from_serialized_state(&corrupt, rate),
544 Err(SuspendableError::InvalidData)
545 ));
546
547 let mut corrupt = good;
549 set_biq(&mut corrupt, rate as u64);
550 assert!(matches!(
551 KeccakInternal::from_serialized_state(&corrupt, rate),
552 Err(SuspendableError::InvalidData)
553 ));
554
555 let mut corrupt = good;
559 set_biq(&mut corrupt, 9);
560 assert!(matches!(
561 KeccakInternal::from_serialized_state(&corrupt, rate),
562 Err(SuspendableError::InvalidData)
563 ));
564 }
565}