* all: added a new access_filter module: record + one hotkey to start/stop
[vlc.git] / modules / mux / mpeg / csa.c
1 /*****************************************************************************
2  * libcsa.c: CSA scrambler/descrambler
3  *****************************************************************************
4  * Copyright (C) 2004 Laurent Aimar
5  * $Id$
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*
25  * XXX: A great part is just a copy/past of deCSA but I can't find the
26  * author and the license. If there is a problem with it please e-mail me.
27  */
28
29 #include <stdlib.h>
30 #include <vlc/vlc.h>
31
32 #include "csa.h"
33
34 struct csa_t
35 {
36     /* odd and even keys */
37     uint8_t o_ck[8];
38     uint8_t e_ck[8];
39
40     uint8_t o_kk[57];
41     uint8_t e_kk[57];
42
43     /* cypher state */
44     int     A[11];
45     int     B[11];
46     int     X, Y, Z;
47     int     D, E, F;
48     int     p, q, r;
49 };
50
51 static void csa_ComputeKey( uint8_t kk[57], uint8_t ck[8] );
52
53 static void csa_StreamCypher( csa_t *c, int b_init, uint8_t *ck, uint8_t *sb, uint8_t *cb );
54
55 static void csa_BlockDecypher( uint8_t kk[57], uint8_t ib[8], uint8_t bd[8] );
56 static void csa_BlockCypher( uint8_t kk[57], uint8_t bd[8], uint8_t ib[8] );
57
58 /*****************************************************************************
59  * csa_New:
60  *****************************************************************************/
61 csa_t *csa_New()
62 {
63     csa_t *c = malloc( sizeof( csa_t ) );
64     memset( c, 0, sizeof( csa_t ) );
65
66     return c;
67 }
68
69 /*****************************************************************************
70  * csa_Delete:
71  *****************************************************************************/
72 void   csa_Delete( csa_t *c )
73 {
74     free( c );
75 }
76
77 /*****************************************************************************
78  * csa_SetCW:
79  *****************************************************************************/
80 void csa_SetCW( csa_t *c, uint8_t o_ck[8], uint8_t e_ck[8] )
81 {
82     memcpy( c->o_ck, o_ck, 8 );
83     csa_ComputeKey( c->o_kk, o_ck );
84
85     memcpy( c->e_ck, e_ck, 8 );
86     csa_ComputeKey( c->e_kk, e_ck );
87 }
88
89 /*****************************************************************************
90  * csa_Decrypt:
91  *****************************************************************************/
92 void csa_Decrypt( csa_t *c, uint8_t *pkt )
93 {
94     uint8_t *ck;
95     uint8_t *kk;
96
97     uint8_t  ib[8], stream[8], block[8];
98
99     int     i_hdr, i_residue;
100     int     i, j, n;
101
102     /* transport scrambling control */
103     if( (pkt[3]&0x80) == 0 )
104     {
105         /* not scrambled */
106         return;
107     }
108     if( pkt[3]&0x40 )
109     {
110         ck = c->o_ck;
111         kk = c->o_kk;
112     }
113     else
114     {
115         ck = c->e_ck;
116         kk = c->e_kk;
117     }
118
119     /* clear transport scrambling control */
120     pkt[3] &= 0x3f;
121
122     i_hdr = 4;
123     if( pkt[3]&0x20 )
124     {
125         /* skip adaption field */
126         i_hdr += pkt[4] + 1;
127     }
128
129     if( 188 - i_hdr < 8 )
130         return;
131
132     /* init csa state */
133     csa_StreamCypher( c, 1, ck, &pkt[i_hdr], ib );
134
135     /* */
136     n = (188 - i_hdr) / 8;
137     i_residue = (188 - i_hdr) % 8;
138     for( i = 1; i < n + 1; i++ )
139     {
140         csa_BlockDecypher( kk, ib, block );
141         if( i != n )
142         {
143             csa_StreamCypher( c, 0, ck, NULL, stream );
144             for( j = 0; j < 8; j++ )
145             {
146                 /* xor ib with stream */
147                 ib[j] = pkt[i_hdr+8*i+j] ^ stream[j];
148             }
149         }
150         else
151         {
152             /* last block */
153             for( j = 0; j < 8; j++ )
154             {
155                 ib[j] = 0;
156             }
157         }
158         /* xor ib with block */
159         for( j = 0; j < 8; j++ )
160         {
161             pkt[i_hdr+8*(i-1)+j] = ib[j] ^ block[j];
162         }
163     }
164
165     if( i_residue > 0 )
166     {
167         csa_StreamCypher( c, 0, ck, NULL, stream );
168         for( j = 0; j < i_residue; j++ )
169         {
170             pkt[188 - i_residue + j] ^= stream[j];
171         }
172     }
173 }
174
175 /*****************************************************************************
176  * csa_Encrypt:
177  *****************************************************************************/
178 void csa_Encrypt( csa_t *c, uint8_t *pkt, int b_odd )
179 {
180     uint8_t *ck;
181     uint8_t *kk;
182
183     int i, j;
184     int i_hdr;
185     uint8_t  ib[184/8+2][8], stream[8], block[8];
186     int n, i_residue;
187
188     /* set transport scrambling control */
189     pkt[3] |= 0x80;
190     if( b_odd )
191     {
192         pkt[3] |= 0x40;
193     }
194
195     if( b_odd )
196     {
197         ck = c->o_ck;
198         kk = c->o_kk;
199     }
200     else
201     {
202         ck = c->e_ck;
203         kk = c->e_kk;
204     }
205
206     /* hdr len */
207     i_hdr = 4;
208     if( pkt[3]&0x20 )
209     {
210         /* skip adaption field */
211         i_hdr += pkt[4] + 1;
212     }
213     n = (188 - i_hdr) / 8;
214     i_residue = (188 - i_hdr) % 8;
215
216     if( n == 0 )
217     {
218         pkt[3] &= 0x3f;
219         return;
220     }
221
222     /* */
223     for( i = 0; i < 8; i++ )
224     {
225         ib[n+1][i] = 0;
226     }
227     for( i = n; i  > 0; i-- )
228     {
229         for( j = 0; j < 8; j++ )
230         {
231             block[j] = pkt[i_hdr+8*(i-1)+j] ^ib[i+1][j];
232         }
233         csa_BlockCypher( kk, block, ib[i] );
234     }
235
236     /* init csa state */
237     csa_StreamCypher( c, 1, ck, ib[1], stream );
238
239     for( i = 0; i < 8; i++ )
240     {
241         pkt[i_hdr+i] = ib[1][i];
242     }
243     for( i = 2; i < n+1; i++ )
244     {
245         csa_StreamCypher( c, 0, ck, NULL, stream );
246         for( j = 0; j < 8; j++ )
247         {
248             pkt[i_hdr+8*(i-1)+j] = ib[i][j] ^ stream[j];
249         }
250     }
251     if( i_residue > 0 )
252     {
253         csa_StreamCypher( c, 0, ck, NULL, stream );
254         for( j = 0; j < i_residue; j++ )
255         {
256             pkt[188 - i_residue + j] ^= stream[j];
257         }
258     }
259 }
260
261 /*****************************************************************************
262  * Divers
263  *****************************************************************************/
264 static const uint8_t key_perm[0x40] =
265 {
266     0x12,0x24,0x09,0x07,0x2A,0x31,0x1D,0x15,0x1C,0x36,0x3E,0x32,0x13,0x21,0x3B,0x40,
267     0x18,0x14,0x25,0x27,0x02,0x35,0x1B,0x01,0x22,0x04,0x0D,0x0E,0x39,0x28,0x1A,0x29,
268     0x33,0x23,0x34,0x0C,0x16,0x30,0x1E,0x3A,0x2D,0x1F,0x08,0x19,0x17,0x2F,0x3D,0x11,
269     0x3C,0x05,0x38,0x2B,0x0B,0x06,0x0A,0x2C,0x20,0x3F,0x2E,0x0F,0x03,0x26,0x10,0x37,
270 };
271
272 static void csa_ComputeKey( uint8_t kk[57], uint8_t ck[8] )
273 {
274     int i,j,k;
275     int bit[64];
276     int newbit[64];
277     int kb[9][8];
278
279     /* from a cw create 56 key bytes, here kk[1..56] */
280
281     /* load ck into kb[7][1..8] */
282     for( i = 0; i < 8; i++ )
283     {
284         kb[7][i+1] = ck[i];
285     }
286
287     /* calculate all kb[6..1][*] */
288     for( i = 0; i < 7; i++ )
289     {
290         /* do a 64 bit perm on kb */
291         for( j = 0; j < 8; j++ )
292         {
293             for( k = 0; k < 8; k++ )
294             {
295                 bit[j*8+k] = (kb[7-i][1+j] >> (7-k)) & 1;
296                 newbit[key_perm[j*8+k]-1] = bit[j*8+k];
297             }
298         }
299         for( j = 0; j < 8; j++ )
300         {
301             kb[6-i][1+j] = 0;
302             for( k = 0; k < 8; k++ )
303             {
304                 kb[6-i][1+j] |= newbit[j*8+k] << (7-k);
305             }
306         }
307     }
308
309     /* xor to give kk */
310     for( i = 0; i < 7; i++ )
311     {
312         for( j = 0; j < 8; j++ )
313         {
314             kk[1+i*8+j] = kb[1+i][1+j] ^ i;
315         }
316     }
317 }
318
319
320 static const int sbox1[0x20] = {2,0,1,1,2,3,3,0, 3,2,2,0,1,1,0,3, 0,3,3,0,2,2,1,1, 2,2,0,3,1,1,3,0};
321 static const int sbox2[0x20] = {3,1,0,2,2,3,3,0, 1,3,2,1,0,0,1,2, 3,1,0,3,3,2,0,2, 0,0,1,2,2,1,3,1};
322 static const int sbox3[0x20] = {2,0,1,2,2,3,3,1, 1,1,0,3,3,0,2,0, 1,3,0,1,3,0,2,2, 2,0,1,2,0,3,3,1};
323 static const int sbox4[0x20] = {3,1,2,3,0,2,1,2, 1,2,0,1,3,0,0,3, 1,0,3,1,2,3,0,3, 0,3,2,0,1,2,2,1};
324 static const int sbox5[0x20] = {2,0,0,1,3,2,3,2, 0,1,3,3,1,0,2,1, 2,3,2,0,0,3,1,1, 1,0,3,2,3,1,0,2};
325 static const int sbox6[0x20] = {0,1,2,3,1,2,2,0, 0,1,3,0,2,3,1,3, 2,3,0,2,3,0,1,1, 2,1,1,2,0,3,3,0};
326 static const int sbox7[0x20] = {0,3,2,2,3,0,0,1, 3,0,1,3,1,2,2,1, 1,0,3,3,0,1,1,2, 2,3,1,0,2,3,0,2};
327
328 static void csa_StreamCypher( csa_t *c, int b_init, uint8_t *ck, uint8_t *sb, uint8_t *cb )
329 {
330     int i,j, k;
331     int extra_B;
332     int s1,s2,s3,s4,s5,s6,s7;
333     int next_A1;
334     int next_B1;
335     int next_E;
336
337     if( b_init )
338     {
339         // load first 32 bits of CK into A[1]..A[8]
340         // load last  32 bits of CK into B[1]..B[8]
341         // all other regs = 0
342         for( i = 0; i < 4; i++ )
343         {
344             c->A[1+2*i+0] = ( ck[i] >> 4 )&0x0f;
345             c->A[1+2*i+1] = ( ck[i] >> 0 )&0x0f;
346
347             c->B[1+2*i+0] = ( ck[4+i] >> 4 )&0x0f;
348             c->B[1+2*i+1] = ( ck[4+i] >> 0 )&0x0f;
349         }
350
351         c->A[9] = c->A[10] = 0;
352         c->B[9] = c->B[10] = 0;
353
354         c->X = c->Y = c->Z = 0;
355         c->D = c->E = c->F = 0;
356         c->p = c->q = c->r = 0;
357     }
358
359     // 8 bytes per operation
360     for( i = 0; i < 8; i++ )
361     {
362         int op = 0;
363         int in1 = 0;    /* gcc warn */
364         int in2 = 0;
365
366         if( b_init )
367         {
368             in1 = ( sb[i] >> 4 )&0x0f;
369             in2 = ( sb[i] >> 0 )&0x0f;
370         }
371
372         // 2 bits per iteration
373         for( j = 0; j < 4; j++ )
374         {
375             // from A[1]..A[10], 35 bits are selected as inputs to 7 s-boxes
376             // 5 bits input per s-box, 2 bits output per s-box
377             s1 = sbox1[ (((c->A[4]>>0)&1)<<4) | (((c->A[1]>>2)&1)<<3) | (((c->A[6]>>1)&1)<<2) | (((c->A[7]>>3)&1)<<1) | (((c->A[9]>>0)&1)<<0) ];
378             s2 = sbox2[ (((c->A[2]>>1)&1)<<4) | (((c->A[3]>>2)&1)<<3) | (((c->A[6]>>3)&1)<<2) | (((c->A[7]>>0)&1)<<1) | (((c->A[9]>>1)&1)<<0) ];
379             s3 = sbox3[ (((c->A[1]>>3)&1)<<4) | (((c->A[2]>>0)&1)<<3) | (((c->A[5]>>1)&1)<<2) | (((c->A[5]>>3)&1)<<1) | (((c->A[6]>>2)&1)<<0) ];
380             s4 = sbox4[ (((c->A[3]>>3)&1)<<4) | (((c->A[1]>>1)&1)<<3) | (((c->A[2]>>3)&1)<<2) | (((c->A[4]>>2)&1)<<1) | (((c->A[8]>>0)&1)<<0) ];
381             s5 = sbox5[ (((c->A[5]>>2)&1)<<4) | (((c->A[4]>>3)&1)<<3) | (((c->A[6]>>0)&1)<<2) | (((c->A[8]>>1)&1)<<1) | (((c->A[9]>>2)&1)<<0) ];
382             s6 = sbox6[ (((c->A[3]>>1)&1)<<4) | (((c->A[4]>>1)&1)<<3) | (((c->A[5]>>0)&1)<<2) | (((c->A[7]>>2)&1)<<1) | (((c->A[9]>>3)&1)<<0) ];
383             s7 = sbox7[ (((c->A[2]>>2)&1)<<4) | (((c->A[3]>>0)&1)<<3) | (((c->A[7]>>1)&1)<<2) | (((c->A[8]>>2)&1)<<1) | (((c->A[8]>>3)&1)<<0) ];
384
385             /* use 4x4 xor to produce extra nibble for T3 */
386             extra_B = ( ((c->B[3]&1)<<3) ^ ((c->B[6]&2)<<2) ^ ((c->B[7]&4)<<1) ^ ((c->B[9]&8)>>0) ) |
387                       ( ((c->B[6]&1)<<2) ^ ((c->B[8]&2)<<1) ^ ((c->B[3]&8)>>1) ^ ((c->B[4]&4)>>0) ) |
388                       ( ((c->B[5]&8)>>2) ^ ((c->B[8]&4)>>1) ^ ((c->B[4]&1)<<1) ^ ((c->B[5]&2)>>0) ) |
389                       ( ((c->B[9]&4)>>2) ^ ((c->B[6]&8)>>3) ^ ((c->B[3]&2)>>1) ^ ((c->B[8]&1)>>0) ) ;
390
391             // T1 = xor all inputs
392             // in1,in2, D are only used in T1 during initialisation, not generation
393             next_A1 = c->A[10] ^ c->X;
394             if( b_init ) next_A1 = next_A1 ^ c->D ^ ((j % 2) ? in2 : in1);
395
396             // T2 =  xor all inputs
397             // in1,in2 are only used in T1 during initialisation, not generation
398             // if p=0, use this, if p=1, rotate the result left
399             next_B1 = c->B[7] ^ c->B[10] ^ c->Y;
400             if( b_init) next_B1 = next_B1 ^ ((j % 2) ? in1 : in2);
401
402             // if p=1, rotate left
403             if( c->p ) next_B1 = ( (next_B1 << 1) | ((next_B1 >> 3) & 1) ) & 0xf;
404
405             // T3 = xor all inputs
406             c->D = c->E ^ c->Z ^ extra_B;
407
408             // T4 = sum, carry of Z + E + r
409             next_E = c->F;
410             if( c->q )
411             {
412                 c->F = c->Z + c->E + c->r;
413                 // r is the carry
414                 c->r = (c->F >> 4) & 1;
415                 c->F = c->F & 0x0f;
416             }
417             else
418             {
419                 c->F = c->E;
420             }
421             c->E = next_E;
422
423             for( k = 10; k > 1; k-- )
424             {
425                 c->A[k] = c->A[k-1];
426                 c->B[k] = c->B[k-1];
427             }
428             c->A[1] = next_A1;
429             c->B[1] = next_B1;
430
431             c->X = ((s4&1)<<3) | ((s3&1)<<2) | (s2&2) | ((s1&2)>>1);
432             c->Y = ((s6&1)<<3) | ((s5&1)<<2) | (s4&2) | ((s3&2)>>1);
433             c->Z = ((s2&1)<<3) | ((s1&1)<<2) | (s6&2) | ((s5&2)>>1);
434             c->p = (s7&2)>>1;
435             c->q = (s7&1);
436
437             // require 4 loops per output byte
438             // 2 output bits are a function of the 4 bits of D
439             // xor 2 by 2
440             op = (op << 2)^ ( (((c->D^(c->D>>1))>>1)&2) | ((c->D^(c->D>>1))&1) );
441         }
442         // return input data during init
443         cb[i] = b_init ? sb[i] : op;
444     }
445 }
446
447
448 // block - sbox
449 static const uint8_t block_sbox[256] =
450 {
451     0x3A,0xEA,0x68,0xFE,0x33,0xE9,0x88,0x1A,0x83,0xCF,0xE1,0x7F,0xBA,0xE2,0x38,0x12,
452     0xE8,0x27,0x61,0x95,0x0C,0x36,0xE5,0x70,0xA2,0x06,0x82,0x7C,0x17,0xA3,0x26,0x49,
453     0xBE,0x7A,0x6D,0x47,0xC1,0x51,0x8F,0xF3,0xCC,0x5B,0x67,0xBD,0xCD,0x18,0x08,0xC9,
454     0xFF,0x69,0xEF,0x03,0x4E,0x48,0x4A,0x84,0x3F,0xB4,0x10,0x04,0xDC,0xF5,0x5C,0xC6,
455     0x16,0xAB,0xAC,0x4C,0xF1,0x6A,0x2F,0x3C,0x3B,0xD4,0xD5,0x94,0xD0,0xC4,0x63,0x62,
456     0x71,0xA1,0xF9,0x4F,0x2E,0xAA,0xC5,0x56,0xE3,0x39,0x93,0xCE,0x65,0x64,0xE4,0x58,
457     0x6C,0x19,0x42,0x79,0xDD,0xEE,0x96,0xF6,0x8A,0xEC,0x1E,0x85,0x53,0x45,0xDE,0xBB,
458     0x7E,0x0A,0x9A,0x13,0x2A,0x9D,0xC2,0x5E,0x5A,0x1F,0x32,0x35,0x9C,0xA8,0x73,0x30,
459
460     0x29,0x3D,0xE7,0x92,0x87,0x1B,0x2B,0x4B,0xA5,0x57,0x97,0x40,0x15,0xE6,0xBC,0x0E,
461     0xEB,0xC3,0x34,0x2D,0xB8,0x44,0x25,0xA4,0x1C,0xC7,0x23,0xED,0x90,0x6E,0x50,0x00,
462     0x99,0x9E,0x4D,0xD9,0xDA,0x8D,0x6F,0x5F,0x3E,0xD7,0x21,0x74,0x86,0xDF,0x6B,0x05,
463     0x8E,0x5D,0x37,0x11,0xD2,0x28,0x75,0xD6,0xA7,0x77,0x24,0xBF,0xF0,0xB0,0x02,0xB7,
464     0xF8,0xFC,0x81,0x09,0xB1,0x01,0x76,0x91,0x7D,0x0F,0xC8,0xA0,0xF2,0xCB,0x78,0x60,
465     0xD1,0xF7,0xE0,0xB5,0x98,0x22,0xB3,0x20,0x1D,0xA6,0xDB,0x7B,0x59,0x9F,0xAE,0x31,
466     0xFB,0xD3,0xB6,0xCA,0x43,0x72,0x07,0xF4,0xD8,0x41,0x14,0x55,0x0D,0x54,0x8B,0xB9,
467     0xAD,0x46,0x0B,0xAF,0x80,0x52,0x2C,0xFA,0x8C,0x89,0x66,0xFD,0xB2,0xA9,0x9B,0xC0,
468 };
469
470 // block - perm
471 static const uint8_t block_perm[256] =
472 {
473     0x00,0x02,0x80,0x82,0x20,0x22,0xA0,0xA2, 0x10,0x12,0x90,0x92,0x30,0x32,0xB0,0xB2,
474     0x04,0x06,0x84,0x86,0x24,0x26,0xA4,0xA6, 0x14,0x16,0x94,0x96,0x34,0x36,0xB4,0xB6,
475     0x40,0x42,0xC0,0xC2,0x60,0x62,0xE0,0xE2, 0x50,0x52,0xD0,0xD2,0x70,0x72,0xF0,0xF2,
476     0x44,0x46,0xC4,0xC6,0x64,0x66,0xE4,0xE6, 0x54,0x56,0xD4,0xD6,0x74,0x76,0xF4,0xF6,
477     0x01,0x03,0x81,0x83,0x21,0x23,0xA1,0xA3, 0x11,0x13,0x91,0x93,0x31,0x33,0xB1,0xB3,
478     0x05,0x07,0x85,0x87,0x25,0x27,0xA5,0xA7, 0x15,0x17,0x95,0x97,0x35,0x37,0xB5,0xB7,
479     0x41,0x43,0xC1,0xC3,0x61,0x63,0xE1,0xE3, 0x51,0x53,0xD1,0xD3,0x71,0x73,0xF1,0xF3,
480     0x45,0x47,0xC5,0xC7,0x65,0x67,0xE5,0xE7, 0x55,0x57,0xD5,0xD7,0x75,0x77,0xF5,0xF7,
481
482     0x08,0x0A,0x88,0x8A,0x28,0x2A,0xA8,0xAA, 0x18,0x1A,0x98,0x9A,0x38,0x3A,0xB8,0xBA,
483     0x0C,0x0E,0x8C,0x8E,0x2C,0x2E,0xAC,0xAE, 0x1C,0x1E,0x9C,0x9E,0x3C,0x3E,0xBC,0xBE,
484     0x48,0x4A,0xC8,0xCA,0x68,0x6A,0xE8,0xEA, 0x58,0x5A,0xD8,0xDA,0x78,0x7A,0xF8,0xFA,
485     0x4C,0x4E,0xCC,0xCE,0x6C,0x6E,0xEC,0xEE, 0x5C,0x5E,0xDC,0xDE,0x7C,0x7E,0xFC,0xFE,
486     0x09,0x0B,0x89,0x8B,0x29,0x2B,0xA9,0xAB, 0x19,0x1B,0x99,0x9B,0x39,0x3B,0xB9,0xBB,
487     0x0D,0x0F,0x8D,0x8F,0x2D,0x2F,0xAD,0xAF, 0x1D,0x1F,0x9D,0x9F,0x3D,0x3F,0xBD,0xBF,
488     0x49,0x4B,0xC9,0xCB,0x69,0x6B,0xE9,0xEB, 0x59,0x5B,0xD9,0xDB,0x79,0x7B,0xF9,0xFB,
489     0x4D,0x4F,0xCD,0xCF,0x6D,0x6F,0xED,0xEF, 0x5D,0x5F,0xDD,0xDF,0x7D,0x7F,0xFD,0xFF,
490 };
491
492 static void csa_BlockDecypher( uint8_t kk[57], uint8_t ib[8], uint8_t bd[8] )
493 {
494     int i;
495     int perm_out;
496     int R[9];
497     int next_R8;
498
499     for( i = 0; i < 8; i++ )
500     {
501         R[i+1] = ib[i];
502     }
503
504     // loop over kk[56]..kk[1]
505     for( i = 56; i > 0; i-- )
506     {
507         const int sbox_out = block_sbox[ kk[i]^R[7] ];
508         perm_out = block_perm[sbox_out];
509
510         next_R8 = R[7];
511         R[7] = R[6] ^ perm_out;
512         R[6] = R[5];
513         R[5] = R[4] ^ R[8] ^ sbox_out;
514         R[4] = R[3] ^ R[8] ^ sbox_out;
515         R[3] = R[2] ^ R[8] ^ sbox_out;
516         R[2] = R[1];
517         R[1] = R[8] ^ sbox_out;
518
519         R[8] = next_R8;
520     }
521
522     for( i = 0; i < 8; i++ )
523     {
524         bd[i] = R[i+1];
525     }
526 }
527
528 static void csa_BlockCypher( uint8_t kk[57], uint8_t bd[8], uint8_t ib[8] )
529 {
530     int i;
531     int perm_out;
532     int R[9];
533     int next_R1;
534
535     for( i = 0; i < 8; i++ )
536     {
537         R[i+1] = bd[i];
538     }
539
540     // loop over kk[1]..kk[56]
541     for( i = 1; i <= 56; i++ )
542     {
543         const int sbox_out = block_sbox[ kk[i]^R[8] ];
544         perm_out = block_perm[sbox_out];
545
546         next_R1 = R[2];
547         R[2] = R[3] ^ R[1];
548         R[3] = R[4] ^ R[1];
549         R[4] = R[5] ^ R[1];
550         R[5] = R[6];
551         R[6] = R[7] ^ perm_out;
552         R[7] = R[8];
553         R[8] = R[1] ^ sbox_out;
554
555         R[1] = next_R1;
556     }
557
558     for( i = 0; i < 8; i++ )
559     {
560         ib[i] = R[i+1];
561     }
562 }
563