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