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