Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

csa.c

00001 /*****************************************************************************
00002  * libcsa.c: CSA scrambler/descrambler
00003  *****************************************************************************
00004  * Copyright (C) 2004-2005 Laurent Aimar
00005  * $Id: csa.c 12066 2005-08-08 09:16:09Z jpsaman $
00006  *
00007  * Authors: Laurent Aimar <[email protected]>
00008  *          Jean-Paul Saman <jpsaman #_at_# m2x.nl>
00009  *
00010  * This program is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00023  *****************************************************************************/
00024 
00025 /*
00026  * XXX: A great part is just a copy/past of deCSA but I can't find the
00027  * author and the license. If there is a problem with it please e-mail me.
00028  */
00029 
00030 #include <stdlib.h>
00031 #include <vlc/vlc.h>
00032 
00033 #include "csa.h"
00034 
00035 struct csa_t
00036 {
00037     /* odd and even keys */
00038     uint8_t o_ck[8];
00039     uint8_t e_ck[8];
00040 
00041     uint8_t o_kk[57];
00042     uint8_t e_kk[57];
00043 
00044     /* cypher state */
00045     int     A[11];
00046     int     B[11];
00047     int     X, Y, Z;
00048     int     D, E, F;
00049     int     p, q, r;
00050 };
00051 
00052 static void csa_ComputeKey( uint8_t kk[57], uint8_t ck[8] );
00053 
00054 static void csa_StreamCypher( csa_t *c, int b_init, uint8_t *ck, uint8_t *sb, uint8_t *cb );
00055 
00056 static void csa_BlockDecypher( uint8_t kk[57], uint8_t ib[8], uint8_t bd[8] );
00057 static void csa_BlockCypher( uint8_t kk[57], uint8_t bd[8], uint8_t ib[8] );
00058 
00059 /*****************************************************************************
00060  * csa_New:
00061  *****************************************************************************/
00062 csa_t *csa_New()
00063 {
00064     csa_t *c = malloc( sizeof( csa_t ) );
00065     memset( c, 0, sizeof( csa_t ) );
00066 
00067     return c;
00068 }
00069 
00070 /*****************************************************************************
00071  * csa_Delete:
00072  *****************************************************************************/
00073 void   csa_Delete( csa_t *c )
00074 {
00075     free( c );
00076 }
00077 
00078 /*****************************************************************************
00079  * csa_SetCW:
00080  *****************************************************************************/
00081 void csa_SetCW( csa_t *c, uint8_t o_ck[8], uint8_t e_ck[8] )
00082 {
00083     memcpy( c->o_ck, o_ck, 8 );
00084     csa_ComputeKey( c->o_kk, o_ck );
00085 
00086     memcpy( c->e_ck, e_ck, 8 );
00087     csa_ComputeKey( c->e_kk, e_ck );
00088 }
00089 
00090 /*****************************************************************************
00091  * csa_Decrypt:
00092  *****************************************************************************/
00093 void csa_Decrypt( csa_t *c, uint8_t *pkt, int i_pkt_size )
00094 {
00095     uint8_t *ck;
00096     uint8_t *kk;
00097 
00098     uint8_t  ib[8], stream[8], block[8];
00099 
00100     int     i_hdr, i_residue;
00101     int     i, j, n;
00102 
00103     /* transport scrambling control */
00104     if( (pkt[3]&0x80) == 0 )
00105     {
00106         /* not scrambled */
00107         return;
00108     }
00109     if( pkt[3]&0x40 )
00110     {
00111         ck = c->o_ck;
00112         kk = c->o_kk;
00113     }
00114     else
00115     {
00116         ck = c->e_ck;
00117         kk = c->e_kk;
00118     }
00119 
00120     /* clear transport scrambling control */
00121     pkt[3] &= 0x3f;
00122 
00123     i_hdr = 4;
00124     if( pkt[3]&0x20 )
00125     {
00126         /* skip adaption field */
00127         i_hdr += pkt[4] + 1;
00128     }
00129 
00130     if( 188 - i_hdr < 8 )
00131         return;
00132 
00133     /* init csa state */
00134     csa_StreamCypher( c, 1, ck, &pkt[i_hdr], ib );
00135 
00136     /* */
00137     n = (i_pkt_size - i_hdr) / 8;
00138     if( n < 0 )
00139         return;
00140         
00141     i_residue = (i_pkt_size - i_hdr) % 8;    
00142     for( i = 1; i < n + 1; i++ )
00143     {
00144         csa_BlockDecypher( kk, ib, block );
00145         if( i != n )
00146         {
00147             csa_StreamCypher( c, 0, ck, NULL, stream );
00148             for( j = 0; j < 8; j++ )
00149             {
00150                 /* xor ib with stream */
00151                 ib[j] = pkt[i_hdr+8*i+j] ^ stream[j];
00152             }
00153         }
00154         else
00155         {
00156             /* last block */
00157             for( j = 0; j < 8; j++ )
00158             {
00159                 ib[j] = 0;
00160             }
00161         }
00162         /* xor ib with block */
00163         for( j = 0; j < 8; j++ )
00164         {
00165             pkt[i_hdr+8*(i-1)+j] = ib[j] ^ block[j];
00166         }
00167     }
00168 
00169     if( i_residue > 0 )
00170     {
00171         csa_StreamCypher( c, 0, ck, NULL, stream );
00172         for( j = 0; j < i_residue; j++ )
00173         {
00174             pkt[i_pkt_size - i_residue + j] ^= stream[j];
00175         }
00176     }
00177 }
00178 
00179 /*****************************************************************************
00180  * csa_Encrypt:
00181  *****************************************************************************/
00182 void csa_Encrypt( csa_t *c, uint8_t *pkt, int i_pkt_size, int b_odd )
00183 {
00184     uint8_t *ck;
00185     uint8_t *kk;
00186 
00187     int i, j;
00188     int i_hdr = 4; /* hdr len */
00189     uint8_t  ib[184/8+2][8], stream[8], block[8];
00190     int n, i_residue;
00191 
00192     /* set transport scrambling control */
00193     pkt[3] |= 0x80;
00194     if( b_odd )
00195     {
00196         pkt[3] |= 0x40;
00197     }
00198 
00199     if( b_odd )
00200     {
00201         ck = c->o_ck;
00202         kk = c->o_kk;
00203     }
00204     else
00205     {
00206         ck = c->e_ck;
00207         kk = c->e_kk;
00208     }
00209 
00210     /* hdr len */
00211     i_hdr = 4;
00212     if( pkt[3]&0x20 )
00213     {
00214         /* skip adaption field */
00215         i_hdr += pkt[4] + 1;
00216     }
00217     n = (i_pkt_size - i_hdr) / 8;
00218     i_residue = (i_pkt_size - i_hdr) % 8;
00219 
00220     if( n <= 0 )
00221     {
00222         pkt[3] &= 0x3f;
00223         return;
00224     }
00225 
00226     /* */
00227     for( i = 0; i < 8; i++ )
00228     {
00229         ib[n+1][i] = 0;
00230     }
00231     for( i = n; i  > 0; i-- )
00232     {
00233         for( j = 0; j < 8; j++ )
00234         {
00235             block[j] = pkt[i_hdr+8*(i-1)+j] ^ib[i+1][j];
00236         }
00237         csa_BlockCypher( kk, block, ib[i] );
00238     }
00239 
00240     /* init csa state */
00241     csa_StreamCypher( c, 1, ck, ib[1], stream );
00242 
00243     for( i = 0; i < 8; i++ )
00244     {
00245         pkt[i_hdr+i] = ib[1][i];
00246     }
00247     for( i = 2; i < n+1; i++ )
00248     {
00249         csa_StreamCypher( c, 0, ck, NULL, stream );
00250         for( j = 0; j < 8; j++ )
00251         {
00252             pkt[i_hdr+8*(i-1)+j] = ib[i][j] ^ stream[j];
00253         }
00254     }
00255     if( i_residue > 0 )
00256     {
00257         csa_StreamCypher( c, 0, ck, NULL, stream );
00258         for( j = 0; j < i_residue; j++ )
00259         {
00260             pkt[i_pkt_size - i_residue + j] ^= stream[j];
00261         }
00262     }
00263 }
00264 
00265 /*****************************************************************************
00266  * Divers
00267  *****************************************************************************/
00268 static const uint8_t key_perm[0x40] =
00269 {
00270     0x12,0x24,0x09,0x07,0x2A,0x31,0x1D,0x15,0x1C,0x36,0x3E,0x32,0x13,0x21,0x3B,0x40,
00271     0x18,0x14,0x25,0x27,0x02,0x35,0x1B,0x01,0x22,0x04,0x0D,0x0E,0x39,0x28,0x1A,0x29,
00272     0x33,0x23,0x34,0x0C,0x16,0x30,0x1E,0x3A,0x2D,0x1F,0x08,0x19,0x17,0x2F,0x3D,0x11,
00273     0x3C,0x05,0x38,0x2B,0x0B,0x06,0x0A,0x2C,0x20,0x3F,0x2E,0x0F,0x03,0x26,0x10,0x37,
00274 };
00275 
00276 static void csa_ComputeKey( uint8_t kk[57], uint8_t ck[8] )
00277 {
00278     int i,j,k;
00279     int bit[64];
00280     int newbit[64];
00281     int kb[9][8];
00282 
00283     /* from a cw create 56 key bytes, here kk[1..56] */
00284 
00285     /* load ck into kb[7][1..8] */
00286     for( i = 0; i < 8; i++ )
00287     {
00288         kb[7][i+1] = ck[i];
00289     }
00290 
00291     /* calculate all kb[6..1][*] */
00292     for( i = 0; i < 7; i++ )
00293     {
00294         /* do a 64 bit perm on kb */
00295         for( j = 0; j < 8; j++ )
00296         {
00297             for( k = 0; k < 8; k++ )
00298             {
00299                 bit[j*8+k] = (kb[7-i][1+j] >> (7-k)) & 1;
00300                 newbit[key_perm[j*8+k]-1] = bit[j*8+k];
00301             }
00302         }
00303         for( j = 0; j < 8; j++ )
00304         {
00305             kb[6-i][1+j] = 0;
00306             for( k = 0; k < 8; k++ )
00307             {
00308                 kb[6-i][1+j] |= newbit[j*8+k] << (7-k);
00309             }
00310         }
00311     }
00312 
00313     /* xor to give kk */
00314     for( i = 0; i < 7; i++ )
00315     {
00316         for( j = 0; j < 8; j++ )
00317         {
00318             kk[1+i*8+j] = kb[1+i][1+j] ^ i;
00319         }
00320     }
00321 }
00322 
00323 
00324 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};
00325 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};
00326 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};
00327 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};
00328 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};
00329 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};
00330 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};
00331 
00332 static void csa_StreamCypher( csa_t *c, int b_init, uint8_t *ck, uint8_t *sb, uint8_t *cb )
00333 {
00334     int i,j, k;
00335     int extra_B;
00336     int s1,s2,s3,s4,s5,s6,s7;
00337     int next_A1;
00338     int next_B1;
00339     int next_E;
00340 
00341     if( b_init )
00342     {
00343         // load first 32 bits of CK into A[1]..A[8]
00344         // load last  32 bits of CK into B[1]..B[8]
00345         // all other regs = 0
00346         for( i = 0; i < 4; i++ )
00347         {
00348             c->A[1+2*i+0] = ( ck[i] >> 4 )&0x0f;
00349             c->A[1+2*i+1] = ( ck[i] >> 0 )&0x0f;
00350 
00351             c->B[1+2*i+0] = ( ck[4+i] >> 4 )&0x0f;
00352             c->B[1+2*i+1] = ( ck[4+i] >> 0 )&0x0f;
00353         }
00354 
00355         c->A[9] = c->A[10] = 0;
00356         c->B[9] = c->B[10] = 0;
00357 
00358         c->X = c->Y = c->Z = 0;
00359         c->D = c->E = c->F = 0;
00360         c->p = c->q = c->r = 0;
00361     }
00362 
00363     // 8 bytes per operation
00364     for( i = 0; i < 8; i++ )
00365     {
00366         int op = 0;
00367         int in1 = 0;    /* gcc warn */
00368         int in2 = 0;
00369 
00370         if( b_init )
00371         {
00372             in1 = ( sb[i] >> 4 )&0x0f;
00373             in2 = ( sb[i] >> 0 )&0x0f;
00374         }
00375 
00376         // 2 bits per iteration
00377         for( j = 0; j < 4; j++ )
00378         {
00379             // from A[1]..A[10], 35 bits are selected as inputs to 7 s-boxes
00380             // 5 bits input per s-box, 2 bits output per s-box
00381             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) ];
00382             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) ];
00383             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) ];
00384             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) ];
00385             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) ];
00386             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) ];
00387             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) ];
00388 
00389             /* use 4x4 xor to produce extra nibble for T3 */
00390             extra_B = ( ((c->B[3]&1)<<3) ^ ((c->B[6]&2)<<2) ^ ((c->B[7]&4)<<1) ^ ((c->B[9]&8)>>0) ) |
00391                       ( ((c->B[6]&1)<<2) ^ ((c->B[8]&2)<<1) ^ ((c->B[3]&8)>>1) ^ ((c->B[4]&4)>>0) ) |
00392                       ( ((c->B[5]&8)>>2) ^ ((c->B[8]&4)>>1) ^ ((c->B[4]&1)<<1) ^ ((c->B[5]&2)>>0) ) |
00393                       ( ((c->B[9]&4)>>2) ^ ((c->B[6]&8)>>3) ^ ((c->B[3]&2)>>1) ^ ((c->B[8]&1)>>0) ) ;
00394 
00395             // T1 = xor all inputs
00396             // in1,in2, D are only used in T1 during initialisation, not generation
00397             next_A1 = c->A[10] ^ c->X;
00398             if( b_init ) next_A1 = next_A1 ^ c->D ^ ((j % 2) ? in2 : in1);
00399 
00400             // T2 =  xor all inputs
00401             // in1,in2 are only used in T1 during initialisation, not generation
00402             // if p=0, use this, if p=1, rotate the result left
00403             next_B1 = c->B[7] ^ c->B[10] ^ c->Y;
00404             if( b_init) next_B1 = next_B1 ^ ((j % 2) ? in1 : in2);
00405 
00406             // if p=1, rotate left
00407             if( c->p ) next_B1 = ( (next_B1 << 1) | ((next_B1 >> 3) & 1) ) & 0xf;
00408 
00409             // T3 = xor all inputs
00410             c->D = c->E ^ c->Z ^ extra_B;
00411 
00412             // T4 = sum, carry of Z + E + r
00413             next_E = c->F;
00414             if( c->q )
00415             {
00416                 c->F = c->Z + c->E + c->r;
00417                 // r is the carry
00418                 c->r = (c->F >> 4) & 1;
00419                 c->F = c->F & 0x0f;
00420             }
00421             else
00422             {
00423                 c->F = c->E;
00424             }
00425             c->E = next_E;
00426 
00427             for( k = 10; k > 1; k-- )
00428             {
00429                 c->A[k] = c->A[k-1];
00430                 c->B[k] = c->B[k-1];
00431             }
00432             c->A[1] = next_A1;
00433             c->B[1] = next_B1;
00434 
00435             c->X = ((s4&1)<<3) | ((s3&1)<<2) | (s2&2) | ((s1&2)>>1);
00436             c->Y = ((s6&1)<<3) | ((s5&1)<<2) | (s4&2) | ((s3&2)>>1);
00437             c->Z = ((s2&1)<<3) | ((s1&1)<<2) | (s6&2) | ((s5&2)>>1);
00438             c->p = (s7&2)>>1;
00439             c->q = (s7&1);
00440 
00441             // require 4 loops per output byte
00442             // 2 output bits are a function of the 4 bits of D
00443             // xor 2 by 2
00444             op = (op << 2)^ ( (((c->D^(c->D>>1))>>1)&2) | ((c->D^(c->D>>1))&1) );
00445         }
00446         // return input data during init
00447         cb[i] = b_init ? sb[i] : op;
00448     }
00449 }
00450 
00451 
00452 // block - sbox
00453 static const uint8_t block_sbox[256] =
00454 {
00455     0x3A,0xEA,0x68,0xFE,0x33,0xE9,0x88,0x1A,0x83,0xCF,0xE1,0x7F,0xBA,0xE2,0x38,0x12,
00456     0xE8,0x27,0x61,0x95,0x0C,0x36,0xE5,0x70,0xA2,0x06,0x82,0x7C,0x17,0xA3,0x26,0x49,
00457     0xBE,0x7A,0x6D,0x47,0xC1,0x51,0x8F,0xF3,0xCC,0x5B,0x67,0xBD,0xCD,0x18,0x08,0xC9,
00458     0xFF,0x69,0xEF,0x03,0x4E,0x48,0x4A,0x84,0x3F,0xB4,0x10,0x04,0xDC,0xF5,0x5C,0xC6,
00459     0x16,0xAB,0xAC,0x4C,0xF1,0x6A,0x2F,0x3C,0x3B,0xD4,0xD5,0x94,0xD0,0xC4,0x63,0x62,
00460     0x71,0xA1,0xF9,0x4F,0x2E,0xAA,0xC5,0x56,0xE3,0x39,0x93,0xCE,0x65,0x64,0xE4,0x58,
00461     0x6C,0x19,0x42,0x79,0xDD,0xEE,0x96,0xF6,0x8A,0xEC,0x1E,0x85,0x53,0x45,0xDE,0xBB,
00462     0x7E,0x0A,0x9A,0x13,0x2A,0x9D,0xC2,0x5E,0x5A,0x1F,0x32,0x35,0x9C,0xA8,0x73,0x30,
00463 
00464     0x29,0x3D,0xE7,0x92,0x87,0x1B,0x2B,0x4B,0xA5,0x57,0x97,0x40,0x15,0xE6,0xBC,0x0E,
00465     0xEB,0xC3,0x34,0x2D,0xB8,0x44,0x25,0xA4,0x1C,0xC7,0x23,0xED,0x90,0x6E,0x50,0x00,
00466     0x99,0x9E,0x4D,0xD9,0xDA,0x8D,0x6F,0x5F,0x3E,0xD7,0x21,0x74,0x86,0xDF,0x6B,0x05,
00467     0x8E,0x5D,0x37,0x11,0xD2,0x28,0x75,0xD6,0xA7,0x77,0x24,0xBF,0xF0,0xB0,0x02,0xB7,
00468     0xF8,0xFC,0x81,0x09,0xB1,0x01,0x76,0x91,0x7D,0x0F,0xC8,0xA0,0xF2,0xCB,0x78,0x60,
00469     0xD1,0xF7,0xE0,0xB5,0x98,0x22,0xB3,0x20,0x1D,0xA6,0xDB,0x7B,0x59,0x9F,0xAE,0x31,
00470     0xFB,0xD3,0xB6,0xCA,0x43,0x72,0x07,0xF4,0xD8,0x41,0x14,0x55,0x0D,0x54,0x8B,0xB9,
00471     0xAD,0x46,0x0B,0xAF,0x80,0x52,0x2C,0xFA,0x8C,0x89,0x66,0xFD,0xB2,0xA9,0x9B,0xC0,
00472 };
00473 
00474 // block - perm
00475 static const uint8_t block_perm[256] =
00476 {
00477     0x00,0x02,0x80,0x82,0x20,0x22,0xA0,0xA2, 0x10,0x12,0x90,0x92,0x30,0x32,0xB0,0xB2,
00478     0x04,0x06,0x84,0x86,0x24,0x26,0xA4,0xA6, 0x14,0x16,0x94,0x96,0x34,0x36,0xB4,0xB6,
00479     0x40,0x42,0xC0,0xC2,0x60,0x62,0xE0,0xE2, 0x50,0x52,0xD0,0xD2,0x70,0x72,0xF0,0xF2,
00480     0x44,0x46,0xC4,0xC6,0x64,0x66,0xE4,0xE6, 0x54,0x56,0xD4,0xD6,0x74,0x76,0xF4,0xF6,
00481     0x01,0x03,0x81,0x83,0x21,0x23,0xA1,0xA3, 0x11,0x13,0x91,0x93,0x31,0x33,0xB1,0xB3,
00482     0x05,0x07,0x85,0x87,0x25,0x27,0xA5,0xA7, 0x15,0x17,0x95,0x97,0x35,0x37,0xB5,0xB7,
00483     0x41,0x43,0xC1,0xC3,0x61,0x63,0xE1,0xE3, 0x51,0x53,0xD1,0xD3,0x71,0x73,0xF1,0xF3,
00484     0x45,0x47,0xC5,0xC7,0x65,0x67,0xE5,0xE7, 0x55,0x57,0xD5,0xD7,0x75,0x77,0xF5,0xF7,
00485 
00486     0x08,0x0A,0x88,0x8A,0x28,0x2A,0xA8,0xAA, 0x18,0x1A,0x98,0x9A,0x38,0x3A,0xB8,0xBA,
00487     0x0C,0x0E,0x8C,0x8E,0x2C,0x2E,0xAC,0xAE, 0x1C,0x1E,0x9C,0x9E,0x3C,0x3E,0xBC,0xBE,
00488     0x48,0x4A,0xC8,0xCA,0x68,0x6A,0xE8,0xEA, 0x58,0x5A,0xD8,0xDA,0x78,0x7A,0xF8,0xFA,
00489     0x4C,0x4E,0xCC,0xCE,0x6C,0x6E,0xEC,0xEE, 0x5C,0x5E,0xDC,0xDE,0x7C,0x7E,0xFC,0xFE,
00490     0x09,0x0B,0x89,0x8B,0x29,0x2B,0xA9,0xAB, 0x19,0x1B,0x99,0x9B,0x39,0x3B,0xB9,0xBB,
00491     0x0D,0x0F,0x8D,0x8F,0x2D,0x2F,0xAD,0xAF, 0x1D,0x1F,0x9D,0x9F,0x3D,0x3F,0xBD,0xBF,
00492     0x49,0x4B,0xC9,0xCB,0x69,0x6B,0xE9,0xEB, 0x59,0x5B,0xD9,0xDB,0x79,0x7B,0xF9,0xFB,
00493     0x4D,0x4F,0xCD,0xCF,0x6D,0x6F,0xED,0xEF, 0x5D,0x5F,0xDD,0xDF,0x7D,0x7F,0xFD,0xFF,
00494 };
00495 
00496 static void csa_BlockDecypher( uint8_t kk[57], uint8_t ib[8], uint8_t bd[8] )
00497 {
00498     int i;
00499     int perm_out;
00500     int R[9];
00501     int next_R8;
00502 
00503     for( i = 0; i < 8; i++ )
00504     {
00505         R[i+1] = ib[i];
00506     }
00507 
00508     // loop over kk[56]..kk[1]
00509     for( i = 56; i > 0; i-- )
00510     {
00511         const int sbox_out = block_sbox[ kk[i]^R[7] ];
00512         perm_out = block_perm[sbox_out];
00513 
00514         next_R8 = R[7];
00515         R[7] = R[6] ^ perm_out;
00516         R[6] = R[5];
00517         R[5] = R[4] ^ R[8] ^ sbox_out;
00518         R[4] = R[3] ^ R[8] ^ sbox_out;
00519         R[3] = R[2] ^ R[8] ^ sbox_out;
00520         R[2] = R[1];
00521         R[1] = R[8] ^ sbox_out;
00522 
00523         R[8] = next_R8;
00524     }
00525 
00526     for( i = 0; i < 8; i++ )
00527     {
00528         bd[i] = R[i+1];
00529     }
00530 }
00531 
00532 static void csa_BlockCypher( uint8_t kk[57], uint8_t bd[8], uint8_t ib[8] )
00533 {
00534     int i;
00535     int perm_out;
00536     int R[9];
00537     int next_R1;
00538 
00539     for( i = 0; i < 8; i++ )
00540     {
00541         R[i+1] = bd[i];
00542     }
00543 
00544     // loop over kk[1]..kk[56]
00545     for( i = 1; i <= 56; i++ )
00546     {
00547         const int sbox_out = block_sbox[ kk[i]^R[8] ];
00548         perm_out = block_perm[sbox_out];
00549 
00550         next_R1 = R[2];
00551         R[2] = R[3] ^ R[1];
00552         R[3] = R[4] ^ R[1];
00553         R[4] = R[5] ^ R[1];
00554         R[5] = R[6];
00555         R[6] = R[7] ^ perm_out;
00556         R[7] = R[8];
00557         R[8] = R[1] ^ sbox_out;
00558 
00559         R[1] = next_R1;
00560     }
00561 
00562     for( i = 0; i < 8; i++ )
00563     {
00564         ib[i] = R[i+1];
00565     }
00566 }
00567 

Generated on Tue Dec 20 10:14:49 2005 for vlc-0.8.4a by  doxygen 1.4.2