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