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