cryptography/ciphers/
rabbit.rs1const A: [u32; 8] = [
21 0x4D34_D34D,
22 0xD34D_34D3,
23 0x34D3_4D34,
24 0x4D34_D34D,
25 0xD34D_34D3,
26 0x34D3_4D34,
27 0x4D34_D34D,
28 0xD34D_34D3,
29];
30
31#[inline]
32fn load_u16_be(bytes: &[u8]) -> u16 {
33 let mut tmp = [0u8; 2];
34 tmp.copy_from_slice(bytes);
35 u16::from_be_bytes(tmp)
36}
37
38#[inline]
39fn load_u32_be(bytes: &[u8]) -> u32 {
40 let mut tmp = [0u8; 4];
41 tmp.copy_from_slice(bytes);
42 u32::from_be_bytes(tmp)
43}
44
45#[inline]
46fn cat16(hi: u16, lo: u16) -> u32 {
47 (u32::from(hi) << 16) | u32::from(lo)
48}
49
50#[inline]
51fn g_func(x: u32, c: u32) -> u32 {
52 let sum = u64::from(x.wrapping_add(c));
53 let square = sum.wrapping_mul(sum);
54 (square as u32) ^ ((square >> 32) as u32)
55}
56
57#[derive(Clone)]
58struct RabbitCore {
59 x: [u32; 8],
60 c: [u32; 8],
61 carry: u32,
62}
63
64impl RabbitCore {
65 fn from_key(key: &[u8; 16]) -> Self {
66 let mut k = [0u16; 8];
67 for (i, chunk) in key.rchunks_exact(2).enumerate() {
68 k[i] = load_u16_be(chunk);
69 }
70
71 let mut core = Self {
72 x: [
73 cat16(k[1], k[0]),
74 cat16(k[6], k[5]),
75 cat16(k[3], k[2]),
76 cat16(k[0], k[7]),
77 cat16(k[5], k[4]),
78 cat16(k[2], k[1]),
79 cat16(k[7], k[6]),
80 cat16(k[4], k[3]),
81 ],
82 c: [
83 cat16(k[4], k[5]),
84 cat16(k[1], k[2]),
85 cat16(k[6], k[7]),
86 cat16(k[3], k[4]),
87 cat16(k[0], k[1]),
88 cat16(k[5], k[6]),
89 cat16(k[2], k[3]),
90 cat16(k[7], k[0]),
91 ],
92 carry: 0,
93 };
94
95 for _ in 0..4 {
96 core.next_state();
97 }
98
99 for i in 0..8 {
100 core.c[i] ^= core.x[(i + 4) & 7];
101 }
102
103 core
104 }
105
106 fn apply_iv(&mut self, iv: &[u8; 8]) {
107 let v0 = load_u32_be(&iv[4..8]);
108 let v1 = cat16(load_u16_be(&iv[0..2]), load_u16_be(&iv[4..6]));
109 let v2 = load_u32_be(&iv[0..4]);
110 let v3 = cat16(load_u16_be(&iv[2..4]), load_u16_be(&iv[6..8]));
111
112 self.c[0] ^= v0;
113 self.c[1] ^= v1;
114 self.c[2] ^= v2;
115 self.c[3] ^= v3;
116 self.c[4] ^= v0;
117 self.c[5] ^= v1;
118 self.c[6] ^= v2;
119 self.c[7] ^= v3;
120
121 for _ in 0..4 {
122 self.next_state();
123 }
124 }
125
126 #[inline]
127 fn next_state(&mut self) {
128 let old_c = self.c;
129 let mut carry = self.carry;
130 for i in 0..8 {
131 let sum = u64::from(old_c[i]) + u64::from(A[i]) + u64::from(carry);
132 self.c[i] = sum as u32;
133 carry = (sum >> 32) as u32;
134 }
135 self.carry = carry;
136
137 let mut g = [0u32; 8];
138 for (i, gi) in g.iter_mut().enumerate() {
139 *gi = g_func(self.x[i], self.c[i]);
140 }
141
142 self.x[0] = g[0]
143 .wrapping_add(g[7].rotate_left(16))
144 .wrapping_add(g[6].rotate_left(16));
145 self.x[1] = g[1].wrapping_add(g[0].rotate_left(8)).wrapping_add(g[7]);
146 self.x[2] = g[2]
147 .wrapping_add(g[1].rotate_left(16))
148 .wrapping_add(g[0].rotate_left(16));
149 self.x[3] = g[3].wrapping_add(g[2].rotate_left(8)).wrapping_add(g[1]);
150 self.x[4] = g[4]
151 .wrapping_add(g[3].rotate_left(16))
152 .wrapping_add(g[2].rotate_left(16));
153 self.x[5] = g[5].wrapping_add(g[4].rotate_left(8)).wrapping_add(g[3]);
154 self.x[6] = g[6]
155 .wrapping_add(g[5].rotate_left(16))
156 .wrapping_add(g[4].rotate_left(16));
157 self.x[7] = g[7].wrapping_add(g[6].rotate_left(8)).wrapping_add(g[5]);
158 }
159
160 #[inline]
161 fn keystream_block(&mut self) -> [u8; 16] {
162 self.next_state();
163
164 let s = [
165 self.x[0] ^ (self.x[5] >> 16) ^ self.x[3].wrapping_shl(16),
166 self.x[2] ^ (self.x[7] >> 16) ^ self.x[5].wrapping_shl(16),
167 self.x[4] ^ (self.x[1] >> 16) ^ self.x[7].wrapping_shl(16),
168 self.x[6] ^ (self.x[3] >> 16) ^ self.x[1].wrapping_shl(16),
169 ];
170
171 let mut out = [0u8; 16];
174 out[0..4].copy_from_slice(&s[3].to_be_bytes());
175 out[4..8].copy_from_slice(&s[2].to_be_bytes());
176 out[8..12].copy_from_slice(&s[1].to_be_bytes());
177 out[12..16].copy_from_slice(&s[0].to_be_bytes());
178 out
179 }
180}
181
182pub struct Rabbit {
188 core: RabbitCore,
189 block: [u8; 16],
190 offset: usize,
191}
192
193impl Rabbit {
194 #[must_use]
196 pub fn new(key: &[u8; 16], iv: &[u8; 8]) -> Self {
197 let mut core = RabbitCore::from_key(key);
198 core.apply_iv(iv);
199 Self {
200 core,
201 block: [0u8; 16],
202 offset: 16,
203 }
204 }
205
206 #[must_use]
208 pub fn without_iv(key: &[u8; 16]) -> Self {
209 Self {
210 core: RabbitCore::from_key(key),
211 block: [0u8; 16],
212 offset: 16,
213 }
214 }
215
216 pub fn new_wiping(key: &mut [u8; 16], iv: &mut [u8; 8]) -> Self {
218 let out = Self::new(key, iv);
219 crate::ct::zeroize_slice(key.as_mut_slice());
220 crate::ct::zeroize_slice(iv.as_mut_slice());
221 out
222 }
223
224 pub fn without_iv_wiping(key: &mut [u8; 16]) -> Self {
226 let out = Self::without_iv(key);
227 crate::ct::zeroize_slice(key.as_mut_slice());
228 out
229 }
230
231 #[inline]
232 fn refill(&mut self) {
233 self.block = self.core.keystream_block();
234 self.offset = 0;
235 }
236
237 pub fn apply_keystream(&mut self, buf: &mut [u8]) {
239 let mut done = 0usize;
240 while done < buf.len() {
241 if self.offset == 16 {
242 self.refill();
243 }
244 let take = core::cmp::min(16 - self.offset, buf.len() - done);
245 for i in 0..take {
246 buf[done + i] ^= self.block[self.offset + i];
247 }
248 self.offset += take;
249 done += take;
250 }
251 }
252
253 pub fn fill(&mut self, buf: &mut [u8]) {
255 self.apply_keystream(buf);
256 }
257
258 pub fn keystream_block(&mut self) -> [u8; 16] {
260 let mut out = [0u8; 16];
261 self.apply_keystream(&mut out);
262 out
263 }
264}
265
266impl Drop for Rabbit {
267 fn drop(&mut self) {
268 crate::ct::zeroize_slice(self.core.x.as_mut_slice());
269 crate::ct::zeroize_slice(self.core.c.as_mut_slice());
270 self.core.carry = 0;
271 crate::ct::zeroize_slice(self.block.as_mut_slice());
272 self.offset = 0;
273 }
274}
275
276#[cfg(test)]
277mod tests {
278 use super::*;
279
280 fn decode_hex(s: &str) -> Vec<u8> {
281 assert!(
282 s.len().is_multiple_of(2),
283 "hex string must have even length"
284 );
285 let mut out = Vec::with_capacity(s.len() / 2);
286 let bytes = s.as_bytes();
287 for i in (0..bytes.len()).step_by(2) {
288 let hi = (bytes[i] as char).to_digit(16).expect("hex") as u8;
289 let lo = (bytes[i + 1] as char).to_digit(16).expect("hex") as u8;
290 out.push((hi << 4) | lo);
291 }
292 out
293 }
294
295 #[test]
296 fn rabbit_zero_key_rfc_keystream() {
297 let mut rabbit = Rabbit::without_iv(&[0u8; 16]);
298 let mut out = [0u8; 48];
299 rabbit.fill(&mut out);
300 let expected = decode_hex(
301 "B15754F036A5D6ECF56B45261C4AF702\
302 88E8D815C59C0C397B696C4789C68AA7\
303 F416A1C3700CD451DA68D1881673D696",
304 );
305 assert_eq!(out.as_slice(), expected.as_slice());
306 }
307
308 #[test]
309 fn rabbit_key_only_rfc_vector_two() {
310 let key = decode_hex("912813292E3D36FE3BFC62F1DC51C3AC");
311 let mut key_arr = [0u8; 16];
312 key_arr.copy_from_slice(&key);
313 let mut rabbit = Rabbit::without_iv(&key_arr);
314 let mut out = [0u8; 48];
315 rabbit.fill(&mut out);
316 let expected = decode_hex(
317 "3D2DF3C83EF627A1E97FC38487E2519C\
318 F576CD61F4405B8896BF53AA8554FC19\
319 E5547473FBDB43508AE53B20204D4C5E",
320 );
321 assert_eq!(out.as_slice(), expected.as_slice());
322 }
323
324 #[test]
325 fn rabbit_zero_key_zero_iv_rfc_keystream() {
326 let mut rabbit = Rabbit::new(&[0u8; 16], &[0u8; 8]);
327 let mut out = [0u8; 48];
328 rabbit.fill(&mut out);
329 let expected = decode_hex(
330 "C6A7275EF85495D87CCD5D376705B7ED\
331 5F29A6AC04F5EFD47B8F293270DC4A8D\
332 2ADE822B29DE6C1EE52BDB8A47BF8F66",
333 );
334 assert_eq!(out.as_slice(), expected.as_slice());
335 }
336
337 #[test]
338 fn rabbit_roundtrip() {
339 let key = [0x42u8; 16];
340 let iv = [0x24u8; 8];
341 let plain = *b"rabbit stream demo";
342
343 let mut enc = Rabbit::new(&key, &iv);
344 let mut ct = plain;
345 enc.apply_keystream(&mut ct);
346
347 let mut dec = Rabbit::new(&key, &iv);
348 dec.apply_keystream(&mut ct);
349
350 assert_eq!(ct, plain);
351 }
352}