pub(crate) const ROT_ALPHA: u32 = 8;
pub(crate) const ROT_BETA: u32 = 3;
pub(crate) struct SpeckKeySchedule {
k: u32,
l: [u32; 3],
round: u32,
}
impl SpeckKeySchedule {
#[inline]
pub(crate) fn new(key: [u32; 4]) -> Self {
Self {
k: key[0],
l: [key[1], key[2], key[3]],
round: 0,
}
}
}
impl Iterator for SpeckKeySchedule {
type Item = u32;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
let current_key = self.k;
let i = self.round;
let l_idx = (i as usize) % 3;
let new_l = (self.k.wrapping_add(self.l[l_idx].rotate_right(ROT_ALPHA))) ^ i;
let new_k = self.k.rotate_left(ROT_BETA) ^ new_l;
self.l[l_idx] = new_l;
self.k = new_k;
self.round += 1;
Some(current_key)
}
}
#[inline(always)]
pub(crate) fn encrypt_step(k: u32, x: &mut u32, y: &mut u32, z: &mut u32) {
*x = (x.rotate_right(ROT_ALPHA).wrapping_add(*y)) ^ k;
*y = y.rotate_left(ROT_BETA) ^ *x;
*z ^= *y;
}
#[cfg(feature = "cipher")]
#[inline(always)]
pub(crate) fn decrypt_step(k: u32, x: &mut u32, y: &mut u32, z: &mut u32) {
*z ^= *y;
*y = (*y ^ *x).rotate_right(ROT_BETA);
*x = ((*x ^ k).wrapping_sub(*y)).rotate_left(ROT_ALPHA);
}