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