1use aes::hazmat;
2use aes::Block;
3use std::net::IpAddr;
4
5use crate::aes::*;
6use crate::common::{bytes_to_ip, ip_to_bytes};
7
8pub struct IpcryptNd {
13 round_keys: [Block; 11],
14}
15
16impl IpcryptNd {
17 pub const KEY_BYTES: usize = 16;
19 pub const TWEAK_BYTES: usize = 8;
21 pub const NDIP_BYTES: usize = Self::TWEAK_BYTES + 16;
23
24 #[cfg(feature = "random")]
26 pub fn generate_key() -> [u8; Self::KEY_BYTES] {
27 rand::random()
28 }
29
30 pub fn new(key: [u8; Self::KEY_BYTES]) -> Self {
36 let round_keys = Self::expand_key(&key);
37 Self { round_keys }
38 }
39
40 #[cfg(feature = "random")]
42 pub fn new_random() -> Self {
43 Self::new(Self::generate_key())
44 }
45
46 #[cfg(feature = "random")]
48 pub fn generate_tweak() -> [u8; Self::TWEAK_BYTES] {
49 rand::random()
50 }
51
52 fn pad_tweak(tweak: &[u8; Self::TWEAK_BYTES]) -> Block {
55 let mut padded = Block::default();
56 for i in (0..8).step_by(2) {
57 padded[i * 2] = tweak[i];
58 padded[i * 2 + 1] = tweak[i + 1];
59 }
60 padded
61 }
62
63 fn encrypt_ip16(&self, ip: &mut [u8; 16], tweak: &[u8; Self::TWEAK_BYTES]) {
68 let padded_tweak = Self::pad_tweak(tweak);
69 let mut block = Block::from(*ip);
70
71 for i in 0..16 {
73 block[i] ^= self.round_keys[0][i] ^ padded_tweak[i];
74 }
75
76 for round in 1..10 {
78 let mut tweaked_key = self.round_keys[round];
80 for i in 0..16 {
81 tweaked_key[i] ^= padded_tweak[i];
82 }
83 hazmat::cipher_round(&mut block, &tweaked_key);
84 }
85
86 for i in 0..16 {
89 block[i] = SBOX[block[i] as usize];
90 }
91
92 shift_rows(&mut block);
94
95 for i in 0..16 {
97 block[i] ^= self.round_keys[10][i] ^ padded_tweak[i];
98 }
99
100 *ip = block.into();
101 }
102
103 fn decrypt_ip16(&self, ip: &mut [u8; 16], tweak: &[u8; Self::TWEAK_BYTES]) {
108 let padded_tweak = Self::pad_tweak(tweak);
109 let mut block = Block::from(*ip);
110
111 for i in 0..16 {
113 block[i] ^= self.round_keys[10][i] ^ padded_tweak[i];
114 }
115
116 inv_shift_rows(&mut block);
118
119 for i in 0..16 {
121 block[i] = INV_SBOX[block[i] as usize];
122 }
123
124 for round in (1..10).rev() {
126 for i in 0..16 {
128 block[i] ^= self.round_keys[round][i] ^ padded_tweak[i];
129 }
130
131 inv_mix_columns(&mut block);
133
134 inv_shift_rows(&mut block);
136
137 for i in 0..16 {
139 block[i] = INV_SBOX[block[i] as usize];
140 }
141 }
142
143 for i in 0..16 {
145 block[i] ^= self.round_keys[0][i] ^ padded_tweak[i];
146 }
147
148 *ip = block.into();
149 }
150
151 pub fn encrypt_ipaddr(
161 &self,
162 ip: IpAddr,
163 tweak: Option<[u8; Self::TWEAK_BYTES]>,
164 ) -> [u8; Self::NDIP_BYTES] {
165 let mut out = [0u8; Self::NDIP_BYTES];
166 #[cfg(feature = "random")]
167 let tweak = tweak.unwrap_or_else(Self::generate_tweak);
168 #[cfg(not(feature = "random"))]
169 let tweak = tweak.expect("tweak must be provided when random feature is disabled");
170 let mut bytes = ip_to_bytes(ip);
171 self.encrypt_ip16(&mut bytes, &tweak);
172 out[0..Self::TWEAK_BYTES].copy_from_slice(&tweak);
173 out[Self::TWEAK_BYTES..].copy_from_slice(&bytes);
174 out
175 }
176
177 pub fn decrypt_ipaddr(&self, encrypted: &[u8; Self::NDIP_BYTES]) -> IpAddr {
186 let mut tweak = [0u8; Self::TWEAK_BYTES];
187 tweak.copy_from_slice(&encrypted[0..Self::TWEAK_BYTES]);
188 let mut bytes = [0u8; 16];
189 bytes.copy_from_slice(&encrypted[Self::TWEAK_BYTES..]);
190 self.decrypt_ip16(&mut bytes, &tweak);
191 bytes_to_ip(bytes)
192 }
193
194 fn expand_key(key: &[u8; Self::KEY_BYTES]) -> [Block; 11] {
199 let mut round_keys = [Block::default(); 11];
200
201 round_keys[0] = Block::from(*key);
203
204 for i in 1..11 {
206 let prev_key = round_keys[i - 1];
207 let mut next_key = Block::default();
208
209 let t0 = prev_key[13];
212 let t1 = prev_key[14];
213 let t2 = prev_key[15];
214 let t3 = prev_key[12];
215 let s0 = SBOX[t0 as usize];
216 let s1 = SBOX[t1 as usize];
217 let s2 = SBOX[t2 as usize];
218 let s3 = SBOX[t3 as usize];
219
220 next_key[0] = prev_key[0] ^ s0 ^ RCON[i - 1];
222 next_key[1] = prev_key[1] ^ s1;
223 next_key[2] = prev_key[2] ^ s2;
224 next_key[3] = prev_key[3] ^ s3;
225
226 next_key[4] = next_key[0] ^ prev_key[4];
228 next_key[5] = next_key[1] ^ prev_key[5];
229 next_key[6] = next_key[2] ^ prev_key[6];
230 next_key[7] = next_key[3] ^ prev_key[7];
231
232 next_key[8] = next_key[4] ^ prev_key[8];
233 next_key[9] = next_key[5] ^ prev_key[9];
234 next_key[10] = next_key[6] ^ prev_key[10];
235 next_key[11] = next_key[7] ^ prev_key[11];
236
237 next_key[12] = next_key[8] ^ prev_key[12];
238 next_key[13] = next_key[9] ^ prev_key[13];
239 next_key[14] = next_key[10] ^ prev_key[14];
240 next_key[15] = next_key[11] ^ prev_key[15];
241
242 round_keys[i] = next_key;
243 }
244
245 round_keys
246 }
247}
248
249#[cfg(test)]
250mod tests {
251 use super::*;
252 use ct_codecs::{Decoder as _, Encoder as _, Hex};
253 use std::str::FromStr;
254
255 #[test]
256 fn test_nd_vectors() {
257 let test_vectors = vec![
258 (
259 "0123456789abcdeffedcba9876543210",
261 "0.0.0.0",
262 "08e0c289bff23b7c",
263 "08e0c289bff23b7cb349aadfe3bcef56221c384c7c217b16",
264 ),
265 (
266 "1032547698badcfeefcdab8967452301",
268 "192.0.2.1",
269 "21bd1834bc088cd2",
270 "21bd1834bc088cd2e5e1fe55f95876e639faae2594a0caad",
271 ),
272 (
273 "2b7e151628aed2a6abf7158809cf4f3c",
275 "2001:db8::1",
276 "b4ecbe30b70898d7",
277 "b4ecbe30b70898d7553ac8974d1b4250eafc4b0aa1f80c96",
278 ),
279 ];
280
281 for (key_hex, input_ip, tweak_hex, expected_output) in test_vectors {
282 let key_vec = Hex::decode_to_vec(key_hex.as_bytes(), None).unwrap();
284 let mut key = [0u8; IpcryptNd::KEY_BYTES];
285 key.copy_from_slice(&key_vec);
286
287 let tweak_vec = Hex::decode_to_vec(tweak_hex.as_bytes(), None).unwrap();
289 let mut tweak = [0u8; IpcryptNd::TWEAK_BYTES];
290 tweak.copy_from_slice(&tweak_vec);
291
292 let ipcrypt = IpcryptNd::new(key);
294
295 let ip = IpAddr::from_str(input_ip).unwrap();
297
298 let encrypted = ipcrypt.encrypt_ipaddr(ip, Some(tweak));
300
301 let encrypted_hex = Hex::encode_to_string(encrypted).unwrap();
303 assert_eq!(encrypted_hex, expected_output);
304
305 let decrypted = ipcrypt.decrypt_ipaddr(&encrypted);
307 assert_eq!(decrypted, ip);
308 }
309 }
310}