1use {
2 crate::{error::Error, word::Word},
3 num::integer::div_ceil,
4 std::{cmp::max, mem::size_of},
5};
6
7pub fn encrypt_block<W: Word>(
23 expanded_key: &[W],
24 mut block: [W; 2], ) -> Result<[W; 2], Error> {
26 let num_rounds = (expanded_key.len() / 2) - 1;
27 block[0] = block[0].wrapping_add(&expanded_key[0]);
28 block[1] = block[1].wrapping_add(&expanded_key[1]);
29
30 for i in 1..=num_rounds {
31 let rotation =
32 block[1].to_u128().ok_or(Error::InvalidWordSize)? % W::BITS as u128;
33 block[0] = (block[0].bitxor(block[1]))
34 .rotate_left(rotation as u32)
35 .wrapping_add(&expanded_key[2 * i]);
36
37 let rotation =
38 block[0].to_u128().ok_or(Error::InvalidWordSize)? % W::BITS as u128;
39 block[1] = (block[1].bitxor(block[0]))
40 .rotate_left(rotation as u32)
41 .wrapping_add(&expanded_key[2 * i + 1]);
42 }
43
44 Ok(block)
45}
46
47pub fn decrypt_block<W: Word>(
57 expanded_key: &[W],
58 mut block: [W; 2],
59) -> Result<[W; 2], Error> {
60 let num_rounds = (expanded_key.len() / 2) - 1;
61
62 for i in (1..=num_rounds).rev() {
63 let rotation =
64 block[0].to_u128().ok_or(Error::InvalidWordSize)? % W::BITS as u128;
65
66 block[1] = (block[1].wrapping_sub(&expanded_key[2 * i + 1]))
67 .rotate_right(rotation as u32)
68 .bitxor(block[0]);
69
70 let rotation =
71 block[1].to_u128().ok_or(Error::InvalidWordSize)? % W::BITS as u128;
72 block[0] = (block[0].wrapping_sub(&expanded_key[2 * i]))
73 .rotate_right(rotation as u32)
74 .bitxor(block[1]);
75 }
76
77 block[1] = block[1].wrapping_sub(&expanded_key[1]);
78 block[0] = block[0].wrapping_sub(&expanded_key[0]);
79
80 Ok(block)
81}
82
83pub fn expand_key<W: Word>(key: &[u8], rounds: usize) -> Result<Vec<W>, Error> {
85 const MAX_ROUNDS: usize = 256;
87 const MAX_KEY_SIZE: usize = 256;
88
89 if key.len() > MAX_KEY_SIZE {
90 return Err(Error::InvalidKeySize);
91 }
92
93 if rounds > MAX_ROUNDS {
94 return Err(Error::InvalidRoundsCount);
95 }
96
97 let mut words: Vec<W> = key_to_words(key);
99
100 let mut subkeys: Vec<W> = initialize_subkeys(rounds);
105
106 let mut i = 0;
116 let mut j = 0;
117 let mut a = W::zero();
118 let mut b = W::zero();
119
120 let iters = max(subkeys.len(), words.len()) * 3;
122
123 for _ in 0..iters {
124 subkeys[i] = subkeys[i].wrapping_add(&a).wrapping_add(&b).rotate_left(3);
125 a = subkeys[i];
126
127 let rotation =
129 a.wrapping_add(&b).to_u128().ok_or(Error::InvalidWordSize)?
130 % W::BITS as u128;
131
132 words[j] = words[j]
133 .wrapping_add(&a)
134 .wrapping_add(&b)
135 .rotate_left(rotation as u32);
136 b = words[j];
137
138 i = (i + 1) % subkeys.len();
139 j = (j + 1) % words.len();
140 }
141
142 Ok(subkeys)
143}
144
145fn key_to_words<W: Word>(key: &[u8]) -> Vec<W> {
151 let words_len = div_ceil(max(key.len(), 1), size_of::<W>());
152 let mut words = vec![W::zero(); words_len];
153 for i in (0..key.len()).rev() {
154 let word_index = i / size_of::<W>();
155 let word = W::from(key[i]).expect("minimum word size is 8");
156 words[word_index] = words[word_index].rotate_left(8).wrapping_add(&word);
157 }
158 words
159}
160
161fn initialize_subkeys<W: Word>(rounds: usize) -> Vec<W> {
166 let subkey_count = 2 * (rounds + 1); let mut subkeys = vec![W::zero(); subkey_count];
168
169 subkeys[0] = W::P;
170 for i in 1..subkey_count {
171 subkeys[i] = subkeys[i - 1].wrapping_add(&W::Q);
172 }
173
174 subkeys
175}