1 /*****************************************************************************
2 * libcsa.c: CSA scrambler/descrambler
3 *****************************************************************************
4 * Copyright (C) 2004-2005 Laurent Aimar
7 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8 * Jean-Paul Saman <jpsaman #_at_# m2x.nl>
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.
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.
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 *****************************************************************************/
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.
40 /* odd and even keys */
55 static void csa_ComputeKey( uint8_t kk[57], uint8_t ck[8] );
57 static void csa_StreamCypher( csa_t *c, int b_init, uint8_t *ck, uint8_t *sb, uint8_t *cb );
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] );
62 /*****************************************************************************
64 *****************************************************************************/
65 csa_t *csa_New( void )
67 csa_t *c = malloc( sizeof( csa_t ) );
68 memset( c, 0, sizeof( csa_t ) );
73 /*****************************************************************************
75 *****************************************************************************/
76 void csa_Delete( csa_t *c )
81 /*****************************************************************************
83 *****************************************************************************/
84 void csa_SetCW( csa_t *c, uint8_t o_ck[8], uint8_t e_ck[8] )
86 memcpy( c->o_ck, o_ck, 8 );
87 csa_ComputeKey( c->o_kk, o_ck );
89 memcpy( c->e_ck, e_ck, 8 );
90 csa_ComputeKey( c->e_kk, e_ck );
93 /*****************************************************************************
95 *****************************************************************************/
96 void csa_Decrypt( csa_t *c, uint8_t *pkt, int i_pkt_size )
101 uint8_t ib[8], stream[8], block[8];
103 int i_hdr, i_residue;
106 /* transport scrambling control */
107 if( (pkt[3]&0x80) == 0 )
123 /* clear transport scrambling control */
129 /* skip adaption field */
133 if( 188 - i_hdr < 8 )
137 csa_StreamCypher( c, 1, ck, &pkt[i_hdr], ib );
140 n = (i_pkt_size - i_hdr) / 8;
144 i_residue = (i_pkt_size - i_hdr) % 8;
145 for( i = 1; i < n + 1; i++ )
147 csa_BlockDecypher( kk, ib, block );
150 csa_StreamCypher( c, 0, ck, NULL, stream );
151 for( j = 0; j < 8; j++ )
153 /* xor ib with stream */
154 ib[j] = pkt[i_hdr+8*i+j] ^ stream[j];
160 for( j = 0; j < 8; j++ )
165 /* xor ib with block */
166 for( j = 0; j < 8; j++ )
168 pkt[i_hdr+8*(i-1)+j] = ib[j] ^ block[j];
174 csa_StreamCypher( c, 0, ck, NULL, stream );
175 for( j = 0; j < i_residue; j++ )
177 pkt[i_pkt_size - i_residue + j] ^= stream[j];
182 /*****************************************************************************
184 *****************************************************************************/
185 void csa_Encrypt( csa_t *c, uint8_t *pkt, int i_pkt_size, int b_odd )
191 int i_hdr = 4; /* hdr len */
192 uint8_t ib[184/8+2][8], stream[8], block[8];
195 /* set transport scrambling control */
217 /* skip adaption field */
220 n = (i_pkt_size - i_hdr) / 8;
221 i_residue = (i_pkt_size - i_hdr) % 8;
230 for( i = 0; i < 8; i++ )
234 for( i = n; i > 0; i-- )
236 for( j = 0; j < 8; j++ )
238 block[j] = pkt[i_hdr+8*(i-1)+j] ^ib[i+1][j];
240 csa_BlockCypher( kk, block, ib[i] );
244 csa_StreamCypher( c, 1, ck, ib[1], stream );
246 for( i = 0; i < 8; i++ )
248 pkt[i_hdr+i] = ib[1][i];
250 for( i = 2; i < n+1; i++ )
252 csa_StreamCypher( c, 0, ck, NULL, stream );
253 for( j = 0; j < 8; j++ )
255 pkt[i_hdr+8*(i-1)+j] = ib[i][j] ^ stream[j];
260 csa_StreamCypher( c, 0, ck, NULL, stream );
261 for( j = 0; j < i_residue; j++ )
263 pkt[i_pkt_size - i_residue + j] ^= stream[j];
268 /*****************************************************************************
270 *****************************************************************************/
271 static const uint8_t key_perm[0x40] =
273 0x12,0x24,0x09,0x07,0x2A,0x31,0x1D,0x15,0x1C,0x36,0x3E,0x32,0x13,0x21,0x3B,0x40,
274 0x18,0x14,0x25,0x27,0x02,0x35,0x1B,0x01,0x22,0x04,0x0D,0x0E,0x39,0x28,0x1A,0x29,
275 0x33,0x23,0x34,0x0C,0x16,0x30,0x1E,0x3A,0x2D,0x1F,0x08,0x19,0x17,0x2F,0x3D,0x11,
276 0x3C,0x05,0x38,0x2B,0x0B,0x06,0x0A,0x2C,0x20,0x3F,0x2E,0x0F,0x03,0x26,0x10,0x37,
279 static void csa_ComputeKey( uint8_t kk[57], uint8_t ck[8] )
286 /* from a cw create 56 key bytes, here kk[1..56] */
288 /* load ck into kb[7][1..8] */
289 for( i = 0; i < 8; i++ )
294 /* calculate all kb[6..1][*] */
295 for( i = 0; i < 7; i++ )
297 /* do a 64 bit perm on kb */
298 for( j = 0; j < 8; j++ )
300 for( k = 0; k < 8; k++ )
302 bit[j*8+k] = (kb[7-i][1+j] >> (7-k)) & 1;
303 newbit[key_perm[j*8+k]-1] = bit[j*8+k];
306 for( j = 0; j < 8; j++ )
309 for( k = 0; k < 8; k++ )
311 kb[6-i][1+j] |= newbit[j*8+k] << (7-k);
317 for( i = 0; i < 7; i++ )
319 for( j = 0; j < 8; j++ )
321 kk[1+i*8+j] = kb[1+i][1+j] ^ i;
327 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};
328 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};
329 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};
330 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};
331 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};
332 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};
333 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};
335 static void csa_StreamCypher( csa_t *c, int b_init, uint8_t *ck, uint8_t *sb, uint8_t *cb )
339 int s1,s2,s3,s4,s5,s6,s7;
346 // load first 32 bits of CK into A[1]..A[8]
347 // load last 32 bits of CK into B[1]..B[8]
348 // all other regs = 0
349 for( i = 0; i < 4; i++ )
351 c->A[1+2*i+0] = ( ck[i] >> 4 )&0x0f;
352 c->A[1+2*i+1] = ( ck[i] >> 0 )&0x0f;
354 c->B[1+2*i+0] = ( ck[4+i] >> 4 )&0x0f;
355 c->B[1+2*i+1] = ( ck[4+i] >> 0 )&0x0f;
358 c->A[9] = c->A[10] = 0;
359 c->B[9] = c->B[10] = 0;
361 c->X = c->Y = c->Z = 0;
362 c->D = c->E = c->F = 0;
363 c->p = c->q = c->r = 0;
366 // 8 bytes per operation
367 for( i = 0; i < 8; i++ )
370 int in1 = 0; /* gcc warn */
375 in1 = ( sb[i] >> 4 )&0x0f;
376 in2 = ( sb[i] >> 0 )&0x0f;
379 // 2 bits per iteration
380 for( j = 0; j < 4; j++ )
382 // from A[1]..A[10], 35 bits are selected as inputs to 7 s-boxes
383 // 5 bits input per s-box, 2 bits output per s-box
384 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) ];
385 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) ];
386 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) ];
387 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) ];
388 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) ];
389 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) ];
390 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) ];
392 /* use 4x4 xor to produce extra nibble for T3 */
393 extra_B = ( ((c->B[3]&1)<<3) ^ ((c->B[6]&2)<<2) ^ ((c->B[7]&4)<<1) ^ ((c->B[9]&8)>>0) ) |
394 ( ((c->B[6]&1)<<2) ^ ((c->B[8]&2)<<1) ^ ((c->B[3]&8)>>1) ^ ((c->B[4]&4)>>0) ) |
395 ( ((c->B[5]&8)>>2) ^ ((c->B[8]&4)>>1) ^ ((c->B[4]&1)<<1) ^ ((c->B[5]&2)>>0) ) |
396 ( ((c->B[9]&4)>>2) ^ ((c->B[6]&8)>>3) ^ ((c->B[3]&2)>>1) ^ ((c->B[8]&1)>>0) ) ;
398 // T1 = xor all inputs
399 // in1,in2, D are only used in T1 during initialisation, not generation
400 next_A1 = c->A[10] ^ c->X;
401 if( b_init ) next_A1 = next_A1 ^ c->D ^ ((j % 2) ? in2 : in1);
403 // T2 = xor all inputs
404 // in1,in2 are only used in T1 during initialisation, not generation
405 // if p=0, use this, if p=1, rotate the result left
406 next_B1 = c->B[7] ^ c->B[10] ^ c->Y;
407 if( b_init) next_B1 = next_B1 ^ ((j % 2) ? in1 : in2);
409 // if p=1, rotate left
410 if( c->p ) next_B1 = ( (next_B1 << 1) | ((next_B1 >> 3) & 1) ) & 0xf;
412 // T3 = xor all inputs
413 c->D = c->E ^ c->Z ^ extra_B;
415 // T4 = sum, carry of Z + E + r
419 c->F = c->Z + c->E + c->r;
421 c->r = (c->F >> 4) & 1;
430 for( k = 10; k > 1; k-- )
438 c->X = ((s4&1)<<3) | ((s3&1)<<2) | (s2&2) | ((s1&2)>>1);
439 c->Y = ((s6&1)<<3) | ((s5&1)<<2) | (s4&2) | ((s3&2)>>1);
440 c->Z = ((s2&1)<<3) | ((s1&1)<<2) | (s6&2) | ((s5&2)>>1);
444 // require 4 loops per output byte
445 // 2 output bits are a function of the 4 bits of D
447 op = (op << 2)^ ( (((c->D^(c->D>>1))>>1)&2) | ((c->D^(c->D>>1))&1) );
449 // return input data during init
450 cb[i] = b_init ? sb[i] : op;
456 static const uint8_t block_sbox[256] =
458 0x3A,0xEA,0x68,0xFE,0x33,0xE9,0x88,0x1A,0x83,0xCF,0xE1,0x7F,0xBA,0xE2,0x38,0x12,
459 0xE8,0x27,0x61,0x95,0x0C,0x36,0xE5,0x70,0xA2,0x06,0x82,0x7C,0x17,0xA3,0x26,0x49,
460 0xBE,0x7A,0x6D,0x47,0xC1,0x51,0x8F,0xF3,0xCC,0x5B,0x67,0xBD,0xCD,0x18,0x08,0xC9,
461 0xFF,0x69,0xEF,0x03,0x4E,0x48,0x4A,0x84,0x3F,0xB4,0x10,0x04,0xDC,0xF5,0x5C,0xC6,
462 0x16,0xAB,0xAC,0x4C,0xF1,0x6A,0x2F,0x3C,0x3B,0xD4,0xD5,0x94,0xD0,0xC4,0x63,0x62,
463 0x71,0xA1,0xF9,0x4F,0x2E,0xAA,0xC5,0x56,0xE3,0x39,0x93,0xCE,0x65,0x64,0xE4,0x58,
464 0x6C,0x19,0x42,0x79,0xDD,0xEE,0x96,0xF6,0x8A,0xEC,0x1E,0x85,0x53,0x45,0xDE,0xBB,
465 0x7E,0x0A,0x9A,0x13,0x2A,0x9D,0xC2,0x5E,0x5A,0x1F,0x32,0x35,0x9C,0xA8,0x73,0x30,
467 0x29,0x3D,0xE7,0x92,0x87,0x1B,0x2B,0x4B,0xA5,0x57,0x97,0x40,0x15,0xE6,0xBC,0x0E,
468 0xEB,0xC3,0x34,0x2D,0xB8,0x44,0x25,0xA4,0x1C,0xC7,0x23,0xED,0x90,0x6E,0x50,0x00,
469 0x99,0x9E,0x4D,0xD9,0xDA,0x8D,0x6F,0x5F,0x3E,0xD7,0x21,0x74,0x86,0xDF,0x6B,0x05,
470 0x8E,0x5D,0x37,0x11,0xD2,0x28,0x75,0xD6,0xA7,0x77,0x24,0xBF,0xF0,0xB0,0x02,0xB7,
471 0xF8,0xFC,0x81,0x09,0xB1,0x01,0x76,0x91,0x7D,0x0F,0xC8,0xA0,0xF2,0xCB,0x78,0x60,
472 0xD1,0xF7,0xE0,0xB5,0x98,0x22,0xB3,0x20,0x1D,0xA6,0xDB,0x7B,0x59,0x9F,0xAE,0x31,
473 0xFB,0xD3,0xB6,0xCA,0x43,0x72,0x07,0xF4,0xD8,0x41,0x14,0x55,0x0D,0x54,0x8B,0xB9,
474 0xAD,0x46,0x0B,0xAF,0x80,0x52,0x2C,0xFA,0x8C,0x89,0x66,0xFD,0xB2,0xA9,0x9B,0xC0,
478 static const uint8_t block_perm[256] =
480 0x00,0x02,0x80,0x82,0x20,0x22,0xA0,0xA2, 0x10,0x12,0x90,0x92,0x30,0x32,0xB0,0xB2,
481 0x04,0x06,0x84,0x86,0x24,0x26,0xA4,0xA6, 0x14,0x16,0x94,0x96,0x34,0x36,0xB4,0xB6,
482 0x40,0x42,0xC0,0xC2,0x60,0x62,0xE0,0xE2, 0x50,0x52,0xD0,0xD2,0x70,0x72,0xF0,0xF2,
483 0x44,0x46,0xC4,0xC6,0x64,0x66,0xE4,0xE6, 0x54,0x56,0xD4,0xD6,0x74,0x76,0xF4,0xF6,
484 0x01,0x03,0x81,0x83,0x21,0x23,0xA1,0xA3, 0x11,0x13,0x91,0x93,0x31,0x33,0xB1,0xB3,
485 0x05,0x07,0x85,0x87,0x25,0x27,0xA5,0xA7, 0x15,0x17,0x95,0x97,0x35,0x37,0xB5,0xB7,
486 0x41,0x43,0xC1,0xC3,0x61,0x63,0xE1,0xE3, 0x51,0x53,0xD1,0xD3,0x71,0x73,0xF1,0xF3,
487 0x45,0x47,0xC5,0xC7,0x65,0x67,0xE5,0xE7, 0x55,0x57,0xD5,0xD7,0x75,0x77,0xF5,0xF7,
489 0x08,0x0A,0x88,0x8A,0x28,0x2A,0xA8,0xAA, 0x18,0x1A,0x98,0x9A,0x38,0x3A,0xB8,0xBA,
490 0x0C,0x0E,0x8C,0x8E,0x2C,0x2E,0xAC,0xAE, 0x1C,0x1E,0x9C,0x9E,0x3C,0x3E,0xBC,0xBE,
491 0x48,0x4A,0xC8,0xCA,0x68,0x6A,0xE8,0xEA, 0x58,0x5A,0xD8,0xDA,0x78,0x7A,0xF8,0xFA,
492 0x4C,0x4E,0xCC,0xCE,0x6C,0x6E,0xEC,0xEE, 0x5C,0x5E,0xDC,0xDE,0x7C,0x7E,0xFC,0xFE,
493 0x09,0x0B,0x89,0x8B,0x29,0x2B,0xA9,0xAB, 0x19,0x1B,0x99,0x9B,0x39,0x3B,0xB9,0xBB,
494 0x0D,0x0F,0x8D,0x8F,0x2D,0x2F,0xAD,0xAF, 0x1D,0x1F,0x9D,0x9F,0x3D,0x3F,0xBD,0xBF,
495 0x49,0x4B,0xC9,0xCB,0x69,0x6B,0xE9,0xEB, 0x59,0x5B,0xD9,0xDB,0x79,0x7B,0xF9,0xFB,
496 0x4D,0x4F,0xCD,0xCF,0x6D,0x6F,0xED,0xEF, 0x5D,0x5F,0xDD,0xDF,0x7D,0x7F,0xFD,0xFF,
499 static void csa_BlockDecypher( uint8_t kk[57], uint8_t ib[8], uint8_t bd[8] )
506 for( i = 0; i < 8; i++ )
511 // loop over kk[56]..kk[1]
512 for( i = 56; i > 0; i-- )
514 const int sbox_out = block_sbox[ kk[i]^R[7] ];
515 perm_out = block_perm[sbox_out];
518 R[7] = R[6] ^ perm_out;
520 R[5] = R[4] ^ R[8] ^ sbox_out;
521 R[4] = R[3] ^ R[8] ^ sbox_out;
522 R[3] = R[2] ^ R[8] ^ sbox_out;
524 R[1] = R[8] ^ sbox_out;
529 for( i = 0; i < 8; i++ )
535 static void csa_BlockCypher( uint8_t kk[57], uint8_t bd[8], uint8_t ib[8] )
542 for( i = 0; i < 8; i++ )
547 // loop over kk[1]..kk[56]
548 for( i = 1; i <= 56; i++ )
550 const int sbox_out = block_sbox[ kk[i]^R[8] ];
551 perm_out = block_perm[sbox_out];
558 R[6] = R[7] ^ perm_out;
560 R[8] = R[1] ^ sbox_out;
565 for( i = 0; i < 8; i++ )