1#![no_std]
2#![forbid(unsafe_code)]
3
4pub mod cipher_modes;
5
6use crate::cipher_modes::ECB;
7
8const ALPHA: u32 = 8;
17const BETA: u32 = 3;
18const ROUNDS: usize = 32;
19
20#[inline(always)]
26fn round(x: &mut u64, y: &mut u64, k: &u64) {
27 *x = x.rotate_right(ALPHA).wrapping_add(*y) ^ k;
28 *y = y.rotate_left(BETA) ^ *x;
29}
30
31#[inline(always)]
38fn inv_round(x: &mut u64, y: &mut u64, k: &u64) {
39 *y = (*y ^ *x).rotate_right(BETA);
40 *x = (*x ^ *k).wrapping_sub(*y).rotate_left(ALPHA);
41}
42
43#[inline(always)]
45fn key_schedule(k1: &mut u64, k2: &mut u64) -> [u64; ROUNDS] {
46 let mut schedule = [0u64; ROUNDS];
47 for i in 0..ROUNDS as u64 {
48 schedule[i as usize] = *k2;
49 round(k1, k2, &i)
50 }
51 schedule
52}
53
54pub struct Speck([u64; ROUNDS]);
59
60impl Speck {
61 pub fn new(key: &u128) -> Self {
62 let mut k1 = (key >> 64) as u64;
63 let mut k2 = *key as u64;
64
65 Speck(key_schedule(&mut k1, &mut k2))
66 }
67
68 pub(crate) fn encrypt(&self, plaintext: &u128) -> u128 {
74 let mut chunk_1 = (plaintext >> 64) as u64;
76 let mut chunk_2 = *plaintext as u64;
77
78 for round_key in &self.0 {
80 round(&mut chunk_1, &mut chunk_2, round_key);
81 }
82
83 chunk_2 as u128 | (chunk_1 as u128) << 64
85 }
86
87 pub(crate) fn decrypt(&self, ciphertext: &u128) -> u128 {
91 let mut chunk_1 = (ciphertext >> 64) as u64;
93 let mut chunk_2 = *ciphertext as u64;
94
95 for round_key in self.0.iter().rev() {
97 inv_round(&mut chunk_1, &mut chunk_2, round_key);
98 }
99
100 chunk_2 as u128 | (chunk_1 as u128) << 64
102 }
103}
104
105impl ECB for Speck {
106 fn encrypt(&self, plaintext: &u128) -> u128 {
107 self.encrypt(plaintext)
108 }
109
110 fn decrypt(&self, ciphertext: &u128) -> u128 {
111 self.decrypt(ciphertext)
112 }
113}
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118
119 #[test]
120 fn test_speck128_128_encryption_and_decryption() {
121 let key: u128 = 0x0f0e0d0c0b0a09080706050403020100;
123 let plaintext: u128 = 0x6c617669757165207469206564616d20;
124 let ciphertext: u128 = 0xa65d9851797832657860fedf5c570d18;
125
126 let speck = Speck::new(&key);
127 assert_eq!(speck.encrypt(&plaintext), ciphertext);
128 assert_eq!(speck.decrypt(&ciphertext), plaintext);
129 }
130
131 #[test]
132 fn test_speck_ecb_mode() {
133 let key: u128 = 0x0f0e0d0c0b0a09080706050403020100;
134 let plaintext: u128 = 0x6c617669757165207469206564616d20;
135 let ciphertext: u128 = 0xa65d9851797832657860fedf5c570d18;
136
137 let speck = Speck::new(&key);
138 assert_eq!(<Speck as ECB>::encrypt(&speck, &plaintext), ciphertext);
139 assert_eq!(<Speck as ECB>::decrypt(&speck, &ciphertext), plaintext);
140 }
141}