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