crypto/
sosemanuk.rs

1// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
2// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
3// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
4// option. This file may not be copied, modified, or distributed
5// except according to those terms.
6
7
8use buffer::{BufferResult, RefReadBuffer, RefWriteBuffer};
9use symmetriccipher::{Encryptor, Decryptor, SynchronousStreamCipher, SymmetricCipherError};
10use cryptoutil::{read_u32_le, symm_enc_or_dec, write_u32v_le};
11
12use cryptoutil::copy_memory;
13
14
15const ALPHA_MUL_TABLE : [u32; 256] =
16[
17    0x00000000, 0xE19FCF13, 0x6B973726, 0x8A08F835,
18    0xD6876E4C, 0x3718A15F, 0xBD10596A, 0x5C8F9679,
19    0x05A7DC98, 0xE438138B, 0x6E30EBBE, 0x8FAF24AD,
20    0xD320B2D4, 0x32BF7DC7, 0xB8B785F2, 0x59284AE1,
21    0x0AE71199, 0xEB78DE8A, 0x617026BF, 0x80EFE9AC,
22    0xDC607FD5, 0x3DFFB0C6, 0xB7F748F3, 0x566887E0,
23    0x0F40CD01, 0xEEDF0212, 0x64D7FA27, 0x85483534,
24    0xD9C7A34D, 0x38586C5E, 0xB250946B, 0x53CF5B78,
25    0x1467229B, 0xF5F8ED88, 0x7FF015BD, 0x9E6FDAAE,
26    0xC2E04CD7, 0x237F83C4, 0xA9777BF1, 0x48E8B4E2,
27    0x11C0FE03, 0xF05F3110, 0x7A57C925, 0x9BC80636,
28    0xC747904F, 0x26D85F5C, 0xACD0A769, 0x4D4F687A,
29    0x1E803302, 0xFF1FFC11, 0x75170424, 0x9488CB37,
30    0xC8075D4E, 0x2998925D, 0xA3906A68, 0x420FA57B,
31    0x1B27EF9A, 0xFAB82089, 0x70B0D8BC, 0x912F17AF,
32    0xCDA081D6, 0x2C3F4EC5, 0xA637B6F0, 0x47A879E3,
33    0x28CE449F, 0xC9518B8C, 0x435973B9, 0xA2C6BCAA,
34    0xFE492AD3, 0x1FD6E5C0, 0x95DE1DF5, 0x7441D2E6,
35    0x2D699807, 0xCCF65714, 0x46FEAF21, 0xA7616032,
36    0xFBEEF64B, 0x1A713958, 0x9079C16D, 0x71E60E7E,
37    0x22295506, 0xC3B69A15, 0x49BE6220, 0xA821AD33,
38    0xF4AE3B4A, 0x1531F459, 0x9F390C6C, 0x7EA6C37F,
39    0x278E899E, 0xC611468D, 0x4C19BEB8, 0xAD8671AB,
40    0xF109E7D2, 0x109628C1, 0x9A9ED0F4, 0x7B011FE7,
41    0x3CA96604, 0xDD36A917, 0x573E5122, 0xB6A19E31,
42    0xEA2E0848, 0x0BB1C75B, 0x81B93F6E, 0x6026F07D,
43    0x390EBA9C, 0xD891758F, 0x52998DBA, 0xB30642A9,
44    0xEF89D4D0, 0x0E161BC3, 0x841EE3F6, 0x65812CE5,
45    0x364E779D, 0xD7D1B88E, 0x5DD940BB, 0xBC468FA8,
46    0xE0C919D1, 0x0156D6C2, 0x8B5E2EF7, 0x6AC1E1E4,
47    0x33E9AB05, 0xD2766416, 0x587E9C23, 0xB9E15330,
48    0xE56EC549, 0x04F10A5A, 0x8EF9F26F, 0x6F663D7C,
49    0x50358897, 0xB1AA4784, 0x3BA2BFB1, 0xDA3D70A2,
50    0x86B2E6DB, 0x672D29C8, 0xED25D1FD, 0x0CBA1EEE,
51    0x5592540F, 0xB40D9B1C, 0x3E056329, 0xDF9AAC3A,
52    0x83153A43, 0x628AF550, 0xE8820D65, 0x091DC276,
53    0x5AD2990E, 0xBB4D561D, 0x3145AE28, 0xD0DA613B,
54    0x8C55F742, 0x6DCA3851, 0xE7C2C064, 0x065D0F77,
55    0x5F754596, 0xBEEA8A85, 0x34E272B0, 0xD57DBDA3,
56    0x89F22BDA, 0x686DE4C9, 0xE2651CFC, 0x03FAD3EF,
57    0x4452AA0C, 0xA5CD651F, 0x2FC59D2A, 0xCE5A5239,
58    0x92D5C440, 0x734A0B53, 0xF942F366, 0x18DD3C75,
59    0x41F57694, 0xA06AB987, 0x2A6241B2, 0xCBFD8EA1,
60    0x977218D8, 0x76EDD7CB, 0xFCE52FFE, 0x1D7AE0ED,
61    0x4EB5BB95, 0xAF2A7486, 0x25228CB3, 0xC4BD43A0,
62    0x9832D5D9, 0x79AD1ACA, 0xF3A5E2FF, 0x123A2DEC,
63    0x4B12670D, 0xAA8DA81E, 0x2085502B, 0xC11A9F38,
64    0x9D950941, 0x7C0AC652, 0xF6023E67, 0x179DF174,
65    0x78FBCC08, 0x9964031B, 0x136CFB2E, 0xF2F3343D,
66    0xAE7CA244, 0x4FE36D57, 0xC5EB9562, 0x24745A71,
67    0x7D5C1090, 0x9CC3DF83, 0x16CB27B6, 0xF754E8A5,
68    0xABDB7EDC, 0x4A44B1CF, 0xC04C49FA, 0x21D386E9,
69    0x721CDD91, 0x93831282, 0x198BEAB7, 0xF81425A4,
70    0xA49BB3DD, 0x45047CCE, 0xCF0C84FB, 0x2E934BE8,
71    0x77BB0109, 0x9624CE1A, 0x1C2C362F, 0xFDB3F93C,
72    0xA13C6F45, 0x40A3A056, 0xCAAB5863, 0x2B349770,
73    0x6C9CEE93, 0x8D032180, 0x070BD9B5, 0xE69416A6,
74    0xBA1B80DF, 0x5B844FCC, 0xD18CB7F9, 0x301378EA,
75    0x693B320B, 0x88A4FD18, 0x02AC052D, 0xE333CA3E,
76    0xBFBC5C47, 0x5E239354, 0xD42B6B61, 0x35B4A472,
77    0x667BFF0A, 0x87E43019, 0x0DECC82C, 0xEC73073F,
78    0xB0FC9146, 0x51635E55, 0xDB6BA660, 0x3AF46973,
79    0x63DC2392, 0x8243EC81, 0x084B14B4, 0xE9D4DBA7,
80    0xB55B4DDE, 0x54C482CD, 0xDECC7AF8, 0x3F53B5EB
81];
82
83const ALPHA_DIV_TABLE : [u32; 256] =
84[
85    0x00000000, 0x180F40CD, 0x301E8033, 0x2811C0FE,
86    0x603CA966, 0x7833E9AB, 0x50222955, 0x482D6998,
87    0xC078FBCC, 0xD877BB01, 0xF0667BFF, 0xE8693B32,
88    0xA04452AA, 0xB84B1267, 0x905AD299, 0x88559254,
89    0x29F05F31, 0x31FF1FFC, 0x19EEDF02, 0x01E19FCF,
90    0x49CCF657, 0x51C3B69A, 0x79D27664, 0x61DD36A9,
91    0xE988A4FD, 0xF187E430, 0xD99624CE, 0xC1996403,
92    0x89B40D9B, 0x91BB4D56, 0xB9AA8DA8, 0xA1A5CD65,
93    0x5249BE62, 0x4A46FEAF, 0x62573E51, 0x7A587E9C,
94    0x32751704, 0x2A7A57C9, 0x026B9737, 0x1A64D7FA,
95    0x923145AE, 0x8A3E0563, 0xA22FC59D, 0xBA208550,
96    0xF20DECC8, 0xEA02AC05, 0xC2136CFB, 0xDA1C2C36,
97    0x7BB9E153, 0x63B6A19E, 0x4BA76160, 0x53A821AD,
98    0x1B854835, 0x038A08F8, 0x2B9BC806, 0x339488CB,
99    0xBBC11A9F, 0xA3CE5A52, 0x8BDF9AAC, 0x93D0DA61,
100    0xDBFDB3F9, 0xC3F2F334, 0xEBE333CA, 0xF3EC7307,
101    0xA492D5C4, 0xBC9D9509, 0x948C55F7, 0x8C83153A,
102    0xC4AE7CA2, 0xDCA13C6F, 0xF4B0FC91, 0xECBFBC5C,
103    0x64EA2E08, 0x7CE56EC5, 0x54F4AE3B, 0x4CFBEEF6,
104    0x04D6876E, 0x1CD9C7A3, 0x34C8075D, 0x2CC74790,
105    0x8D628AF5, 0x956DCA38, 0xBD7C0AC6, 0xA5734A0B,
106    0xED5E2393, 0xF551635E, 0xDD40A3A0, 0xC54FE36D,
107    0x4D1A7139, 0x551531F4, 0x7D04F10A, 0x650BB1C7,
108    0x2D26D85F, 0x35299892, 0x1D38586C, 0x053718A1,
109    0xF6DB6BA6, 0xEED42B6B, 0xC6C5EB95, 0xDECAAB58,
110    0x96E7C2C0, 0x8EE8820D, 0xA6F942F3, 0xBEF6023E,
111    0x36A3906A, 0x2EACD0A7, 0x06BD1059, 0x1EB25094,
112    0x569F390C, 0x4E9079C1, 0x6681B93F, 0x7E8EF9F2,
113    0xDF2B3497, 0xC724745A, 0xEF35B4A4, 0xF73AF469,
114    0xBF179DF1, 0xA718DD3C, 0x8F091DC2, 0x97065D0F,
115    0x1F53CF5B, 0x075C8F96, 0x2F4D4F68, 0x37420FA5,
116    0x7F6F663D, 0x676026F0, 0x4F71E60E, 0x577EA6C3,
117    0xE18D0321, 0xF98243EC, 0xD1938312, 0xC99CC3DF,
118    0x81B1AA47, 0x99BEEA8A, 0xB1AF2A74, 0xA9A06AB9,
119    0x21F5F8ED, 0x39FAB820, 0x11EB78DE, 0x09E43813,
120    0x41C9518B, 0x59C61146, 0x71D7D1B8, 0x69D89175,
121    0xC87D5C10, 0xD0721CDD, 0xF863DC23, 0xE06C9CEE,
122    0xA841F576, 0xB04EB5BB, 0x985F7545, 0x80503588,
123    0x0805A7DC, 0x100AE711, 0x381B27EF, 0x20146722,
124    0x68390EBA, 0x70364E77, 0x58278E89, 0x4028CE44,
125    0xB3C4BD43, 0xABCBFD8E, 0x83DA3D70, 0x9BD57DBD,
126    0xD3F81425, 0xCBF754E8, 0xE3E69416, 0xFBE9D4DB,
127    0x73BC468F, 0x6BB30642, 0x43A2C6BC, 0x5BAD8671,
128    0x1380EFE9, 0x0B8FAF24, 0x239E6FDA, 0x3B912F17,
129    0x9A34E272, 0x823BA2BF, 0xAA2A6241, 0xB225228C,
130    0xFA084B14, 0xE2070BD9, 0xCA16CB27, 0xD2198BEA,
131    0x5A4C19BE, 0x42435973, 0x6A52998D, 0x725DD940,
132    0x3A70B0D8, 0x227FF015, 0x0A6E30EB, 0x12617026,
133    0x451FD6E5, 0x5D109628, 0x750156D6, 0x6D0E161B,
134    0x25237F83, 0x3D2C3F4E, 0x153DFFB0, 0x0D32BF7D,
135    0x85672D29, 0x9D686DE4, 0xB579AD1A, 0xAD76EDD7,
136    0xE55B844F, 0xFD54C482, 0xD545047C, 0xCD4A44B1,
137    0x6CEF89D4, 0x74E0C919, 0x5CF109E7, 0x44FE492A,
138    0x0CD320B2, 0x14DC607F, 0x3CCDA081, 0x24C2E04C,
139    0xAC977218, 0xB49832D5, 0x9C89F22B, 0x8486B2E6,
140    0xCCABDB7E, 0xD4A49BB3, 0xFCB55B4D, 0xE4BA1B80,
141    0x17566887, 0x0F59284A, 0x2748E8B4, 0x3F47A879,
142    0x776AC1E1, 0x6F65812C, 0x477441D2, 0x5F7B011F,
143    0xD72E934B, 0xCF21D386, 0xE7301378, 0xFF3F53B5,
144    0xB7123A2D, 0xAF1D7AE0, 0x870CBA1E, 0x9F03FAD3,
145    0x3EA637B6, 0x26A9777B, 0x0EB8B785, 0x16B7F748,
146    0x5E9A9ED0, 0x4695DE1D, 0x6E841EE3, 0x768B5E2E,
147    0xFEDECC7A, 0xE6D18CB7, 0xCEC04C49, 0xD6CF0C84,
148    0x9EE2651C, 0x86ED25D1, 0xAEFCE52F, 0xB6F3A5E2
149];
150
151
152#[derive(Copy)]
153pub struct Sosemanuk {
154    lfsr: [u32; 10],
155    fsm_r: [u32; 2],
156    subkeys: [u32; 100],
157    output: [u8; 80],
158    offset: u32
159}
160
161impl Clone for Sosemanuk { fn clone(&self) -> Sosemanuk { *self } }
162
163impl Sosemanuk {
164    pub fn new(key: &[u8], nonce: &[u8]) -> Sosemanuk {
165        let mut sosemanuk = Sosemanuk { lfsr: [0; 10], fsm_r: [0; 2], subkeys: [0; 100], output: [0; 80], offset: 80 };
166
167        assert!(key.len() <= 32);
168        assert!(nonce.len() <= 16);
169
170        key_setup(&key, &mut sosemanuk.subkeys);
171        iv_setup(&nonce, &mut sosemanuk.subkeys, &mut sosemanuk.lfsr, &mut sosemanuk.fsm_r);
172
173        sosemanuk
174    }
175
176    fn advance_state(&mut self) {
177        let mut s0 = self.lfsr[0];
178        let mut s1 = self.lfsr[1];
179        let mut s2 = self.lfsr[2];
180        let mut s3 = self.lfsr[3];
181        let mut s4 = self.lfsr[4];
182        let mut s5 = self.lfsr[5];
183        let mut s6 = self.lfsr[6];
184        let mut s7 = self.lfsr[7];
185        let mut s8 = self.lfsr[8];
186        let mut s9 = self.lfsr[9];
187        let mut r1 = self.fsm_r[0];
188        let mut r2 = self.fsm_r[1];
189        let mut f0 : u32;
190        let mut f1 : u32;
191        let mut f2 : u32;
192        let mut f3 : u32;
193        let mut f4 : u32;
194        let mut v0 : u32;
195        let mut v1 : u32;
196        let mut v2 : u32;
197        let mut v3 : u32;
198        let mut tt : u32;
199
200        let ref mul_alpha = ALPHA_MUL_TABLE;
201        let ref div_alpha = ALPHA_DIV_TABLE;
202
203        tt = r1;
204        //r1 = r2 + (s1 ^ ((r1 & 0x01) != 0 ? s8 : 0));
205        r1 = r2.wrapping_add(s1 ^ match r1 & 0x01 {
206            0 => 0,
207            _ => s8
208        });
209        r2 = tt.wrapping_mul(0x54655307).rotate_left(7);
210        v0 = s0;
211        s0 = ((s0 << 8) ^ mul_alpha[s0 as usize >> 24])
212            ^ ((s3 >> 8) ^ div_alpha[s3 as usize & 0xFF]) ^ s9;
213        f0 = s9.wrapping_add(r1) ^ r2;
214
215        tt = r1;
216        //r1 = r2 + (s2 ^ ((r1 & 0x01) != 0 ? s9 : 0));
217        r1 = r2.wrapping_add(s2 ^ match r1 & 0x01 {
218            0 => 0,
219            _ => s9
220        });
221        r2 = tt.wrapping_mul(0x54655307).rotate_left(7);
222        v1 = s1;
223        s1 = ((s1 << 8) ^ mul_alpha[s1 as usize >> 24])
224            ^ ((s4 >> 8) ^ div_alpha[s4 as usize & 0xFF]) ^ s0;
225        f1 = s0.wrapping_add(r1) ^ r2;
226
227        tt = r1;
228        //r1 = r2 + (s3 ^ ((r1 & 0x01) != 0 ? s0 : 0));
229        r1 = r2.wrapping_add(s3 ^ match r1 & 0x01 {
230            0 => 0,
231            _ => s0
232        });
233        r2 = tt.wrapping_mul(0x54655307).rotate_left(7);
234        v2 = s2;
235        s2 = ((s2 << 8) ^ mul_alpha[s2 as usize >> 24])
236            ^ ((s5 >> 8) ^ div_alpha[s5 as usize & 0xFF]) ^ s1;
237        f2 = s1.wrapping_add(r1) ^ r2;
238
239        tt = r1;
240        //r1 = r2 + (s4 ^ ((r1 & 0x01) != 0 ? s1 : 0));
241        r1 = r2.wrapping_add(s4 ^ match r1 & 0x01 {
242            0 => 0,
243            _ => s1
244        });
245        r2 = tt.wrapping_mul(0x54655307).rotate_left(7);
246        v3 = s3;
247        s3 = ((s3 << 8) ^ mul_alpha[s3 as usize >> 24])
248            ^ ((s6 >> 8) ^ div_alpha[s6 as usize & 0xFF]) ^ s2;
249        f3 = s2.wrapping_add(r1) ^ r2;
250
251        /*
252         * Apply the third S-box (number 2) on (f3, f2, f1, f0).
253         */
254        f4 = f0;
255        f0 &= f2;
256        f0 ^= f3;
257        f2 ^= f1;
258        f2 ^= f0;
259        f3 |= f4;
260        f3 ^= f1;
261        f4 ^= f2;
262        f1 = f3;
263        f3 |= f4;
264        f3 ^= f0;
265        f0 &= f1;
266        f4 ^= f0;
267        f1 ^= f3;
268        f1 ^= f4;
269        f4 = !f4;
270
271        /*
272         * S-box result is in (f2, f3, f1, f4).
273         */
274        let sbox_res = [(f2 ^ v0), (f3 ^ v1), (f1 ^ v2), (f4 ^ v3)];
275        write_u32v_le(&mut self.output[0..16], &sbox_res);
276
277        tt = r1;
278        //r1 = r2 + (s5 ^ ((r1 & 0x01) != 0 ? s2 : 0));
279        r1 = r2.wrapping_add(s5 ^ match r1 & 0x01 {
280            0 => 0,
281            _ => s2
282        });
283        r2 = tt.wrapping_mul(0x54655307).rotate_left(7);
284        v0 = s4;
285        s4 = ((s4 << 8) ^ mul_alpha[s4 as usize >> 24])
286            ^ ((s7 >> 8) ^ div_alpha[s7 as usize & 0xFF]) ^ s3;
287        f0 = s3.wrapping_add(r1) ^ r2;
288
289        tt = r1;
290        //r1 = r2 + (s6 ^ ((r1 & 0x01) != 0 ? s3 : 0));
291        r1 = r2.wrapping_add(s6 ^ match r1 & 0x01 {
292            0 => 0,
293            _ => s3
294        });
295        r2 = tt.wrapping_mul(0x54655307).rotate_left(7);
296        v1 = s5;
297        s5 = ((s5 << 8) ^ mul_alpha[s5 as usize >> 24])
298            ^ ((s8 >> 8) ^ div_alpha[s8 as usize & 0xFF]) ^ s4;
299        f1 = s4.wrapping_add(r1) ^ r2;
300
301        tt = r1;
302        //r1 = r2 + (s7 ^ ((r1 & 0x01) != 0 ? s4 : 0));
303        r1 = r2.wrapping_add(s7 ^ match r1 & 0x01 {
304            0 => 0,
305            _ => s4
306        });
307        r2 = tt.wrapping_mul(0x54655307).rotate_left(7);
308        v2 = s6;
309        s6 = ((s6 << 8) ^ mul_alpha[s6 as usize >> 24])
310            ^ ((s9 >> 8) ^ div_alpha[s9 as usize & 0xFF]) ^ s5;
311        f2 = s5.wrapping_add(r1) ^ r2;
312
313        tt = r1;
314        //r1 = r2 + (s8 ^ ((r1 & 0x01) != 0 ? s5 : 0));
315        r1 = r2.wrapping_add(s8 ^ match r1 & 0x01 {
316            0 => 0,
317            _ => s5
318        });
319        r2 = tt.wrapping_mul(0x54655307).rotate_left(7);
320        v3 = s7;
321        s7 = ((s7 << 8) ^ mul_alpha[s7 as usize >> 24])
322            ^ ((s0 >> 8) ^ div_alpha[s0 as usize & 0xFF]) ^ s6;
323        f3 = s6.wrapping_add(r1) ^ r2;
324
325        /*
326         * Apply the third S-box (number 2) on (f3, f2, f1, f0).
327         */
328        f4 = f0;
329        f0 &= f2;
330        f0 ^= f3;
331        f2 ^= f1;
332        f2 ^= f0;
333        f3 |= f4;
334        f3 ^= f1;
335        f4 ^= f2;
336        f1 = f3;
337        f3 |= f4;
338        f3 ^= f0;
339        f0 &= f1;
340        f4 ^= f0;
341        f1 ^= f3;
342        f1 ^= f4;
343        f4 = !f4;
344
345        /*
346         * S-box result is in (f2, f3, f1, f4).
347         */
348        let sbox_res = [(f2 ^ v0), (f3 ^ v1), (f1 ^ v2), (f4 ^ v3)];
349        write_u32v_le(&mut self.output[16..32], &sbox_res);
350
351        tt = r1;
352        //r1 = r2 + (s9 ^ ((r1 & 0x01) != 0 ? s6 : 0));
353        r1 = r2.wrapping_add(s9 ^ match r1 & 0x01 {
354            0 => 0,
355            _ => s6
356        });
357        r2 = tt.wrapping_mul(0x54655307).rotate_left(7);
358        v0 = s8;
359        s8 = ((s8 << 8) ^ mul_alpha[s8 as usize >> 24])
360            ^ ((s1 >> 8) ^ div_alpha[s1 as usize & 0xFF]) ^ s7;
361        f0 = s7.wrapping_add(r1) ^ r2;
362
363        tt = r1;
364        //r1 = r2 + (s0 ^ ((r1 & 0x01) != 0 ? s7 : 0));
365        r1 = r2.wrapping_add(s0 ^ match r1 & 0x01 {
366            0 => 0,
367            _ => s7
368        });
369        r2 = tt.wrapping_mul(0x54655307).rotate_left(7);
370        v1 = s9;
371        s9 = ((s9 << 8) ^ mul_alpha[s9 as usize >> 24])
372            ^ ((s2 >> 8) ^ div_alpha[s2 as usize & 0xFF]) ^ s8;
373        f1 = s8.wrapping_add(r1) ^ r2;
374
375        tt = r1;
376        //r1 = r2 + (s1 ^ ((r1 & 0x01) != 0 ? s8 : 0));
377        r1 = r2.wrapping_add(s1 ^ match r1 & 0x01 {
378            0 => 0,
379            _ => s8
380        });
381        r2 = tt.wrapping_mul(0x54655307).rotate_left(7);
382        v2 = s0;
383        s0 = ((s0 << 8) ^ mul_alpha[s0 as usize >> 24])
384            ^ ((s3 >> 8) ^ div_alpha[s3 as usize & 0xFF]) ^ s9;
385        f2 = s9.wrapping_add(r1) ^ r2;
386
387        tt = r1;
388        //r1 = r2 + (s2 ^ ((r1 & 0x01) != 0 ? s9 : 0));
389        r1 = r2.wrapping_add(s2 ^ match r1 & 0x01 {
390            0 => 0,
391            _ => s9
392        });
393        r2 = tt.wrapping_mul(0x54655307).rotate_left(7);
394        v3 = s1;
395        s1 = ((s1 << 8) ^ mul_alpha[s1 as usize >> 24])
396            ^ ((s4 >> 8) ^ div_alpha[s4 as usize & 0xFF]) ^ s0;
397        f3 = s0.wrapping_add(r1) ^ r2;
398
399        /*
400         * Apply the third S-box (number 2) on (f3, f2, f1, f0).
401         */
402        f4 = f0;
403        f0 &= f2;
404        f0 ^= f3;
405        f2 ^= f1;
406        f2 ^= f0;
407        f3 |= f4;
408        f3 ^= f1;
409        f4 ^= f2;
410        f1 = f3;
411        f3 |= f4;
412        f3 ^= f0;
413        f0 &= f1;
414        f4 ^= f0;
415        f1 ^= f3;
416        f1 ^= f4;
417        f4 = !f4;
418
419        /*
420         * S-box result is in (f2, f3, f1, f4).
421         */
422        let sbox_res = [(f2 ^ v0), (f3 ^ v1), (f1 ^ v2), (f4 ^ v3)];
423        write_u32v_le(&mut self.output[32..48], &sbox_res);
424
425        tt = r1;
426        //r1 = r2 + (s3 ^ ((r1 & 0x01) != 0 ? s0 : 0));
427        r1 = r2.wrapping_add(s3 ^ match r1 & 0x01 {
428            0 => 0,
429            _ => s0
430        });
431        r2 = tt.wrapping_mul(0x54655307).rotate_left(7);
432        v0 = s2;
433        s2 = ((s2 << 8) ^ mul_alpha[s2 as usize >> 24])
434            ^ ((s5 >> 8) ^ div_alpha[s5 as usize & 0xFF]) ^ s1;
435        f0 = s1.wrapping_add(r1) ^ r2;
436
437        tt = r1;
438        //r1 = r2 + (s4 ^ ((r1 & 0x01) != 0 ? s1 : 0));
439        r1 = r2.wrapping_add(s4 ^ match r1 & 0x01 {
440            0 => 0,
441            _ => s1
442        });
443        r2 = tt.wrapping_mul(0x54655307).rotate_left(7);
444        v1 = s3;
445        s3 = ((s3 << 8) ^ mul_alpha[s3 as usize >> 24])
446            ^ ((s6 >> 8) ^ div_alpha[s6 as usize & 0xFF]) ^ s2;
447        f1 = s2.wrapping_add(r1) ^ r2;
448
449        tt = r1;
450        //r1 = r2 + (s5 ^ ((r1 & 0x01) != 0 ? s2 : 0));
451        r1 = r2.wrapping_add(s5 ^ match r1 & 0x01 {
452            0 => 0,
453            _ => s2
454        });
455        r2 = tt.wrapping_mul(0x54655307).rotate_left(7);
456        v2 = s4;
457        s4 = ((s4 << 8) ^ mul_alpha[s4 as usize >> 24])
458            ^ ((s7 >> 8) ^ div_alpha[s7 as usize & 0xFF]) ^ s3;
459        f2 = s3.wrapping_add(r1) ^ r2;
460
461        tt = r1;
462        //r1 = r2 + (s6 ^ ((r1 & 0x01) != 0 ? s3 : 0));
463        r1 = r2.wrapping_add(s6 ^ match r1 & 0x01 {
464            0 => 0,
465            _ => s3
466        });
467        r2 = tt.wrapping_mul(0x54655307).rotate_left(7);
468        v3 = s5;
469        s5 = ((s5 << 8) ^ mul_alpha[s5 as usize >> 24])
470            ^ ((s8 >> 8) ^ div_alpha[s8 as usize & 0xFF]) ^ s4;
471        f3 = s4.wrapping_add(r1) ^ r2;
472
473        /*
474         * Apply the third S-box (number 2) on (f3, f2, f1, f0).
475         */
476        f4 = f0;
477        f0 &= f2;
478        f0 ^= f3;
479        f2 ^= f1;
480        f2 ^= f0;
481        f3 |= f4;
482        f3 ^= f1;
483        f4 ^= f2;
484        f1 = f3;
485        f3 |= f4;
486        f3 ^= f0;
487        f0 &= f1;
488        f4 ^= f0;
489        f1 ^= f3;
490        f1 ^= f4;
491        f4 = !f4;
492
493        /*
494         * S-box result is in (f2, f3, f1, f4).
495         */
496        let sbox_res = [(f2 ^ v0), (f3 ^ v1), (f1 ^ v2), (f4 ^ v3)];
497        write_u32v_le(&mut self.output[48..64], &sbox_res);
498
499        tt = r1;
500        //r1 = r2 + (s7 ^ ((r1 & 0x01) != 0 ? s4 : 0));
501        r1 = r2.wrapping_add(s7 ^ match r1 & 0x01 {
502            0 => 0,
503            _ => s4
504        });
505        r2 = tt.wrapping_mul(0x54655307).rotate_left(7);
506        v0 = s6;
507        s6 = ((s6 << 8) ^ mul_alpha[s6 as usize >> 24])
508            ^ ((s9 >> 8) ^ div_alpha[s9 as usize & 0xFF]) ^ s5;
509        f0 = s5.wrapping_add(r1) ^ r2;
510
511        tt = r1;
512        //r1 = r2 + (s8 ^ ((r1 & 0x01) != 0 ? s5 : 0));
513        r1 = r2.wrapping_add(s8 ^ match r1 & 0x01 {
514            0 => 0,
515            _ => s5
516        });
517        r2 = tt.wrapping_mul(0x54655307).rotate_left(7);
518        v1 = s7;
519        s7 = ((s7 << 8) ^ mul_alpha[s7 as usize >> 24])
520            ^ ((s0 >> 8) ^ div_alpha[s0 as usize & 0xFF]) ^ s6;
521        f1 = s6.wrapping_add(r1) ^ r2;
522
523        tt = r1;
524        //r1 = r2 + (s9 ^ ((r1 & 0x01) != 0 ? s6 : 0));
525        r1 = r2.wrapping_add(s9 ^ match r1 & 0x01 {
526            0 => 0,
527            _ => s6
528        });
529        r2 = tt.wrapping_mul(0x54655307).rotate_left(7);
530        v2 = s8;
531        s8 = ((s8 << 8) ^ mul_alpha[s8 as usize >> 24])
532            ^ ((s1 >> 8) ^ div_alpha[s1 as usize & 0xFF]) ^ s7;
533        f2 = s7.wrapping_add(r1) ^ r2;
534
535        tt = r1;
536        //r1 = r2 + (s0 ^ ((r1 & 0x01) != 0 ? s7 : 0));
537        r1 = r2.wrapping_add(s0 ^ match r1 & 0x01 {
538            0 => 0,
539            _ => s7
540        });
541        r2 = tt.wrapping_mul(0x54655307).rotate_left(7);
542        v3 = s9;
543        s9 = ((s9 << 8) ^ mul_alpha[s9 as usize >> 24])
544            ^ ( ( s2 >> 8) ^ div_alpha[s2 as usize & 0xFF]) ^ s8;
545        f3 = s8.wrapping_add(r1) ^ r2;
546
547        /*
548         * Apply the third S-box (number 2) on (f3, f2, f1, f0).
549         */
550        f4 = f0;
551        f0 &= f2;
552        f0 ^= f3;
553        f2 ^= f1;
554        f2 ^= f0;
555        f3 |= f4;
556        f3 ^= f1;
557        f4 ^= f2;
558        f1 = f3;
559        f3 |= f4;
560        f3 ^= f0;
561        f0 &= f1;
562        f4 ^= f0;
563        f1 ^= f3;
564        f1 ^= f4;
565        f4 = !f4;
566
567        /*
568         * S-box result is in (f2, f3, f1, f4).
569         */
570        let sbox_res = [(f2 ^ v0), (f3 ^ v1), (f1 ^ v2), (f4 ^ v3)];
571        write_u32v_le(&mut self.output[64..80], &sbox_res);
572
573        self.lfsr[0] = s0;
574        self.lfsr[1] = s1;
575        self.lfsr[2] = s2;
576        self.lfsr[3] = s3;
577        self.lfsr[4] = s4;
578        self.lfsr[5] = s5;
579        self.lfsr[6] = s6;
580        self.lfsr[7] = s7;
581        self.lfsr[8] = s8;
582        self.lfsr[9] = s9;
583        self.fsm_r[0] = r1;
584        self.fsm_r[1] = r2;
585        self.offset = 0;
586    }
587
588    fn next(&mut self) -> u8 {
589        if self.offset == 80 {
590            self.advance_state();
591        }
592        let ret = self.output[self.offset as usize];
593        self.offset += 1;
594        ret
595    }
596}
597
598
599fn key_setup(key : &[u8], subkeys : &mut[u32; 100]) {
600    let mut full_key : [u8; 32] = [0; 32];
601    if key.len() < 32 {
602        copy_memory(&key, &mut full_key[0..key.len()]);
603        full_key[key.len()] = 0x01;
604    } else {
605        copy_memory(&key[0..32], &mut full_key[0..32]);
606    }
607
608    let mut w0 = read_u32_le(&full_key[0..4]);
609    let mut w1 = read_u32_le(&full_key[4..8]);
610    let mut w2 = read_u32_le(&full_key[8..12]);
611    let mut w3 = read_u32_le(&full_key[12..16]);
612    let mut w4 = read_u32_le(&full_key[16..20]);
613    let mut w5 = read_u32_le(&full_key[20..24]);
614    let mut w6 = read_u32_le(&full_key[24..28]);
615    let mut w7 = read_u32_le(&full_key[28..32]);
616    let mut r0 : u32;
617    let mut r1 : u32;
618    let mut r2 : u32;
619    let mut r3 : u32;
620    let mut r4 : u32;
621    let mut tt : u32;
622    let mut i = 0;
623
624    tt = w0 ^ w3 ^ w5 ^ w7 ^ (0x9E3779B9 ^ (0));
625    w0 = tt.rotate_left(11);
626    tt = w1 ^ w4 ^ w6 ^ w0 ^ (0x9E3779B9 ^ (0 + 1));
627    w1 = tt.rotate_left(11);
628    tt = w2 ^ w5 ^ w7 ^ w1 ^ (0x9E3779B9 ^ (0 + 2));
629    w2 = tt.rotate_left(11);
630    tt = w3 ^ w6 ^ w0 ^ w2 ^ (0x9E3779B9 ^ (0 + 3));
631    w3 = tt.rotate_left(11);
632    r0 = w0;
633    r1 = w1;
634    r2 = w2;
635    r3 = w3;
636    r4 = r0;
637    r0 |= r3;
638    r3 ^= r1;
639    r1 &= r4;
640    r4 ^= r2;
641    r2 ^= r3;
642    r3 &= r0;
643    r4 |= r1;
644    r3 ^= r4;
645    r0 ^= r1;
646    r4 &= r0;
647    r1 ^= r3;
648    r4 ^= r2;
649    r1 |= r0;
650    r1 ^= r2;
651    r0 ^= r3;
652    r2 = r1;
653    r1 |= r3;
654    r1 ^= r0;
655    subkeys[i] = r1; i+=1;
656    subkeys[i] = r2; i+=1;
657    subkeys[i] = r3; i+=1;
658    subkeys[i] = r4; i+=1;
659    tt = w4 ^ w7 ^ w1 ^ w3 ^ (0x9E3779B9 ^ (4));
660    w4 = tt.rotate_left(11);
661    tt = w5 ^ w0 ^ w2 ^ w4 ^ (0x9E3779B9 ^ (4 + 1));
662    w5 = tt.rotate_left(11);
663    tt = w6 ^ w1 ^ w3 ^ w5 ^ (0x9E3779B9 ^ (4 + 2));
664    w6 = tt.rotate_left(11);
665    tt = w7 ^ w2 ^ w4 ^ w6 ^ (0x9E3779B9 ^ (4 + 3));
666    w7 = tt.rotate_left(11);
667    r0 = w4;
668    r1 = w5;
669    r2 = w6;
670    r3 = w7;
671    r4 = r0;
672    r0 &= r2;
673    r0 ^= r3;
674    r2 ^= r1;
675    r2 ^= r0;
676    r3 |= r4;
677    r3 ^= r1;
678    r4 ^= r2;
679    r1 = r3;
680    r3 |= r4;
681    r3 ^= r0;
682    r0 &= r1;
683    r4 ^= r0;
684    r1 ^= r3;
685    r1 ^= r4;
686    r4 = !r4;
687    subkeys[i] = r2; i+=1;
688    subkeys[i] = r3; i+=1;
689    subkeys[i] = r1; i+=1;
690    subkeys[i] = r4; i+=1;
691    tt = w0 ^ w3 ^ w5 ^ w7 ^ (0x9E3779B9 ^ (8));
692    w0 = tt.rotate_left(11);
693    tt = w1 ^ w4 ^ w6 ^ w0 ^ (0x9E3779B9 ^ (8 + 1));
694    w1 = tt.rotate_left(11);
695    tt = w2 ^ w5 ^ w7 ^ w1 ^ (0x9E3779B9 ^ (8 + 2));
696    w2 = tt.rotate_left(11);
697    tt = w3 ^ w6 ^ w0 ^ w2 ^ (0x9E3779B9 ^ (8 + 3));
698    w3 = tt.rotate_left(11);
699    r0 = w0;
700    r1 = w1;
701    r2 = w2;
702    r3 = w3;
703    r0 = !r0;
704    r2 = !r2;
705    r4 = r0;
706    r0 &= r1;
707    r2 ^= r0;
708    r0 |= r3;
709    r3 ^= r2;
710    r1 ^= r0;
711    r0 ^= r4;
712    r4 |= r1;
713    r1 ^= r3;
714    r2 |= r0;
715    r2 &= r4;
716    r0 ^= r1;
717    r1 &= r2;
718    r1 ^= r0;
719    r0 &= r2;
720    r0 ^= r4;
721    subkeys[i] = r2; i+=1;
722    subkeys[i] = r0; i+=1;
723    subkeys[i] = r3; i+=1;
724    subkeys[i] = r1; i+=1;
725    tt = w4 ^ w7 ^ w1 ^ w3 ^ (0x9E3779B9 ^ (12));
726    w4 = tt.rotate_left(11);
727    tt = w5 ^ w0 ^ w2 ^ w4 ^ (0x9E3779B9 ^ (12 + 1));
728    w5 = tt.rotate_left(11);
729    tt = w6 ^ w1 ^ w3 ^ w5 ^ (0x9E3779B9 ^ (12 + 2));
730    w6 = tt.rotate_left(11);
731    tt = w7 ^ w2 ^ w4 ^ w6 ^ (0x9E3779B9 ^ (12 + 3));
732    w7 = tt.rotate_left(11);
733    r0 = w4;
734    r1 = w5;
735    r2 = w6;
736    r3 = w7;
737    r3 ^= r0;
738    r4 = r1;
739    r1 &= r3;
740    r4 ^= r2;
741    r1 ^= r0;
742    r0 |= r3;
743    r0 ^= r4;
744    r4 ^= r3;
745    r3 ^= r2;
746    r2 |= r1;
747    r2 ^= r4;
748    r4 = !r4;
749    r4 |= r1;
750    r1 ^= r3;
751    r1 ^= r4;
752    r3 |= r0;
753    r1 ^= r3;
754    r4 ^= r3;
755    subkeys[i] = r1; i+=1;
756    subkeys[i] = r4; i+=1;
757    subkeys[i] = r2; i+=1;
758    subkeys[i] = r0; i+=1;
759    tt = w0 ^ w3 ^ w5 ^ w7 ^ (0x9E3779B9 ^ (16));
760    w0 = tt.rotate_left(11);
761    tt = w1 ^ w4 ^ w6 ^ w0 ^ (0x9E3779B9 ^ (16 + 1));
762    w1 = tt.rotate_left(11);
763    tt = w2 ^ w5 ^ w7 ^ w1 ^ (0x9E3779B9 ^ (16 + 2));
764    w2 = tt.rotate_left(11);
765    tt = w3 ^ w6 ^ w0 ^ w2 ^ (0x9E3779B9 ^ (16 + 3));
766    w3 = tt.rotate_left(11);
767    r0 = w0;
768    r1 = w1;
769    r2 = w2;
770    r3 = w3;
771    r4 = r1;
772    r1 |= r2;
773    r1 ^= r3;
774    r4 ^= r2;
775    r2 ^= r1;
776    r3 |= r4;
777    r3 &= r0;
778    r4 ^= r2;
779    r3 ^= r1;
780    r1 |= r4;
781    r1 ^= r0;
782    r0 |= r4;
783    r0 ^= r2;
784    r1 ^= r4;
785    r2 ^= r1;
786    r1 &= r0;
787    r1 ^= r4;
788    r2 = !r2;
789    r2 |= r0;
790    r4 ^= r2;
791    subkeys[i] = r4; i+=1;
792    subkeys[i] = r3; i+=1;
793    subkeys[i] = r1; i+=1;
794    subkeys[i] = r0; i+=1;
795    tt = w4 ^ w7 ^ w1 ^ w3 ^ (0x9E3779B9 ^ (20));
796    w4 = tt.rotate_left(11);
797    tt = w5 ^ w0 ^ w2 ^ w4 ^ (0x9E3779B9 ^ (20 + 1));
798    w5 = tt.rotate_left(11);
799    tt = w6 ^ w1 ^ w3 ^ w5 ^ (0x9E3779B9 ^ (20 + 2));
800    w6 = tt.rotate_left(11);
801    tt = w7 ^ w2 ^ w4 ^ w6 ^ (0x9E3779B9 ^ (20 + 3));
802    w7 = tt.rotate_left(11);
803    r0 = w4;
804    r1 = w5;
805    r2 = w6;
806    r3 = w7;
807    r2 = !r2;
808    r4 = r3;
809    r3 &= r0;
810    r0 ^= r4;
811    r3 ^= r2;
812    r2 |= r4;
813    r1 ^= r3;
814    r2 ^= r0;
815    r0 |= r1;
816    r2 ^= r1;
817    r4 ^= r0;
818    r0 |= r3;
819    r0 ^= r2;
820    r4 ^= r3;
821    r4 ^= r0;
822    r3 = !r3;
823    r2 &= r4;
824    r2 ^= r3;
825    subkeys[i] = r0; i+=1;
826    subkeys[i] = r1; i+=1;
827    subkeys[i] = r4; i+=1;
828    subkeys[i] = r2; i+=1;
829    tt = w0 ^ w3 ^ w5 ^ w7 ^ (0x9E3779B9 ^ (24));
830    w0 = tt.rotate_left(11);
831    tt = w1 ^ w4 ^ w6 ^ w0 ^ (0x9E3779B9 ^ (24 + 1));
832    w1 = tt.rotate_left(11);
833    tt = w2 ^ w5 ^ w7 ^ w1 ^ (0x9E3779B9 ^ (24 + 2));
834    w2 = tt.rotate_left(11);
835    tt = w3 ^ w6 ^ w0 ^ w2 ^ (0x9E3779B9 ^ (24 + 3));
836    w3 = tt.rotate_left(11);
837    r0 = w0;
838    r1 = w1;
839    r2 = w2;
840    r3 = w3;
841    r0 ^= r1;
842    r1 ^= r3;
843    r3 = !r3;
844    r4 = r1;
845    r1 &= r0;
846    r2 ^= r3;
847    r1 ^= r2;
848    r2 |= r4;
849    r4 ^= r3;
850    r3 &= r1;
851    r3 ^= r0;
852    r4 ^= r1;
853    r4 ^= r2;
854    r2 ^= r0;
855    r0 &= r3;
856    r2 = !r2;
857    r0 ^= r4;
858    r4 |= r3;
859    r2 ^= r4;
860    subkeys[i] = r1; i+=1;
861    subkeys[i] = r3; i+=1;
862    subkeys[i] = r0; i+=1;
863    subkeys[i] = r2; i+=1;
864    tt = w4 ^ w7 ^ w1 ^ w3 ^ (0x9E3779B9 ^ (28));
865    w4 = tt.rotate_left(11);
866    tt = w5 ^ w0 ^ w2 ^ w4 ^ (0x9E3779B9 ^ (28 + 1));
867    w5 = tt.rotate_left(11);
868    tt = w6 ^ w1 ^ w3 ^ w5 ^ (0x9E3779B9 ^ (28 + 2));
869    w6 = tt.rotate_left(11);
870    tt = w7 ^ w2 ^ w4 ^ w6 ^ (0x9E3779B9 ^ (28 + 3));
871    w7 = tt.rotate_left(11);
872    r0 = w4;
873    r1 = w5;
874    r2 = w6;
875    r3 = w7;
876    r1 ^= r3;
877    r3 = !r3;
878    r2 ^= r3;
879    r3 ^= r0;
880    r4 = r1;
881    r1 &= r3;
882    r1 ^= r2;
883    r4 ^= r3;
884    r0 ^= r4;
885    r2 &= r4;
886    r2 ^= r0;
887    r0 &= r1;
888    r3 ^= r0;
889    r4 |= r1;
890    r4 ^= r0;
891    r0 |= r3;
892    r0 ^= r2;
893    r2 &= r3;
894    r0 = !r0;
895    r4 ^= r2;
896    subkeys[i] = r1; i+=1;
897    subkeys[i] = r4; i+=1;
898    subkeys[i] = r0; i+=1;
899    subkeys[i] = r3; i+=1;
900    tt = w0 ^ w3 ^ w5 ^ w7 ^ (0x9E3779B9 ^ (32));
901    w0 = tt.rotate_left(11);
902    tt = w1 ^ w4 ^ w6 ^ w0 ^ (0x9E3779B9 ^ (32 + 1));
903    w1 = tt.rotate_left(11);
904    tt = w2 ^ w5 ^ w7 ^ w1 ^ (0x9E3779B9 ^ (32 + 2));
905    w2 = tt.rotate_left(11);
906    tt = w3 ^ w6 ^ w0 ^ w2 ^ (0x9E3779B9 ^ (32 + 3));
907    w3 = tt.rotate_left(11);
908    r0 = w0;
909    r1 = w1;
910    r2 = w2;
911    r3 = w3;
912    r4 = r0;
913    r0 |= r3;
914    r3 ^= r1;
915    r1 &= r4;
916    r4 ^= r2;
917    r2 ^= r3;
918    r3 &= r0;
919    r4 |= r1;
920    r3 ^= r4;
921    r0 ^= r1;
922    r4 &= r0;
923    r1 ^= r3;
924    r4 ^= r2;
925    r1 |= r0;
926    r1 ^= r2;
927    r0 ^= r3;
928    r2 = r1;
929    r1 |= r3;
930    r1 ^= r0;
931    subkeys[i] = r1; i+=1;
932    subkeys[i] = r2; i+=1;
933    subkeys[i] = r3; i+=1;
934    subkeys[i] = r4; i+=1;
935    tt = w4 ^ w7 ^ w1 ^ w3 ^ (0x9E3779B9 ^ (36));
936    w4 = tt.rotate_left(11);
937    tt = w5 ^ w0 ^ w2 ^ w4 ^ (0x9E3779B9 ^ (36 + 1));
938    w5 = tt.rotate_left(11);
939    tt = w6 ^ w1 ^ w3 ^ w5 ^ (0x9E3779B9 ^ (36 + 2));
940    w6 = tt.rotate_left(11);
941    tt = w7 ^ w2 ^ w4 ^ w6 ^ (0x9E3779B9 ^ (36 + 3));
942    w7 = tt.rotate_left(11);
943    r0 = w4;
944    r1 = w5;
945    r2 = w6;
946    r3 = w7;
947    r4 = r0;
948    r0 &= r2;
949    r0 ^= r3;
950    r2 ^= r1;
951    r2 ^= r0;
952    r3 |= r4;
953    r3 ^= r1;
954    r4 ^= r2;
955    r1 = r3;
956    r3 |= r4;
957    r3 ^= r0;
958    r0 &= r1;
959    r4 ^= r0;
960    r1 ^= r3;
961    r1 ^= r4;
962    r4 = !r4;
963    subkeys[i] = r2; i+=1;
964    subkeys[i] = r3; i+=1;
965    subkeys[i] = r1; i+=1;
966    subkeys[i] = r4; i+=1;
967    tt = w0 ^ w3 ^ w5 ^ w7 ^ (0x9E3779B9 ^ (40));
968    w0 = tt.rotate_left(11);
969    tt = w1 ^ w4 ^ w6 ^ w0 ^ (0x9E3779B9 ^ (40 + 1));
970    w1 = tt.rotate_left(11);
971    tt = w2 ^ w5 ^ w7 ^ w1 ^ (0x9E3779B9 ^ (40 + 2));
972    w2 = tt.rotate_left(11);
973    tt = w3 ^ w6 ^ w0 ^ w2 ^ (0x9E3779B9 ^ (40 + 3));
974    w3 = tt.rotate_left(11);
975    r0 = w0;
976    r1 = w1;
977    r2 = w2;
978    r3 = w3;
979    r0 = !r0;
980    r2 = !r2;
981    r4 = r0;
982    r0 &= r1;
983    r2 ^= r0;
984    r0 |= r3;
985    r3 ^= r2;
986    r1 ^= r0;
987    r0 ^= r4;
988    r4 |= r1;
989    r1 ^= r3;
990    r2 |= r0;
991    r2 &= r4;
992    r0 ^= r1;
993    r1 &= r2;
994    r1 ^= r0;
995    r0 &= r2;
996    r0 ^= r4;
997    subkeys[i] = r2; i+=1;
998    subkeys[i] = r0; i+=1;
999    subkeys[i] = r3; i+=1;
1000    subkeys[i] = r1; i+=1;
1001    tt = w4 ^ w7 ^ w1 ^ w3 ^ (0x9E3779B9 ^ (44));
1002    w4 = tt.rotate_left(11);
1003    tt = w5 ^ w0 ^ w2 ^ w4 ^ (0x9E3779B9 ^ (44 + 1));
1004    w5 = tt.rotate_left(11);
1005    tt = w6 ^ w1 ^ w3 ^ w5 ^ (0x9E3779B9 ^ (44 + 2));
1006    w6 = tt.rotate_left(11);
1007    tt = w7 ^ w2 ^ w4 ^ w6 ^ (0x9E3779B9 ^ (44 + 3));
1008    w7 = tt.rotate_left(11);
1009    r0 = w4;
1010    r1 = w5;
1011    r2 = w6;
1012    r3 = w7;
1013    r3 ^= r0;
1014    r4 = r1;
1015    r1 &= r3;
1016    r4 ^= r2;
1017    r1 ^= r0;
1018    r0 |= r3;
1019    r0 ^= r4;
1020    r4 ^= r3;
1021    r3 ^= r2;
1022    r2 |= r1;
1023    r2 ^= r4;
1024    r4 = !r4;
1025    r4 |= r1;
1026    r1 ^= r3;
1027    r1 ^= r4;
1028    r3 |= r0;
1029    r1 ^= r3;
1030    r4 ^= r3;
1031    subkeys[i] = r1; i+=1;
1032    subkeys[i] = r4; i+=1;
1033    subkeys[i] = r2; i+=1;
1034    subkeys[i] = r0; i+=1;
1035    tt = w0 ^ w3 ^ w5 ^ w7 ^ (0x9E3779B9 ^ (48));
1036    w0 = tt.rotate_left(11);
1037    tt = w1 ^ w4 ^ w6 ^ w0 ^ (0x9E3779B9 ^ (48 + 1));
1038    w1 = tt.rotate_left(11);
1039    tt = w2 ^ w5 ^ w7 ^ w1 ^ (0x9E3779B9 ^ (48 + 2));
1040    w2 = tt.rotate_left(11);
1041    tt = w3 ^ w6 ^ w0 ^ w2 ^ (0x9E3779B9 ^ (48 + 3));
1042    w3 = tt.rotate_left(11);
1043    r0 = w0;
1044    r1 = w1;
1045    r2 = w2;
1046    r3 = w3;
1047    r4 = r1;
1048    r1 |= r2;
1049    r1 ^= r3;
1050    r4 ^= r2;
1051    r2 ^= r1;
1052    r3 |= r4;
1053    r3 &= r0;
1054    r4 ^= r2;
1055    r3 ^= r1;
1056    r1 |= r4;
1057    r1 ^= r0;
1058    r0 |= r4;
1059    r0 ^= r2;
1060    r1 ^= r4;
1061    r2 ^= r1;
1062    r1 &= r0;
1063    r1 ^= r4;
1064    r2 = !r2;
1065    r2 |= r0;
1066    r4 ^= r2;
1067    subkeys[i] = r4; i+=1;
1068    subkeys[i] = r3; i+=1;
1069    subkeys[i] = r1; i+=1;
1070    subkeys[i] = r0; i+=1;
1071    tt = w4 ^ w7 ^ w1 ^ w3 ^ (0x9E3779B9 ^ (52));
1072    w4 = tt.rotate_left(11);
1073    tt = w5 ^ w0 ^ w2 ^ w4 ^ (0x9E3779B9 ^ (52 + 1));
1074    w5 = tt.rotate_left(11);
1075    tt = w6 ^ w1 ^ w3 ^ w5 ^ (0x9E3779B9 ^ (52 + 2));
1076    w6 = tt.rotate_left(11);
1077    tt = w7 ^ w2 ^ w4 ^ w6 ^ (0x9E3779B9 ^ (52 + 3));
1078    w7 = tt.rotate_left(11);
1079    r0 = w4;
1080    r1 = w5;
1081    r2 = w6;
1082    r3 = w7;
1083    r2 = !r2;
1084    r4 = r3;
1085    r3 &= r0;
1086    r0 ^= r4;
1087    r3 ^= r2;
1088    r2 |= r4;
1089    r1 ^= r3;
1090    r2 ^= r0;
1091    r0 |= r1;
1092    r2 ^= r1;
1093    r4 ^= r0;
1094    r0 |= r3;
1095    r0 ^= r2;
1096    r4 ^= r3;
1097    r4 ^= r0;
1098    r3 = !r3;
1099    r2 &= r4;
1100    r2 ^= r3;
1101    subkeys[i] = r0; i+=1;
1102    subkeys[i] = r1; i+=1;
1103    subkeys[i] = r4; i+=1;
1104    subkeys[i] = r2; i+=1;
1105    tt = w0 ^ w3 ^ w5 ^ w7 ^ (0x9E3779B9 ^ (56));
1106    w0 = tt.rotate_left(11);
1107    tt = w1 ^ w4 ^ w6 ^ w0 ^ (0x9E3779B9 ^ (56 + 1));
1108    w1 = tt.rotate_left(11);
1109    tt = w2 ^ w5 ^ w7 ^ w1 ^ (0x9E3779B9 ^ (56 + 2));
1110    w2 = tt.rotate_left(11);
1111    tt = w3 ^ w6 ^ w0 ^ w2 ^ (0x9E3779B9 ^ (56 + 3));
1112    w3 = tt.rotate_left(11);
1113    r0 = w0;
1114    r1 = w1;
1115    r2 = w2;
1116    r3 = w3;
1117    r0 ^= r1;
1118    r1 ^= r3;
1119    r3 = !r3;
1120    r4 = r1;
1121    r1 &= r0;
1122    r2 ^= r3;
1123    r1 ^= r2;
1124    r2 |= r4;
1125    r4 ^= r3;
1126    r3 &= r1;
1127    r3 ^= r0;
1128    r4 ^= r1;
1129    r4 ^= r2;
1130    r2 ^= r0;
1131    r0 &= r3;
1132    r2 = !r2;
1133    r0 ^= r4;
1134    r4 |= r3;
1135    r2 ^= r4;
1136    subkeys[i] = r1; i+=1;
1137    subkeys[i] = r3; i+=1;
1138    subkeys[i] = r0; i+=1;
1139    subkeys[i] = r2; i+=1;
1140    tt = w4 ^ w7 ^ w1 ^ w3 ^ (0x9E3779B9 ^ (60));
1141    w4 = tt.rotate_left(11);
1142    tt = w5 ^ w0 ^ w2 ^ w4 ^ (0x9E3779B9 ^ (60 + 1));
1143    w5 = tt.rotate_left(11);
1144    tt = w6 ^ w1 ^ w3 ^ w5 ^ (0x9E3779B9 ^ (60 + 2));
1145    w6 = tt.rotate_left(11);
1146    tt = w7 ^ w2 ^ w4 ^ w6 ^ (0x9E3779B9 ^ (60 + 3));
1147    w7 = tt.rotate_left(11);
1148    r0 = w4;
1149    r1 = w5;
1150    r2 = w6;
1151    r3 = w7;
1152    r1 ^= r3;
1153    r3 = !r3;
1154    r2 ^= r3;
1155    r3 ^= r0;
1156    r4 = r1;
1157    r1 &= r3;
1158    r1 ^= r2;
1159    r4 ^= r3;
1160    r0 ^= r4;
1161    r2 &= r4;
1162    r2 ^= r0;
1163    r0 &= r1;
1164    r3 ^= r0;
1165    r4 |= r1;
1166    r4 ^= r0;
1167    r0 |= r3;
1168    r0 ^= r2;
1169    r2 &= r3;
1170    r0 = !r0;
1171    r4 ^= r2;
1172    subkeys[i] = r1; i+=1;
1173    subkeys[i] = r4; i+=1;
1174    subkeys[i] = r0; i+=1;
1175    subkeys[i] = r3; i+=1;
1176    tt = w0 ^ w3 ^ w5 ^ w7 ^ (0x9E3779B9 ^ (64));
1177    w0 = tt.rotate_left(11);
1178    tt = w1 ^ w4 ^ w6 ^ w0 ^ (0x9E3779B9 ^ (64 + 1));
1179    w1 = tt.rotate_left(11);
1180    tt = w2 ^ w5 ^ w7 ^ w1 ^ (0x9E3779B9 ^ (64 + 2));
1181    w2 = tt.rotate_left(11);
1182    tt = w3 ^ w6 ^ w0 ^ w2 ^ (0x9E3779B9 ^ (64 + 3));
1183    w3 = tt.rotate_left(11);
1184    r0 = w0;
1185    r1 = w1;
1186    r2 = w2;
1187    r3 = w3;
1188    r4 = r0;
1189    r0 |= r3;
1190    r3 ^= r1;
1191    r1 &= r4;
1192    r4 ^= r2;
1193    r2 ^= r3;
1194    r3 &= r0;
1195    r4 |= r1;
1196    r3 ^= r4;
1197    r0 ^= r1;
1198    r4 &= r0;
1199    r1 ^= r3;
1200    r4 ^= r2;
1201    r1 |= r0;
1202    r1 ^= r2;
1203    r0 ^= r3;
1204    r2 = r1;
1205    r1 |= r3;
1206    r1 ^= r0;
1207    subkeys[i] = r1; i+=1;
1208    subkeys[i] = r2; i+=1;
1209    subkeys[i] = r3; i+=1;
1210    subkeys[i] = r4; i+=1;
1211    tt = w4 ^ w7 ^ w1 ^ w3 ^ (0x9E3779B9 ^ (68));
1212    w4 = tt.rotate_left(11);
1213    tt = w5 ^ w0 ^ w2 ^ w4 ^ (0x9E3779B9 ^ (68 + 1));
1214    w5 = tt.rotate_left(11);
1215    tt = w6 ^ w1 ^ w3 ^ w5 ^ (0x9E3779B9 ^ (68 + 2));
1216    w6 = tt.rotate_left(11);
1217    tt = w7 ^ w2 ^ w4 ^ w6 ^ (0x9E3779B9 ^ (68 + 3));
1218    w7 = tt.rotate_left(11);
1219    r0 = w4;
1220    r1 = w5;
1221    r2 = w6;
1222    r3 = w7;
1223    r4 = r0;
1224    r0 &= r2;
1225    r0 ^= r3;
1226    r2 ^= r1;
1227    r2 ^= r0;
1228    r3 |= r4;
1229    r3 ^= r1;
1230    r4 ^= r2;
1231    r1 = r3;
1232    r3 |= r4;
1233    r3 ^= r0;
1234    r0 &= r1;
1235    r4 ^= r0;
1236    r1 ^= r3;
1237    r1 ^= r4;
1238    r4 = !r4;
1239    subkeys[i] = r2; i+=1;
1240    subkeys[i] = r3; i+=1;
1241    subkeys[i] = r1; i+=1;
1242    subkeys[i] = r4; i+=1;
1243    tt = w0 ^ w3 ^ w5 ^ w7 ^ (0x9E3779B9 ^ (72));
1244    w0 = tt.rotate_left(11);
1245    tt = w1 ^ w4 ^ w6 ^ w0 ^ (0x9E3779B9 ^ (72 + 1));
1246    w1 = tt.rotate_left(11);
1247    tt = w2 ^ w5 ^ w7 ^ w1 ^ (0x9E3779B9 ^ (72 + 2));
1248    w2 = tt.rotate_left(11);
1249    tt = w3 ^ w6 ^ w0 ^ w2 ^ (0x9E3779B9 ^ (72 + 3));
1250    w3 = tt.rotate_left(11);
1251    r0 = w0;
1252    r1 = w1;
1253    r2 = w2;
1254    r3 = w3;
1255    r0 = !r0;
1256    r2 = !r2;
1257    r4 = r0;
1258    r0 &= r1;
1259    r2 ^= r0;
1260    r0 |= r3;
1261    r3 ^= r2;
1262    r1 ^= r0;
1263    r0 ^= r4;
1264    r4 |= r1;
1265    r1 ^= r3;
1266    r2 |= r0;
1267    r2 &= r4;
1268    r0 ^= r1;
1269    r1 &= r2;
1270    r1 ^= r0;
1271    r0 &= r2;
1272    r0 ^= r4;
1273    subkeys[i] = r2; i+=1;
1274    subkeys[i] = r0; i+=1;
1275    subkeys[i] = r3; i+=1;
1276    subkeys[i] = r1; i+=1;
1277    tt = w4 ^ w7 ^ w1 ^ w3 ^ (0x9E3779B9 ^ (76));
1278    w4 = tt.rotate_left(11);
1279    tt = w5 ^ w0 ^ w2 ^ w4 ^ (0x9E3779B9 ^ (76 + 1));
1280    w5 = tt.rotate_left(11);
1281    tt = w6 ^ w1 ^ w3 ^ w5 ^ (0x9E3779B9 ^ (76 + 2));
1282    w6 = tt.rotate_left(11);
1283    tt = w7 ^ w2 ^ w4 ^ w6 ^ (0x9E3779B9 ^ (76 + 3));
1284    w7 = tt.rotate_left(11);
1285    r0 = w4;
1286    r1 = w5;
1287    r2 = w6;
1288    r3 = w7;
1289    r3 ^= r0;
1290    r4 = r1;
1291    r1 &= r3;
1292    r4 ^= r2;
1293    r1 ^= r0;
1294    r0 |= r3;
1295    r0 ^= r4;
1296    r4 ^= r3;
1297    r3 ^= r2;
1298    r2 |= r1;
1299    r2 ^= r4;
1300    r4 = !r4;
1301    r4 |= r1;
1302    r1 ^= r3;
1303    r1 ^= r4;
1304    r3 |= r0;
1305    r1 ^= r3;
1306    r4 ^= r3;
1307    subkeys[i] = r1; i+=1;
1308    subkeys[i] = r4; i+=1;
1309    subkeys[i] = r2; i+=1;
1310    subkeys[i] = r0; i+=1;
1311    tt = w0 ^ w3 ^ w5 ^ w7 ^ (0x9E3779B9 ^ (80));
1312    w0 = tt.rotate_left(11);
1313    tt = w1 ^ w4 ^ w6 ^ w0 ^ (0x9E3779B9 ^ (80 + 1));
1314    w1 = tt.rotate_left(11);
1315    tt = w2 ^ w5 ^ w7 ^ w1 ^ (0x9E3779B9 ^ (80 + 2));
1316    w2 = tt.rotate_left(11);
1317    tt = w3 ^ w6 ^ w0 ^ w2 ^ (0x9E3779B9 ^ (80 + 3));
1318    w3 = tt.rotate_left(11);
1319    r0 = w0;
1320    r1 = w1;
1321    r2 = w2;
1322    r3 = w3;
1323    r4 = r1;
1324    r1 |= r2;
1325    r1 ^= r3;
1326    r4 ^= r2;
1327    r2 ^= r1;
1328    r3 |= r4;
1329    r3 &= r0;
1330    r4 ^= r2;
1331    r3 ^= r1;
1332    r1 |= r4;
1333    r1 ^= r0;
1334    r0 |= r4;
1335    r0 ^= r2;
1336    r1 ^= r4;
1337    r2 ^= r1;
1338    r1 &= r0;
1339    r1 ^= r4;
1340    r2 = !r2;
1341    r2 |= r0;
1342    r4 ^= r2;
1343    subkeys[i] = r4; i+=1;
1344    subkeys[i] = r3; i+=1;
1345    subkeys[i] = r1; i+=1;
1346    subkeys[i] = r0; i+=1;
1347    tt = w4 ^ w7 ^ w1 ^ w3 ^ (0x9E3779B9 ^ (84));
1348    w4 = tt.rotate_left(11);
1349    tt = w5 ^ w0 ^ w2 ^ w4 ^ (0x9E3779B9 ^ (84 + 1));
1350    w5 = tt.rotate_left(11);
1351    tt = w6 ^ w1 ^ w3 ^ w5 ^ (0x9E3779B9 ^ (84 + 2));
1352    w6 = tt.rotate_left(11);
1353    tt = w7 ^ w2 ^ w4 ^ w6 ^ (0x9E3779B9 ^ (84 + 3));
1354    w7 = tt.rotate_left(11);
1355    r0 = w4;
1356    r1 = w5;
1357    r2 = w6;
1358    r3 = w7;
1359    r2 = !r2;
1360    r4 = r3;
1361    r3 &= r0;
1362    r0 ^= r4;
1363    r3 ^= r2;
1364    r2 |= r4;
1365    r1 ^= r3;
1366    r2 ^= r0;
1367    r0 |= r1;
1368    r2 ^= r1;
1369    r4 ^= r0;
1370    r0 |= r3;
1371    r0 ^= r2;
1372    r4 ^= r3;
1373    r4 ^= r0;
1374    r3 = !r3;
1375    r2 &= r4;
1376    r2 ^= r3;
1377    subkeys[i] = r0; i+=1;
1378    subkeys[i] = r1; i+=1;
1379    subkeys[i] = r4; i+=1;
1380    subkeys[i] = r2; i+=1;
1381    tt = w0 ^ w3 ^ w5 ^ w7 ^ (0x9E3779B9 ^ (88));
1382    w0 = tt.rotate_left(11);
1383    tt = w1 ^ w4 ^ w6 ^ w0 ^ (0x9E3779B9 ^ (88 + 1));
1384    w1 = tt.rotate_left(11);
1385    tt = w2 ^ w5 ^ w7 ^ w1 ^ (0x9E3779B9 ^ (88 + 2));
1386    w2 = tt.rotate_left(11);
1387    tt = w3 ^ w6 ^ w0 ^ w2 ^ (0x9E3779B9 ^ (88 + 3));
1388    w3 = tt.rotate_left(11);
1389    r0 = w0;
1390    r1 = w1;
1391    r2 = w2;
1392    r3 = w3;
1393    r0 ^= r1;
1394    r1 ^= r3;
1395    r3 = !r3;
1396    r4 = r1;
1397    r1 &= r0;
1398    r2 ^= r3;
1399    r1 ^= r2;
1400    r2 |= r4;
1401    r4 ^= r3;
1402    r3 &= r1;
1403    r3 ^= r0;
1404    r4 ^= r1;
1405    r4 ^= r2;
1406    r2 ^= r0;
1407    r0 &= r3;
1408    r2 = !r2;
1409    r0 ^= r4;
1410    r4 |= r3;
1411    r2 ^= r4;
1412    subkeys[i] = r1; i+=1;
1413    subkeys[i] = r3; i+=1;
1414    subkeys[i] = r0; i+=1;
1415    subkeys[i] = r2; i+=1;
1416    tt = w4 ^ w7 ^ w1 ^ w3 ^ (0x9E3779B9 ^ (92));
1417    w4 = tt.rotate_left(11);
1418    tt = w5 ^ w0 ^ w2 ^ w4 ^ (0x9E3779B9 ^ (92 + 1));
1419    w5 = tt.rotate_left(11);
1420    tt = w6 ^ w1 ^ w3 ^ w5 ^ (0x9E3779B9 ^ (92 + 2));
1421    w6 = tt.rotate_left(11);
1422    tt = w7 ^ w2 ^ w4 ^ w6 ^ (0x9E3779B9 ^ (92 + 3));
1423    w7 = tt.rotate_left(11);
1424    r0 = w4;
1425    r1 = w5;
1426    r2 = w6;
1427    r3 = w7;
1428    r1 ^= r3;
1429    r3 = !r3;
1430    r2 ^= r3;
1431    r3 ^= r0;
1432    r4 = r1;
1433    r1 &= r3;
1434    r1 ^= r2;
1435    r4 ^= r3;
1436    r0 ^= r4;
1437    r2 &= r4;
1438    r2 ^= r0;
1439    r0 &= r1;
1440    r3 ^= r0;
1441    r4 |= r1;
1442    r4 ^= r0;
1443    r0 |= r3;
1444    r0 ^= r2;
1445    r2 &= r3;
1446    r0 = !r0;
1447    r4 ^= r2;
1448    subkeys[i] = r1; i+=1;
1449    subkeys[i] = r4; i+=1;
1450    subkeys[i] = r0; i+=1;
1451    subkeys[i] = r3; i+=1;
1452    tt = w0 ^ w3 ^ w5 ^ w7 ^ (0x9E3779B9 ^ (96));
1453    w0 = tt.rotate_left(11);
1454    tt = w1 ^ w4 ^ w6 ^ w0 ^ (0x9E3779B9 ^ (96 + 1));
1455    w1 = tt.rotate_left(11);
1456    tt = w2 ^ w5 ^ w7 ^ w1 ^ (0x9E3779B9 ^ (96 + 2));
1457    w2 = tt.rotate_left(11);
1458    tt = w3 ^ w6 ^ w0 ^ w2 ^ (0x9E3779B9 ^ (96 + 3));
1459    w3 = tt.rotate_left(11);
1460    r0 = w0;
1461    r1 = w1;
1462    r2 = w2;
1463    r3 = w3;
1464    r4 = r0;
1465    r0 |= r3;
1466    r3 ^= r1;
1467    r1 &= r4;
1468    r4 ^= r2;
1469    r2 ^= r3;
1470    r3 &= r0;
1471    r4 |= r1;
1472    r3 ^= r4;
1473    r0 ^= r1;
1474    r4 &= r0;
1475    r1 ^= r3;
1476    r4 ^= r2;
1477    r1 |= r0;
1478    r1 ^= r2;
1479    r0 ^= r3;
1480    r2 = r1;
1481    r1 |= r3;
1482    r1 ^= r0;
1483    subkeys[i] = r1; i+=1;
1484    subkeys[i] = r2; i+=1;
1485    subkeys[i] = r3; i+=1;
1486    subkeys[i] = r4;
1487}
1488
1489fn iv_setup(iv : &[u8], subkeys : &mut[u32; 100], lfsr : &mut[u32; 10], fsm_r : &mut[u32; 2]) {
1490    let mut nonce : [u8; 16] = [0; 16];
1491    if iv.len() < 16 {
1492        copy_memory(&iv, &mut nonce[0..iv.len()]);
1493    } else {
1494        copy_memory(&iv[0..16], &mut nonce[0..16]);
1495    }
1496
1497    let mut r0 : u32;
1498    let mut r1 : u32;
1499    let mut r2 : u32;
1500    let mut r3 : u32;
1501    let mut r4 : u32;
1502    r0 = read_u32_le(&nonce[0..4]);
1503    r1 = read_u32_le(&nonce[4..8]);
1504    r2 = read_u32_le(&nonce[8..12]);
1505    r3 = read_u32_le(&nonce[12..16]);
1506
1507    r0 ^= subkeys[0];
1508    r1 ^= subkeys[0 + 1];
1509    r2 ^= subkeys[0 + 2];
1510    r3 ^= subkeys[0 + 3];
1511    r3 ^= r0;
1512    r4 = r1;
1513    r1 &= r3;
1514    r4 ^= r2;
1515    r1 ^= r0;
1516    r0 |= r3;
1517    r0 ^= r4;
1518    r4 ^= r3;
1519    r3 ^= r2;
1520    r2 |= r1;
1521    r2 ^= r4;
1522    r4 = !r4;
1523    r4 |= r1;
1524    r1 ^= r3;
1525    r1 ^= r4;
1526    r3 |= r0;
1527    r1 ^= r3;
1528    r4 ^= r3;
1529    r1 = r1.rotate_left(13);
1530    r2 = r2.rotate_left(3);
1531    r4 = r4 ^ r1 ^ r2;
1532    r0 = r0 ^ r2 ^ (r1 << 3);
1533    r4 = r4.rotate_left(1);
1534    r0 = r0.rotate_left(7);
1535    r1 = r1 ^ r4 ^ r0;
1536    r2 = r2 ^ r0 ^ (r4 << 7);
1537    r1 = r1.rotate_left(5);
1538    r2 = r2.rotate_left(22);
1539    r1 ^= subkeys[4];
1540    r4 ^= subkeys[4 + 1];
1541    r2 ^= subkeys[4 + 2];
1542    r0 ^= subkeys[4 + 3];
1543    r1 = !r1;
1544    r2 = !r2;
1545    r3 = r1;
1546    r1 &= r4;
1547    r2 ^= r1;
1548    r1 |= r0;
1549    r0 ^= r2;
1550    r4 ^= r1;
1551    r1 ^= r3;
1552    r3 |= r4;
1553    r4 ^= r0;
1554    r2 |= r1;
1555    r2 &= r3;
1556    r1 ^= r4;
1557    r4 &= r2;
1558    r4 ^= r1;
1559    r1 &= r2;
1560    r1 ^= r3;
1561    r2 = r2.rotate_left(13);
1562    r0 = r0.rotate_left(3);
1563    r1 = r1 ^ r2 ^ r0;
1564    r4 = r4 ^ r0 ^ (r2 << 3);
1565    r1 = r1.rotate_left(1);
1566    r4 = r4.rotate_left(7);
1567    r2 = r2 ^ r1 ^ r4;
1568    r0 = r0 ^ r4 ^ (r1 << 7);
1569    r2 = r2.rotate_left(5);
1570    r0 = r0.rotate_left(22);
1571    r2 ^= subkeys[8];
1572    r1 ^= subkeys[8 + 1];
1573    r0 ^= subkeys[8 + 2];
1574    r4 ^= subkeys[8 + 3];
1575    r3 = r2;
1576    r2 &= r0;
1577    r2 ^= r4;
1578    r0 ^= r1;
1579    r0 ^= r2;
1580    r4 |= r3;
1581    r4 ^= r1;
1582    r3 ^= r0;
1583    r1 = r4;
1584    r4 |= r3;
1585    r4 ^= r2;
1586    r2 &= r1;
1587    r3 ^= r2;
1588    r1 ^= r4;
1589    r1 ^= r3;
1590    r3 = !r3;
1591    r0 = r0.rotate_left(13);
1592    r1 = r1.rotate_left(3);
1593    r4 = r4 ^ r0 ^ r1;
1594    r3 = r3 ^ r1 ^ (r0 << 3);
1595    r4 = r4.rotate_left(1);
1596    r3 = r3.rotate_left(7);
1597    r0 = r0 ^ r4 ^ r3;
1598    r1 = r1 ^ r3 ^ (r4 << 7);
1599    r0 = r0.rotate_left(5);
1600    r1 = r1.rotate_left(22);
1601    r0 ^= subkeys[12];
1602    r4 ^= subkeys[12 + 1];
1603    r1 ^= subkeys[12 + 2];
1604    r3 ^= subkeys[12 + 3];
1605    r2 = r0;
1606    r0 |= r3;
1607    r3 ^= r4;
1608    r4 &= r2;
1609    r2 ^= r1;
1610    r1 ^= r3;
1611    r3 &= r0;
1612    r2 |= r4;
1613    r3 ^= r2;
1614    r0 ^= r4;
1615    r2 &= r0;
1616    r4 ^= r3;
1617    r2 ^= r1;
1618    r4 |= r0;
1619    r4 ^= r1;
1620    r0 ^= r3;
1621    r1 = r4;
1622    r4 |= r3;
1623    r4 ^= r0;
1624    r4 = r4.rotate_left(13);
1625    r3 = r3.rotate_left(3);
1626    r1 = r1 ^ r4 ^ r3;
1627    r2 = r2 ^ r3 ^ (r4 << 3);
1628    r1 = r1.rotate_left(1);
1629    r2 = r2.rotate_left(7);
1630    r4 = r4 ^ r1 ^ r2;
1631    r3 = r3 ^ r2 ^ (r1 << 7);
1632    r4 = r4.rotate_left(5);
1633    r3 = r3.rotate_left(22);
1634    r4 ^= subkeys[16];
1635    r1 ^= subkeys[16 + 1];
1636    r3 ^= subkeys[16 + 2];
1637    r2 ^= subkeys[16 + 3];
1638    r1 ^= r2;
1639    r2 = !r2;
1640    r3 ^= r2;
1641    r2 ^= r4;
1642    r0 = r1;
1643    r1 &= r2;
1644    r1 ^= r3;
1645    r0 ^= r2;
1646    r4 ^= r0;
1647    r3 &= r0;
1648    r3 ^= r4;
1649    r4 &= r1;
1650    r2 ^= r4;
1651    r0 |= r1;
1652    r0 ^= r4;
1653    r4 |= r2;
1654    r4 ^= r3;
1655    r3 &= r2;
1656    r4 = !r4;
1657    r0 ^= r3;
1658    r1 = r1.rotate_left(13);
1659    r4 = r4.rotate_left(3);
1660    r0 = r0 ^ r1 ^ r4;
1661    r2 = r2 ^ r4 ^ (r1 << 3);
1662    r0 = r0.rotate_left(1);
1663    r2 = r2.rotate_left(7);
1664    r1 = r1 ^ r0 ^ r2;
1665    r4 = r4 ^ r2 ^ (r0 << 7);
1666    r1 = r1.rotate_left(5);
1667    r4 = r4.rotate_left(22);
1668    r1 ^= subkeys[20];
1669    r0 ^= subkeys[20 + 1];
1670    r4 ^= subkeys[20 + 2];
1671    r2 ^= subkeys[20 + 3];
1672    r1 ^= r0;
1673    r0 ^= r2;
1674    r2 = !r2;
1675    r3 = r0;
1676    r0 &= r1;
1677    r4 ^= r2;
1678    r0 ^= r4;
1679    r4 |= r3;
1680    r3 ^= r2;
1681    r2 &= r0;
1682    r2 ^= r1;
1683    r3 ^= r0;
1684    r3 ^= r4;
1685    r4 ^= r1;
1686    r1 &= r2;
1687    r4 = !r4;
1688    r1 ^= r3;
1689    r3 |= r2;
1690    r4 ^= r3;
1691    r0 = r0.rotate_left(13);
1692    r1 = r1.rotate_left(3);
1693    r2 = r2 ^ r0 ^ r1;
1694    r4 = r4 ^ r1 ^ (r0 << 3);
1695    r2 = r2.rotate_left(1);
1696    r4 = r4.rotate_left(7);
1697    r0 = r0 ^ r2 ^ r4;
1698    r1 = r1 ^ r4 ^ (r2 << 7);
1699    r0 = r0.rotate_left(5);
1700    r1 = r1.rotate_left(22);
1701    r0 ^= subkeys[24];
1702    r2 ^= subkeys[24 + 1];
1703    r1 ^= subkeys[24 + 2];
1704    r4 ^= subkeys[24 + 3];
1705    r1 = !r1;
1706    r3 = r4;
1707    r4 &= r0;
1708    r0 ^= r3;
1709    r4 ^= r1;
1710    r1 |= r3;
1711    r2 ^= r4;
1712    r1 ^= r0;
1713    r0 |= r2;
1714    r1 ^= r2;
1715    r3 ^= r0;
1716    r0 |= r4;
1717    r0 ^= r1;
1718    r3 ^= r4;
1719    r3 ^= r0;
1720    r4 = !r4;
1721    r1 &= r3;
1722    r1 ^= r4;
1723    r0 = r0.rotate_left(13);
1724    r3 = r3.rotate_left(3);
1725    r2 = r2 ^ r0 ^ r3;
1726    r1 = r1 ^ r3 ^ (r0 << 3);
1727    r2 = r2.rotate_left(1);
1728    r1 = r1.rotate_left(7);
1729    r0 = r0 ^ r2 ^ r1;
1730    r3 = r3 ^ r1 ^ (r2 << 7);
1731    r0 = r0.rotate_left(5);
1732    r3 = r3.rotate_left(22);
1733    r0 ^= subkeys[28];
1734    r2 ^= subkeys[28 + 1];
1735    r3 ^= subkeys[28 + 2];
1736    r1 ^= subkeys[28 + 3];
1737    r4 = r2;
1738    r2 |= r3;
1739    r2 ^= r1;
1740    r4 ^= r3;
1741    r3 ^= r2;
1742    r1 |= r4;
1743    r1 &= r0;
1744    r4 ^= r3;
1745    r1 ^= r2;
1746    r2 |= r4;
1747    r2 ^= r0;
1748    r0 |= r4;
1749    r0 ^= r3;
1750    r2 ^= r4;
1751    r3 ^= r2;
1752    r2 &= r0;
1753    r2 ^= r4;
1754    r3 = !r3;
1755    r3 |= r0;
1756    r4 ^= r3;
1757    r4 = r4.rotate_left(13);
1758    r2 = r2.rotate_left(3);
1759    r1 = r1 ^ r4 ^ r2;
1760    r0 = r0 ^ r2 ^ (r4 << 3);
1761    r1 = r1.rotate_left(1);
1762    r0 = r0.rotate_left(7);
1763    r4 = r4 ^ r1 ^ r0;
1764    r2 = r2 ^ r0 ^ (r1 << 7);
1765    r4 = r4.rotate_left(5);
1766    r2 = r2.rotate_left(22);
1767    r4 ^= subkeys[32];
1768    r1 ^= subkeys[32 + 1];
1769    r2 ^= subkeys[32 + 2];
1770    r0 ^= subkeys[32 + 3];
1771    r0 ^= r4;
1772    r3 = r1;
1773    r1 &= r0;
1774    r3 ^= r2;
1775    r1 ^= r4;
1776    r4 |= r0;
1777    r4 ^= r3;
1778    r3 ^= r0;
1779    r0 ^= r2;
1780    r2 |= r1;
1781    r2 ^= r3;
1782    r3 = !r3;
1783    r3 |= r1;
1784    r1 ^= r0;
1785    r1 ^= r3;
1786    r0 |= r4;
1787    r1 ^= r0;
1788    r3 ^= r0;
1789    r1 = r1.rotate_left(13);
1790    r2 = r2.rotate_left(3);
1791    r3 = r3 ^ r1 ^ r2;
1792    r4 = r4 ^ r2 ^ (r1 << 3);
1793    r3 = r3.rotate_left(1);
1794    r4 = r4.rotate_left(7);
1795    r1 = r1 ^ r3 ^ r4;
1796    r2 = r2 ^ r4 ^ (r3 << 7);
1797    r1 = r1.rotate_left(5);
1798    r2 = r2.rotate_left(22);
1799    r1 ^= subkeys[36];
1800    r3 ^= subkeys[36 + 1];
1801    r2 ^= subkeys[36 + 2];
1802    r4 ^= subkeys[36 + 3];
1803    r1 = !r1;
1804    r2 = !r2;
1805    r0 = r1;
1806    r1 &= r3;
1807    r2 ^= r1;
1808    r1 |= r4;
1809    r4 ^= r2;
1810    r3 ^= r1;
1811    r1 ^= r0;
1812    r0 |= r3;
1813    r3 ^= r4;
1814    r2 |= r1;
1815    r2 &= r0;
1816    r1 ^= r3;
1817    r3 &= r2;
1818    r3 ^= r1;
1819    r1 &= r2;
1820    r1 ^= r0;
1821    r2 = r2.rotate_left(13);
1822    r4 = r4.rotate_left(3);
1823    r1 = r1 ^ r2 ^ r4;
1824    r3 = r3 ^ r4 ^ (r2 << 3);
1825    r1 = r1.rotate_left(1);
1826    r3 = r3.rotate_left(7);
1827    r2 = r2 ^ r1 ^ r3;
1828    r4 = r4 ^ r3 ^ (r1 << 7);
1829    r2 = r2.rotate_left(5);
1830    r4 = r4.rotate_left(22);
1831    r2 ^= subkeys[40];
1832    r1 ^= subkeys[40 + 1];
1833    r4 ^= subkeys[40 + 2];
1834    r3 ^= subkeys[40 + 3];
1835    r0 = r2;
1836    r2 &= r4;
1837    r2 ^= r3;
1838    r4 ^= r1;
1839    r4 ^= r2;
1840    r3 |= r0;
1841    r3 ^= r1;
1842    r0 ^= r4;
1843    r1 = r3;
1844    r3 |= r0;
1845    r3 ^= r2;
1846    r2 &= r1;
1847    r0 ^= r2;
1848    r1 ^= r3;
1849    r1 ^= r0;
1850    r0 = !r0;
1851    r4 = r4.rotate_left(13);
1852    r1 = r1.rotate_left(3);
1853    r3 = r3 ^ r4 ^ r1;
1854    r0 = r0 ^ r1 ^ (r4 << 3);
1855    r3 = r3.rotate_left(1);
1856    r0 = r0.rotate_left(7);
1857    r4 = r4 ^ r3 ^ r0;
1858    r1 = r1 ^ r0 ^ (r3 << 7);
1859    r4 = r4.rotate_left(5);
1860    r1 = r1.rotate_left(22);
1861    r4 ^= subkeys[44];
1862    r3 ^= subkeys[44 + 1];
1863    r1 ^= subkeys[44 + 2];
1864    r0 ^= subkeys[44 + 3];
1865    r2 = r4;
1866    r4 |= r0;
1867    r0 ^= r3;
1868    r3 &= r2;
1869    r2 ^= r1;
1870    r1 ^= r0;
1871    r0 &= r4;
1872    r2 |= r3;
1873    r0 ^= r2;
1874    r4 ^= r3;
1875    r2 &= r4;
1876    r3 ^= r0;
1877    r2 ^= r1;
1878    r3 |= r4;
1879    r3 ^= r1;
1880    r4 ^= r0;
1881    r1 = r3;
1882    r3 |= r0;
1883    r3 ^= r4;
1884    r3 = r3.rotate_left(13);
1885    r0 = r0.rotate_left(3);
1886    r1 = r1 ^ r3 ^ r0;
1887    r2 = r2 ^ r0 ^ (r3 << 3);
1888    r1 = r1.rotate_left(1);
1889    r2 = r2.rotate_left(7);
1890    r3 = r3 ^ r1 ^ r2;
1891    r0 = r0 ^ r2 ^ (r1 << 7);
1892    r3 = r3.rotate_left(5);
1893    r0 = r0.rotate_left(22);
1894    lfsr[9] = r3;
1895    lfsr[8] = r1;
1896    lfsr[7] = r0;
1897    lfsr[6] = r2;
1898    r3 ^= subkeys[48];
1899    r1 ^= subkeys[48 + 1];
1900    r0 ^= subkeys[48 + 2];
1901    r2 ^= subkeys[48 + 3];
1902    r1 ^= r2;
1903    r2 = !r2;
1904    r0 ^= r2;
1905    r2 ^= r3;
1906    r4 = r1;
1907    r1 &= r2;
1908    r1 ^= r0;
1909    r4 ^= r2;
1910    r3 ^= r4;
1911    r0 &= r4;
1912    r0 ^= r3;
1913    r3 &= r1;
1914    r2 ^= r3;
1915    r4 |= r1;
1916    r4 ^= r3;
1917    r3 |= r2;
1918    r3 ^= r0;
1919    r0 &= r2;
1920    r3 = !r3;
1921    r4 ^= r0;
1922    r1 = r1.rotate_left(13);
1923    r3 = r3.rotate_left(3);
1924    r4 = r4 ^ r1 ^ r3;
1925    r2 = r2 ^ r3 ^ (r1 << 3);
1926    r4 = r4.rotate_left(1);
1927    r2 = r2.rotate_left(7);
1928    r1 = r1 ^ r4 ^ r2;
1929    r3 = r3 ^ r2 ^ (r4 << 7);
1930    r1 = r1.rotate_left(5);
1931    r3 = r3.rotate_left(22);
1932    r1 ^= subkeys[52];
1933    r4 ^= subkeys[52 + 1];
1934    r3 ^= subkeys[52 + 2];
1935    r2 ^= subkeys[52 + 3];
1936    r1 ^= r4;
1937    r4 ^= r2;
1938    r2 = !r2;
1939    r0 = r4;
1940    r4 &= r1;
1941    r3 ^= r2;
1942    r4 ^= r3;
1943    r3 |= r0;
1944    r0 ^= r2;
1945    r2 &= r4;
1946    r2 ^= r1;
1947    r0 ^= r4;
1948    r0 ^= r3;
1949    r3 ^= r1;
1950    r1 &= r2;
1951    r3 = !r3;
1952    r1 ^= r0;
1953    r0 |= r2;
1954    r3 ^= r0;
1955    r4 = r4.rotate_left(13);
1956    r1 = r1.rotate_left(3);
1957    r2 = r2 ^ r4 ^ r1;
1958    r3 = r3 ^ r1 ^ (r4 << 3);
1959    r2 = r2.rotate_left(1);
1960    r3 = r3.rotate_left(7);
1961    r4 = r4 ^ r2 ^ r3;
1962    r1 = r1 ^ r3 ^ (r2 << 7);
1963    r4 = r4.rotate_left(5);
1964    r1 = r1.rotate_left(22);
1965    r4 ^= subkeys[56];
1966    r2 ^= subkeys[56 + 1];
1967    r1 ^= subkeys[56 + 2];
1968    r3 ^= subkeys[56 + 3];
1969    r1 = !r1;
1970    r0 = r3;
1971    r3 &= r4;
1972    r4 ^= r0;
1973    r3 ^= r1;
1974    r1 |= r0;
1975    r2 ^= r3;
1976    r1 ^= r4;
1977    r4 |= r2;
1978    r1 ^= r2;
1979    r0 ^= r4;
1980    r4 |= r3;
1981    r4 ^= r1;
1982    r0 ^= r3;
1983    r0 ^= r4;
1984    r3 = !r3;
1985    r1 &= r0;
1986    r1 ^= r3;
1987    r4 = r4.rotate_left(13);
1988    r0 = r0.rotate_left(3);
1989    r2 = r2 ^ r4 ^ r0;
1990    r1 = r1 ^ r0 ^ (r4 << 3);
1991    r2 = r2.rotate_left(1);
1992    r1 = r1.rotate_left(7);
1993    r4 = r4 ^ r2 ^ r1;
1994    r0 = r0 ^ r1 ^ (r2 << 7);
1995    r4 = r4.rotate_left(5);
1996    r0 = r0.rotate_left(22);
1997    r4 ^= subkeys[60];
1998    r2 ^= subkeys[60 + 1];
1999    r0 ^= subkeys[60 + 2];
2000    r1 ^= subkeys[60 + 3];
2001    r3 = r2;
2002    r2 |= r0;
2003    r2 ^= r1;
2004    r3 ^= r0;
2005    r0 ^= r2;
2006    r1 |= r3;
2007    r1 &= r4;
2008    r3 ^= r0;
2009    r1 ^= r2;
2010    r2 |= r3;
2011    r2 ^= r4;
2012    r4 |= r3;
2013    r4 ^= r0;
2014    r2 ^= r3;
2015    r0 ^= r2;
2016    r2 &= r4;
2017    r2 ^= r3;
2018    r0 = !r0;
2019    r0 |= r4;
2020    r3 ^= r0;
2021    r3 = r3.rotate_left(13);
2022    r2 = r2.rotate_left(3);
2023    r1 = r1 ^ r3 ^ r2;
2024    r4 = r4 ^ r2 ^ (r3 << 3);
2025    r1 = r1.rotate_left(1);
2026    r4 = r4.rotate_left(7);
2027    r3 = r3 ^ r1 ^ r4;
2028    r2 = r2 ^ r4 ^ (r1 << 7);
2029    r3 = r3.rotate_left(5);
2030    r2 = r2.rotate_left(22);
2031    r3 ^= subkeys[64];
2032    r1 ^= subkeys[64 + 1];
2033    r2 ^= subkeys[64 + 2];
2034    r4 ^= subkeys[64 + 3];
2035    r4 ^= r3;
2036    r0 = r1;
2037    r1 &= r4;
2038    r0 ^= r2;
2039    r1 ^= r3;
2040    r3 |= r4;
2041    r3 ^= r0;
2042    r0 ^= r4;
2043    r4 ^= r2;
2044    r2 |= r1;
2045    r2 ^= r0;
2046    r0 = !r0;
2047    r0 |= r1;
2048    r1 ^= r4;
2049    r1 ^= r0;
2050    r4 |= r3;
2051    r1 ^= r4;
2052    r0 ^= r4;
2053    r1 = r1.rotate_left(13);
2054    r2 = r2.rotate_left(3);
2055    r0 = r0 ^ r1 ^ r2;
2056    r3 = r3 ^ r2 ^ (r1 << 3);
2057    r0 = r0.rotate_left(1);
2058    r3 = r3.rotate_left(7);
2059    r1 = r1 ^ r0 ^ r3;
2060    r2 = r2 ^ r3 ^ (r0 << 7);
2061    r1 = r1.rotate_left(5);
2062    r2 = r2.rotate_left(22);
2063    r1 ^= subkeys[68];
2064    r0 ^= subkeys[68 + 1];
2065    r2 ^= subkeys[68 + 2];
2066    r3 ^= subkeys[68 + 3];
2067    r1 = !r1;
2068    r2 = !r2;
2069    r4 = r1;
2070    r1 &= r0;
2071    r2 ^= r1;
2072    r1 |= r3;
2073    r3 ^= r2;
2074    r0 ^= r1;
2075    r1 ^= r4;
2076    r4 |= r0;
2077    r0 ^= r3;
2078    r2 |= r1;
2079    r2 &= r4;
2080    r1 ^= r0;
2081    r0 &= r2;
2082    r0 ^= r1;
2083    r1 &= r2;
2084    r1 ^= r4;
2085    r2 = r2.rotate_left(13);
2086    r3 = r3.rotate_left(3);
2087    r1 = r1 ^ r2 ^ r3;
2088    r0 = r0 ^ r3 ^ (r2 << 3);
2089    r1 = r1.rotate_left(1);
2090    r0 = r0.rotate_left(7);
2091    r2 = r2 ^ r1 ^ r0;
2092    r3 = r3 ^ r0 ^ (r1 << 7);
2093    r2 = r2.rotate_left(5);
2094    r3 = r3.rotate_left(22);
2095    fsm_r[0] = r2;
2096    lfsr[4] = r1;
2097    fsm_r[1] = r3;
2098    lfsr[5] = r0;
2099    r2 ^= subkeys[72];
2100    r1 ^= subkeys[72 + 1];
2101    r3 ^= subkeys[72 + 2];
2102    r0 ^= subkeys[72 + 3];
2103    r4 = r2;
2104    r2 &= r3;
2105    r2 ^= r0;
2106    r3 ^= r1;
2107    r3 ^= r2;
2108    r0 |= r4;
2109    r0 ^= r1;
2110    r4 ^= r3;
2111    r1 = r0;
2112    r0 |= r4;
2113    r0 ^= r2;
2114    r2 &= r1;
2115    r4 ^= r2;
2116    r1 ^= r0;
2117    r1 ^= r4;
2118    r4 = !r4;
2119    r3 = r3.rotate_left(13);
2120    r1 = r1.rotate_left(3);
2121    r0 = r0 ^ r3 ^ r1;
2122    r4 = r4 ^ r1 ^ (r3 << 3);
2123    r0 = r0.rotate_left(1);
2124    r4 = r4.rotate_left(7);
2125    r3 = r3 ^ r0 ^ r4;
2126    r1 = r1 ^ r4 ^ (r0 << 7);
2127    r3 = r3.rotate_left(5);
2128    r1 = r1.rotate_left(22);
2129    r3 ^= subkeys[76];
2130    r0 ^= subkeys[76 + 1];
2131    r1 ^= subkeys[76 + 2];
2132    r4 ^= subkeys[76 + 3];
2133    r2 = r3;
2134    r3 |= r4;
2135    r4 ^= r0;
2136    r0 &= r2;
2137    r2 ^= r1;
2138    r1 ^= r4;
2139    r4 &= r3;
2140    r2 |= r0;
2141    r4 ^= r2;
2142    r3 ^= r0;
2143    r2 &= r3;
2144    r0 ^= r4;
2145    r2 ^= r1;
2146    r0 |= r3;
2147    r0 ^= r1;
2148    r3 ^= r4;
2149    r1 = r0;
2150    r0 |= r4;
2151    r0 ^= r3;
2152    r0 = r0.rotate_left(13);
2153    r4 = r4.rotate_left(3);
2154    r1 = r1 ^ r0 ^ r4;
2155    r2 = r2 ^ r4 ^ (r0 << 3);
2156    r1 = r1.rotate_left(1);
2157    r2 = r2.rotate_left(7);
2158    r0 = r0 ^ r1 ^ r2;
2159    r4 = r4 ^ r2 ^ (r1 << 7);
2160    r0 = r0.rotate_left(5);
2161    r4 = r4.rotate_left(22);
2162    r0 ^= subkeys[80];
2163    r1 ^= subkeys[80 + 1];
2164    r4 ^= subkeys[80 + 2];
2165    r2 ^= subkeys[80 + 3];
2166    r1 ^= r2;
2167    r2 = !r2;
2168    r4 ^= r2;
2169    r2 ^= r0;
2170    r3 = r1;
2171    r1 &= r2;
2172    r1 ^= r4;
2173    r3 ^= r2;
2174    r0 ^= r3;
2175    r4 &= r3;
2176    r4 ^= r0;
2177    r0 &= r1;
2178    r2 ^= r0;
2179    r3 |= r1;
2180    r3 ^= r0;
2181    r0 |= r2;
2182    r0 ^= r4;
2183    r4 &= r2;
2184    r0 = !r0;
2185    r3 ^= r4;
2186    r1 = r1.rotate_left(13);
2187    r0 = r0.rotate_left(3);
2188    r3 = r3 ^ r1 ^ r0;
2189    r2 = r2 ^ r0 ^ (r1 << 3);
2190    r3 = r3.rotate_left(1);
2191    r2 = r2.rotate_left(7);
2192    r1 = r1 ^ r3 ^ r2;
2193    r0 = r0 ^ r2 ^ (r3 << 7);
2194    r1 = r1.rotate_left(5);
2195    r0 = r0.rotate_left(22);
2196    r1 ^= subkeys[84];
2197    r3 ^= subkeys[84 + 1];
2198    r0 ^= subkeys[84 + 2];
2199    r2 ^= subkeys[84 + 3];
2200    r1 ^= r3;
2201    r3 ^= r2;
2202    r2 = !r2;
2203    r4 = r3;
2204    r3 &= r1;
2205    r0 ^= r2;
2206    r3 ^= r0;
2207    r0 |= r4;
2208    r4 ^= r2;
2209    r2 &= r3;
2210    r2 ^= r1;
2211    r4 ^= r3;
2212    r4 ^= r0;
2213    r0 ^= r1;
2214    r1 &= r2;
2215    r0 = !r0;
2216    r1 ^= r4;
2217    r4 |= r2;
2218    r0 ^= r4;
2219    r3 = r3.rotate_left(13);
2220    r1 = r1.rotate_left(3);
2221    r2 = r2 ^ r3 ^ r1;
2222    r0 = r0 ^ r1 ^ (r3 << 3);
2223    r2 = r2.rotate_left(1);
2224    r0 = r0.rotate_left(7);
2225    r3 = r3 ^ r2 ^ r0;
2226    r1 = r1 ^ r0 ^ (r2 << 7);
2227    r3 = r3.rotate_left(5);
2228    r1 = r1.rotate_left(22);
2229    r3 ^= subkeys[88];
2230    r2 ^= subkeys[88 + 1];
2231    r1 ^= subkeys[88 + 2];
2232    r0 ^= subkeys[88 + 3];
2233    r1 = !r1;
2234    r4 = r0;
2235    r0 &= r3;
2236    r3 ^= r4;
2237    r0 ^= r1;
2238    r1 |= r4;
2239    r2 ^= r0;
2240    r1 ^= r3;
2241    r3 |= r2;
2242    r1 ^= r2;
2243    r4 ^= r3;
2244    r3 |= r0;
2245    r3 ^= r1;
2246    r4 ^= r0;
2247    r4 ^= r3;
2248    r0 = !r0;
2249    r1 &= r4;
2250    r1 ^= r0;
2251    r3 = r3.rotate_left(13);
2252    r4 = r4.rotate_left(3);
2253    r2 = r2 ^ r3 ^ r4;
2254    r1 = r1 ^ r4 ^ (r3 << 3);
2255    r2 = r2.rotate_left(1);
2256    r1 = r1.rotate_left(7);
2257    r3 = r3 ^ r2 ^ r1;
2258    r4 = r4 ^ r1 ^ (r2 << 7);
2259    r3 = r3.rotate_left(5);
2260    r4 = r4.rotate_left(22);
2261    r3 ^= subkeys[92];
2262    r2 ^= subkeys[92 + 1];
2263    r4 ^= subkeys[92 + 2];
2264    r1 ^= subkeys[92 + 3];
2265    r0 = r2;
2266    r2 |= r4;
2267    r2 ^= r1;
2268    r0 ^= r4;
2269    r4 ^= r2;
2270    r1 |= r0;
2271    r1 &= r3;
2272    r0 ^= r4;
2273    r1 ^= r2;
2274    r2 |= r0;
2275    r2 ^= r3;
2276    r3 |= r0;
2277    r3 ^= r4;
2278    r2 ^= r0;
2279    r4 ^= r2;
2280    r2 &= r3;
2281    r2 ^= r0;
2282    r4 = !r4;
2283    r4 |= r3;
2284    r0 ^= r4;
2285    r0 = r0.rotate_left(13);
2286    r2 = r2.rotate_left(3);
2287    r1 = r1 ^ r0 ^ r2;
2288    r3 = r3 ^ r2 ^ (r0 << 3);
2289    r1 = r1.rotate_left(1);
2290    r3 = r3.rotate_left(7);
2291    r0 = r0 ^ r1 ^ r3;
2292    r2 = r2 ^ r3 ^ (r1 << 7);
2293    r0 = r0.rotate_left(5);
2294    r2 = r2.rotate_left(22);
2295    r0 ^= subkeys[96];
2296    r1 ^= subkeys[96 + 1];
2297    r2 ^= subkeys[96 + 2];
2298    r3 ^= subkeys[96 + 3];
2299    lfsr[3] = r0;
2300    lfsr[2] = r1;
2301    lfsr[1] = r2;
2302    lfsr[0] = r3;
2303}
2304
2305
2306impl SynchronousStreamCipher for Sosemanuk {
2307    fn process(&mut self, input: &[u8], output: &mut [u8]) {
2308        assert!(input.len() == output.len());
2309        for (x, y) in input.iter().zip(output.iter_mut()) {
2310            *y = *x ^ self.next();
2311        }
2312    }
2313}
2314
2315impl Encryptor for Sosemanuk {
2316    fn encrypt(&mut self, input: &mut RefReadBuffer, output: &mut RefWriteBuffer, _: bool)
2317            -> Result<BufferResult, SymmetricCipherError> {
2318        symm_enc_or_dec(self, input, output)
2319    }
2320}
2321
2322impl Decryptor for Sosemanuk {
2323    fn decrypt(&mut self, input: &mut RefReadBuffer, output: &mut RefWriteBuffer, _: bool)
2324            -> Result<BufferResult, SymmetricCipherError> {
2325        symm_enc_or_dec(self, input, output)
2326    }
2327}
2328
2329
2330#[cfg(test)]
2331mod test {
2332    use sosemanuk::Sosemanuk;
2333    use symmetriccipher::SynchronousStreamCipher;
2334    use serialize::hex::{FromHex};
2335
2336    // Vectors from http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/sosemanuk/unverified.test-vectors?rev=108&view=markup
2337
2338    #[test]
2339    fn test_sosemanuk_ecrypt_set_1_vector_0() {
2340        let key = "8000000000000000000000000000000000000000000000000000000000000000".from_hex().unwrap();
2341        let nonce = "00000000000000000000000000000000".from_hex().unwrap();
2342
2343        let input = [0u8; 64];
2344        let expected_output_hex = "1782FABFF497A0E89E16E1BCF22F0FE8AA8C566D293AA35B2425E4F26E31C3E7701C08A0D614AF3D3861A7DFF7D6A38A0EFE84A29FADF68D390A3D15B75C972D";
2345        let expected_output = expected_output_hex.from_hex().unwrap();
2346
2347        let mut output = [0u8; 64];
2348
2349        let mut sosemanuk = Sosemanuk::new(key.as_ref(), nonce.as_ref());
2350        sosemanuk.process(&input, &mut output);
2351        let expected: &[u8] = expected_output.as_ref();
2352        assert!(output.as_ref() == expected);
2353    }
2354
2355    #[test]
2356    fn test_sosemanuk_ecrypt_set_2_vector_63() {
2357        let key = "3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F".from_hex().unwrap();
2358        let nonce = "00000000000000000000000000000000".from_hex().unwrap();
2359
2360        let input = [0u8; 64];
2361        let expected_output_hex = "7D755F30A2B747A50D7D28147EDF0B3E3FAB6856A7373C7306C00D1D4076969354D7AB4343C0115E7839502C5C699ED06DB119968AEBFD08D8B968A7161D613F";
2362        let expected_output = expected_output_hex.from_hex().unwrap();
2363
2364        let mut output = [0u8; 64];
2365
2366        let mut sosemanuk = Sosemanuk::new(key.as_ref(), nonce.as_ref());
2367        sosemanuk.process(&input, &mut output);
2368        let expected: &[u8] = expected_output.as_ref();
2369        assert!(output.as_ref() == expected);
2370    }
2371
2372    #[test]
2373    fn test_sosemanuk_ecrypt_set_2_vector_90() {
2374        let key = "5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A".from_hex().unwrap();
2375        let nonce = "00000000000000000000000000000000".from_hex().unwrap();
2376
2377        let input = [0u8; 64];
2378        let expected_output_hex = "F5D7D72686322D1751AFD16A1DD98282D2B9A1EE0C305DF52F86AE1B831E90C22E2DE089CEE656A992736385D9135B823B3611098674BF820986A4342B89ABF7";
2379        let expected_output = expected_output_hex.from_hex().unwrap();
2380
2381        let mut output = [0u8; 64];
2382
2383        let mut sosemanuk = Sosemanuk::new(key.as_ref(), nonce.as_ref());
2384        sosemanuk.process(&input, &mut output);
2385        let expected: &[u8] = expected_output.as_ref();
2386        assert!(output.as_ref() == expected);
2387    }
2388
2389    #[test]
2390    fn test_sosemanuk_ecrypt_set_3_vector_135() {
2391        let key = "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4".from_hex().unwrap();
2392        let nonce = "00000000000000000000000000000000".from_hex().unwrap();
2393
2394        let input = [0u8; 64];
2395        let expected_output_hex = "9D7EE5A10BBB0756D66B8DAA5AE08F41B05C9E7C6B13532EAA81F224282B61C66DEEE5AF6251DB26C49B865C5AD4250AE89787FC86C35409CF2986CF820293AA";
2396        let expected_output = expected_output_hex.from_hex().unwrap();
2397
2398        let mut output = [0u8; 64];
2399
2400        let mut sosemanuk = Sosemanuk::new(key.as_ref(), nonce.as_ref());
2401        sosemanuk.process(&input, &mut output);
2402        let expected: &[u8] = expected_output.as_ref();
2403        assert!(output.as_ref() == expected);
2404    }
2405
2406    #[test]
2407    fn test_sosemanuk_ecrypt_set_3_vector_207() {
2408        let key = "CFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEE".from_hex().unwrap();
2409        let nonce = "00000000000000000000000000000000".from_hex().unwrap();
2410
2411        let input = [0u8; 64];
2412        let expected_output_hex = "F028923659C6C0A17065E013368D93EBCF2F4FD892B6E27E104EF0A2605708EA26336AE966D5058BC144F7954FE2FC3C258F00734AA5BEC8281814B746197084";
2413        let expected_output = expected_output_hex.from_hex().unwrap();
2414
2415        let mut output = [0u8; 64];
2416
2417        let mut sosemanuk = Sosemanuk::new(key.as_ref(), nonce.as_ref());
2418        sosemanuk.process(&input, &mut output);
2419        let expected: &[u8] = expected_output.as_ref();
2420        assert!(output.as_ref() == expected);
2421    }
2422
2423    #[test]
2424    fn test_sosemanuk_ecrypt_set_6_vector_3() {
2425        let key = "0F62B5085BAE0154A7FA4DA0F34699EC3F92E5388BDE3184D72A7DD02376C91C".from_hex().unwrap();
2426        let nonce = "288FF65DC42B92F960C72E95FC63CA31".from_hex().unwrap();
2427
2428        let input = [0u8; 64];
2429        let expected_output_hex = "1FC4F2E266B21C24FDDB3492D40A3FA6DE32CDF13908511E84420ABDFA1D3B0FEC600F83409C57CBE0394B90CDB1D759243EFD8B8E2AB7BC453A8D8A3515183E";
2430        let expected_output = expected_output_hex.from_hex().unwrap();
2431
2432        let mut output = [0u8; 64];
2433
2434        let mut sosemanuk = Sosemanuk::new(key.as_ref(), nonce.as_ref());
2435        sosemanuk.process(&input, &mut output);
2436        let expected: &[u8] = expected_output.as_ref();
2437        assert!(output.as_ref() == expected);
2438    }
2439
2440    // From TEST_VECTOR_128.txt from reference C implementation
2441
2442    #[test]
2443    fn test_sosemanuk_vector128_test1() {
2444        let key = "A7C083FEB7".from_hex().unwrap();
2445        let nonce = "00112233445566778899AABBCCDDEEFF".from_hex().unwrap();
2446
2447        let input = [0u8; 160];
2448        let expected_output_hex = "FE81D2162C9A100D04895C454A77515BBE6A431A935CB90E2221EBB7EF502328943539492EFF6310C871054C2889CC728F82E86B1AFFF4334B6127A13A155C75151630BD482EB673FF5DB477FA6C53EBE1A4EC38C23C5400C315455D93A2ACED9598604727FA340D5F2A8BD757B77833F74BD2BC049313C80616B4A06268AE350DB92EEC4FA56C171374A67A80C006D0EAD048CE7B640F17D3D5A62D1F251C21";
2449        let expected_output = expected_output_hex.from_hex().unwrap();
2450
2451        let mut output = [0u8; 160];
2452
2453        let mut sosemanuk = Sosemanuk::new(key.as_ref(), nonce.as_ref());
2454        sosemanuk.process(&input, &mut output);
2455        let expected: &[u8] = expected_output.as_ref();
2456        assert!(output.as_ref() == expected);
2457    }
2458
2459    #[test]
2460    fn test_sosemanuk_vector128_test2() {
2461        let key = "00112233445566778899AABBCCDDEEFF".from_hex().unwrap();
2462        let nonce = "8899AABBCCDDEEFF0011223344556677".from_hex().unwrap();
2463
2464        let input = [0u8; 160];
2465        let expected_output_hex = "FA61DBEB71178131A77C714BD2EABF4E1394207A25698AA1308F2F063A0F760604CF67569BA59A3DFAD7F00145C78D29C5FFE5F964950486424451952C84039D234D9C37EECBBCA1EBFB0DD16EA1194A6AFC1A460E33E33FE8D55C48977079C687810D74FEDDEE1B3986218FB1E1C1765E4DF64D7F6911C19A270C59C74B24461717F86CE3B11808FACD4F2E714168DA44CF6360D54DDA2241BCB79401A4EDCC";
2466        let expected_output = expected_output_hex.from_hex().unwrap();
2467
2468        let mut output = [0u8; 160];
2469
2470        let mut sosemanuk = Sosemanuk::new(key.as_ref(), nonce.as_ref());
2471        sosemanuk.process(&input, &mut output);
2472        let expected: &[u8] = expected_output.as_ref();
2473        assert!(output.as_ref() == expected);
2474    }
2475}
2476
2477#[cfg(all(test, feature = "with-bench"))]
2478mod bench {
2479    use test::Bencher;
2480    use symmetriccipher::SynchronousStreamCipher;
2481    use sosemanuk::Sosemanuk;
2482
2483    #[bench]
2484    pub fn sosemanuk_10(bh: & mut Bencher) {
2485        let mut sosemanuk = Sosemanuk::new(&[0; 32], &[0; 16]);
2486        let input = [1u8; 10];
2487        let mut output = [0u8; 10];
2488        bh.iter( || {
2489            sosemanuk.process(&input, &mut output);
2490        });
2491        bh.bytes = input.len() as u64;
2492    }
2493
2494    #[bench]
2495    pub fn sosemanuk_1k(bh: & mut Bencher) {
2496        let mut sosemanuk = Sosemanuk::new(&[0; 32], &[0; 16]);
2497        let input = [1u8; 1024];
2498        let mut output = [0u8; 1024];
2499        bh.iter( || {
2500            sosemanuk.process(&input, &mut output);
2501        });
2502        bh.bytes = input.len() as u64;
2503    }
2504
2505    #[bench]
2506    pub fn sosemanuk_64k(bh: & mut Bencher) {
2507        let mut sosemanuk = Sosemanuk::new(&[0; 32], &[0; 16]);
2508        let input = [1u8; 65536];
2509        let mut output = [0u8; 65536];
2510        bh.iter( || {
2511            sosemanuk.process(&input, &mut output);
2512        });
2513        bh.bytes = input.len() as u64;
2514    }
2515}