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