1use buffer::{BufferResult, RefReadBuffer, RefWriteBuffer};
9use symmetriccipher::{Encryptor, Decryptor, SynchronousStreamCipher, SymmetricCipherError};
10use cryptoutil::{read_u32_le, symm_enc_or_dec, write_u32_le};
11
12use std::ptr;
13
14
15#[derive(Copy)]
16pub struct Hc128 {
17 p: [u32; 512],
18 q: [u32; 512],
19 cnt: usize,
20 output: [u8; 4],
21 output_index: usize
22}
23
24impl Clone for Hc128 { fn clone(&self) -> Hc128 { *self } }
25
26impl Hc128 {
27 pub fn new(key: &[u8], nonce: &[u8]) -> Hc128 {
28 assert!(key.len() == 16);
29 assert!(nonce.len() == 16);
30 let mut hc128 = Hc128 { p: [0; 512], q: [0; 512], cnt: 0, output: [0; 4], output_index: 0 };
31 hc128.init(&key, &nonce);
32
33 hc128
34 }
35
36 fn init(&mut self, key : &[u8], nonce : &[u8]) {
37 self.cnt = 0;
38
39 let mut w : [u32; 1280] = [0; 1280];
40
41 for i in 0..16 {
42 w[i >> 2] |= (key[i] as u32) << (8 * (i & 0x3));
43 }
44 unsafe {
45 ptr::copy_nonoverlapping(w.as_ptr(), w.as_mut_ptr().offset(4), 4);
46 }
47
48 for i in 0..nonce.len() & 16 {
49 w[(i >> 2) + 8] |= (nonce[i] as u32) << (8 * (i & 0x3));
50 }
51 unsafe {
52 ptr::copy_nonoverlapping(w.as_ptr().offset(8), w.as_mut_ptr().offset(12), 4);
53 }
54
55 for i in 16..1280 {
56 w[i] = f2(w[i - 2]).wrapping_add(w[i - 7]).wrapping_add(f1(w[i - 15])).wrapping_add(w[i - 16]).wrapping_add(i as u32);
57 }
58
59 unsafe {
61 ptr::copy_nonoverlapping(w.as_ptr().offset(256), self.p.as_mut_ptr(), 512);
62 ptr::copy_nonoverlapping(w.as_ptr().offset(768), self.q.as_mut_ptr(), 512);
63 }
64
65 for i in 0..512 {
66 self.p[i] = self.step();
67 }
68 for i in 0..512 {
69 self.q[i] = self.step();
70 }
71
72 self.cnt = 0;
73 }
74
75 fn step(&mut self) -> u32 {
76 let j : usize = self.cnt & 0x1FF;
77
78 let dim_j3 : usize = (j.wrapping_sub(3)) & 0x1FF;
80 let dim_j10 : usize = (j.wrapping_sub(10)) & 0x1FF;
81 let dim_j511 : usize = (j.wrapping_sub(511)) & 0x1FF;
82 let dim_j12 : usize = (j.wrapping_sub(12)) & 0x1FF;
83
84 let ret : u32;
85
86 if self.cnt < 512 {
87 self.p[j] = self.p[j].wrapping_add(self.p[dim_j3].rotate_right(10) ^ self.p[dim_j511].rotate_right(23)).wrapping_add(self.p[dim_j10].rotate_right(8));
88 ret = (self.q[(self.p[dim_j12] & 0xFF) as usize].wrapping_add(self.q[(((self.p[dim_j12] >> 16) & 0xFF) + 256) as usize])) ^ self.p[j];
89 } else {
90 self.q[j] = self.q[j].wrapping_add(self.q[dim_j3].rotate_left(10) ^ self.q[dim_j511].rotate_left(23)).wrapping_add(self.q[dim_j10].rotate_left(8));
91 ret = (self.p[(self.q[dim_j12] & 0xFF) as usize].wrapping_add(self.p[(((self.q[dim_j12] >> 16) & 0xFF) + 256) as usize])) ^ self.q[j];
92 }
93
94 self.cnt = (self.cnt + 1) & 0x3FF;
95 ret
96 }
97
98 fn next(&mut self) -> u8 {
99 if self.output_index == 0 {
100 let step = self.step();
101 write_u32_le(&mut self.output, step);
102 }
103 let ret = self.output[self.output_index];
104 self.output_index = (self.output_index + 1) & 0x3;
105
106 ret
107 }
108}
109
110fn f1(x: u32) -> u32 {
111 let ret : u32 = x.rotate_right(7) ^ x.rotate_right(18) ^ (x >> 3);
112 ret
113}
114
115fn f2(x: u32) -> u32 {
116 let ret : u32 = x.rotate_right(17) ^ x.rotate_right(19) ^ (x >> 10);
117 ret
118}
119
120impl SynchronousStreamCipher for Hc128 {
121 fn process(&mut self, input: &[u8], output: &mut [u8]) {
122 assert!(input.len() == output.len());
123
124 if input.len() <= 4 {
125 for (inb, outb) in input.iter().zip(output.iter_mut()) {
127 *outb = *inb ^ self.next();
128 }
129 } else {
130 let mut data_index = 0;
131 let data_index_end = data_index + input.len();
132
133 while self.output_index > 0 && data_index < data_index_end {
136 output[data_index] = input[data_index] ^ self.next();
137 data_index += 1;
138 }
139
140 while data_index + 4 <= data_index_end {
144 let data_index_inc = data_index + 4;
145
146 let input_u32 = read_u32_le(&input[data_index..data_index_inc]);
148 let xored = input_u32 ^ self.step();
150 write_u32_le(&mut output[data_index..data_index_inc], xored);
152
153 data_index = data_index_inc;
154 }
155
156 while data_index < data_index_end {
159 output[data_index] = input[data_index] ^ self.next();
160 data_index += 1;
161 }
162 }
163 }
164}
165
166impl Encryptor for Hc128 {
167 fn encrypt(&mut self, input: &mut RefReadBuffer, output: &mut RefWriteBuffer, _: bool)
168 -> Result<BufferResult, SymmetricCipherError> {
169 symm_enc_or_dec(self, input, output)
170 }
171}
172
173impl Decryptor for Hc128 {
174 fn decrypt(&mut self, input: &mut RefReadBuffer, output: &mut RefWriteBuffer, _: bool)
175 -> Result<BufferResult, SymmetricCipherError> {
176 symm_enc_or_dec(self, input, output)
177 }
178}
179
180
181#[cfg(test)]
182mod test {
183 use hc128::Hc128;
184 use symmetriccipher::SynchronousStreamCipher;
185 use serialize::hex::{FromHex};
186
187 #[test]
190 fn test_hc128_ecrypt_set_2_vector_0() {
191 let key = "00000000000000000000000000000000".from_hex().unwrap();
192 let nonce = "00000000000000000000000000000000".from_hex().unwrap();
193
194 let input = [0u8; 64];
195 let expected_output_hex = "82001573A003FD3B7FD72FFB0EAF63AAC62F12DEB629DCA72785A66268EC758B1EDB36900560898178E0AD009ABF1F491330DC1C246E3D6CB264F6900271D59C";
196 let expected_output = expected_output_hex.from_hex().unwrap();
197
198 let mut output = [0u8; 64];
199
200 let mut hc128 = Hc128::new(key.as_ref(), nonce.as_ref());
201 hc128.process(&input, &mut output);
202 let result: &[u8] = output.as_ref();
203 let expected: &[u8] = expected_output.as_ref();
204 assert!(result == expected); }
205
206 #[test]
207 fn test_hc128_ecrypt_set_6_vector_1() {
208 let key = "0558ABFE51A4F74A9DF04396E93C8FE2".from_hex().unwrap();
209 let nonce = "167DE44BB21980E74EB51C83EA51B81F".from_hex().unwrap();
210
211 let input = [0u8; 64];
212 let expected_output_hex = "4F864BF3C96D0363B1903F0739189138F6ED2BC0AF583FEEA0CEA66BA7E06E63FB28BF8B3CA0031D24ABB511C57DD17BFC2861C32400072CB680DF2E58A5CECC";
213 let expected_output = expected_output_hex.from_hex().unwrap();
214
215 let mut output = [0u8; 64];
216
217 let mut hc128 = Hc128::new(key.as_ref(), nonce.as_ref());
218 hc128.process(&input, &mut output);
219 let result: &[u8] = output.as_ref();
220 let expected: &[u8] = expected_output.as_ref();
221 assert!(result == expected);
222 }
223
224 #[test]
225 fn test_hc128_ecrypt_set_6_vector_2() {
226 let key = "0A5DB00356A9FC4FA2F5489BEE4194E7".from_hex().unwrap();
227 let nonce = "1F86ED54BB2289F057BE258CF35AC128".from_hex().unwrap();
228
229 let input = [0u8; 64];
230 let expected_output_hex = "82168AB0023B79AAF1E6B4D823855E14A7084378036A951B1CFEF35173875ED86CB66AB8410491A08582BE40080C3102193BA567F9E95D096C3CC60927DD7901";
231 let expected_output = expected_output_hex.from_hex().unwrap();
232
233 let mut output = [0u8; 64];
234
235 let mut hc128 = Hc128::new(key.as_ref(), nonce.as_ref());
236 hc128.process(&input, &mut output);
237 let result: &[u8] = output.as_ref();
238 let expected: &[u8] = expected_output.as_ref();
239 assert!(result == expected);
240 }
241
242 #[test]
243 fn test_hc128_ecrypt_set_6_vector_3() {
244 let key = "0F62B5085BAE0154A7FA4DA0F34699EC".from_hex().unwrap();
245 let nonce = "288FF65DC42B92F960C72E95FC63CA31".from_hex().unwrap();
246
247 let input = [0u8; 64];
248 let expected_output_hex = "1CD8AEDDFE52E217E835D0B7E84E2922D04B1ADBCA53C4522B1AA604C42856A90AF83E2614BCE65C0AECABDD8975B55700D6A26D52FFF0888DA38F1DE20B77B7";
249 let expected_output = expected_output_hex.from_hex().unwrap();
250
251 let mut output = [0u8; 64];
252
253 let mut hc128 = Hc128::new(&key, &nonce);
254 hc128.process(&input, &mut output);
255 assert!(&output[..] == &expected_output[..]);
256 }
257}
258
259#[cfg(all(test, feature = "with-bench"))]
260mod bench {
261 use test::Bencher;
262 use symmetriccipher::SynchronousStreamCipher;
263 use hc128::Hc128;
264
265 #[bench]
266 pub fn hc128_10(bh: & mut Bencher) {
267 let mut hc128 = Hc128::new(&[0; 16], &[0; 16]);
268 let input = [1u8; 10];
269 let mut output = [0u8; 10];
270 bh.iter( || {
271 hc128.process(&input, &mut output);
272 });
273 bh.bytes = input.len() as u64;
274 }
275
276 #[bench]
277 pub fn hc128_1k(bh: & mut Bencher) {
278 let mut hc128 = Hc128::new(&[0; 16], &[0; 16]);
279 let input = [1u8; 1024];
280 let mut output = [0u8; 1024];
281 bh.iter( || {
282 hc128.process(&input, &mut output);
283 });
284 bh.bytes = input.len() as u64;
285 }
286
287 #[bench]
288 pub fn hc128_64k(bh: & mut Bencher) {
289 let mut hc128 = Hc128::new(&[0; 16], &[0; 16]);
290 let input = [1u8; 65536];
291 let mut output = [0u8; 65536];
292 bh.iter( || {
293 hc128.process(&input, &mut output);
294 });
295 bh.bytes = input.len() as u64;
296 }
297}