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