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.
34 #include <vlc_common.h>
40 /* odd and even keys */
57 static void csa_ComputeKey( uint8_t kk[57], uint8_t ck[8] );
59 static void csa_StreamCypher( csa_t *c, int b_init, uint8_t *ck, uint8_t *sb, uint8_t *cb );
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] );
64 /*****************************************************************************
66 *****************************************************************************/
67 csa_t *csa_New( void )
69 csa_t *c = malloc( sizeof( csa_t ) );
70 memset( c, 0, sizeof( csa_t ) );
75 /*****************************************************************************
77 *****************************************************************************/
78 void csa_Delete( csa_t *c )
83 /*****************************************************************************
85 *****************************************************************************/
86 int csa_SetCW( vlc_object_t *p_caller, csa_t *c, char *psz_ck, bool set_odd )
90 msg_Dbg( p_caller, "no CSA found" );
94 if( psz_ck[0] == '0' && ( psz_ck[1] == 'x' || psz_ck[1] == 'X' ) )
98 if( strlen( psz_ck ) != 16 )
100 msg_Warn( p_caller, "invalid csa ck (it must be 16 chars long)" );
106 uint64_t i_ck = strtoull( psz_ck, NULL, 16 );
108 uint64_t i_ck = strtoll( psz_ck, NULL, 16 );
113 for( i = 0; i < 8; i++ )
115 ck[i] = ( i_ck >> ( 56 - 8*i) )&0xff;
117 #ifndef TS_NO_CSA_CK_MSG
118 msg_Dbg( p_caller, "using CSA (de)scrambling with %s "
119 "key=%x:%x:%x:%x:%x:%x:%x:%x", set_odd ? "odd" : "even",
120 ck[0], ck[1], ck[2], ck[3], ck[4], ck[5], ck[6], ck[7] );
124 memcpy( c->o_ck, ck, 8 );
125 csa_ComputeKey( c->o_kk, ck );
129 memcpy( c->e_ck , ck, 8 );
130 csa_ComputeKey( c->e_kk , ck );
136 /*****************************************************************************
138 *****************************************************************************/
139 int csa_UseKey( vlc_object_t *p_caller, csa_t *c, bool use_odd )
141 if ( !c ) return VLC_ENOOBJ;
142 c->use_odd = use_odd;
143 #ifndef TS_NO_CSA_CK_MSG
144 msg_Dbg( p_caller, "using the %s key for scrambling",
145 use_odd ? "odd" : "even" );
150 /*****************************************************************************
152 *****************************************************************************/
153 void csa_Decrypt( csa_t *c, uint8_t *pkt, int i_pkt_size )
158 uint8_t ib[8], stream[8], block[8];
160 int i_hdr, i_residue;
163 /* transport scrambling control */
164 if( (pkt[3]&0x80) == 0 )
180 /* clear transport scrambling control */
186 /* skip adaption field */
190 if( 188 - i_hdr < 8 )
194 csa_StreamCypher( c, 1, ck, &pkt[i_hdr], ib );
197 n = (i_pkt_size - i_hdr) / 8;
201 i_residue = (i_pkt_size - i_hdr) % 8;
202 for( i = 1; i < n + 1; i++ )
204 csa_BlockDecypher( kk, ib, block );
207 csa_StreamCypher( c, 0, ck, NULL, stream );
208 for( j = 0; j < 8; j++ )
210 /* xor ib with stream */
211 ib[j] = pkt[i_hdr+8*i+j] ^ stream[j];
217 for( j = 0; j < 8; j++ )
222 /* xor ib with block */
223 for( j = 0; j < 8; j++ )
225 pkt[i_hdr+8*(i-1)+j] = ib[j] ^ block[j];
231 csa_StreamCypher( c, 0, ck, NULL, stream );
232 for( j = 0; j < i_residue; j++ )
234 pkt[i_pkt_size - i_residue + j] ^= stream[j];
239 /*****************************************************************************
241 *****************************************************************************/
242 void csa_Encrypt( csa_t *c, uint8_t *pkt, int i_pkt_size )
248 int i_hdr = 4; /* hdr len */
249 uint8_t ib[184/8+2][8], stream[8], block[8];
252 /* set transport scrambling control */
271 /* skip adaption field */
274 n = (i_pkt_size - i_hdr) / 8;
275 i_residue = (i_pkt_size - i_hdr) % 8;
284 for( i = 0; i < 8; i++ )
288 for( i = n; i > 0; i-- )
290 for( j = 0; j < 8; j++ )
292 block[j] = pkt[i_hdr+8*(i-1)+j] ^ib[i+1][j];
294 csa_BlockCypher( kk, block, ib[i] );
298 csa_StreamCypher( c, 1, ck, ib[1], stream );
300 for( i = 0; i < 8; i++ )
302 pkt[i_hdr+i] = ib[1][i];
304 for( i = 2; i < n+1; i++ )
306 csa_StreamCypher( c, 0, ck, NULL, stream );
307 for( j = 0; j < 8; j++ )
309 pkt[i_hdr+8*(i-1)+j] = ib[i][j] ^ stream[j];
314 csa_StreamCypher( c, 0, ck, NULL, stream );
315 for( j = 0; j < i_residue; j++ )
317 pkt[i_pkt_size - i_residue + j] ^= stream[j];
322 /*****************************************************************************
324 *****************************************************************************/
325 static const uint8_t key_perm[0x40] =
327 0x12,0x24,0x09,0x07,0x2A,0x31,0x1D,0x15,0x1C,0x36,0x3E,0x32,0x13,0x21,0x3B,0x40,
328 0x18,0x14,0x25,0x27,0x02,0x35,0x1B,0x01,0x22,0x04,0x0D,0x0E,0x39,0x28,0x1A,0x29,
329 0x33,0x23,0x34,0x0C,0x16,0x30,0x1E,0x3A,0x2D,0x1F,0x08,0x19,0x17,0x2F,0x3D,0x11,
330 0x3C,0x05,0x38,0x2B,0x0B,0x06,0x0A,0x2C,0x20,0x3F,0x2E,0x0F,0x03,0x26,0x10,0x37,
333 static void csa_ComputeKey( uint8_t kk[57], uint8_t ck[8] )
340 /* from a cw create 56 key bytes, here kk[1..56] */
342 /* load ck into kb[7][1..8] */
343 for( i = 0; i < 8; i++ )
348 /* calculate all kb[6..1][*] */
349 for( i = 0; i < 7; i++ )
351 /* do a 64 bit perm on kb */
352 for( j = 0; j < 8; j++ )
354 for( k = 0; k < 8; k++ )
356 bit[j*8+k] = (kb[7-i][1+j] >> (7-k)) & 1;
357 newbit[key_perm[j*8+k]-1] = bit[j*8+k];
360 for( j = 0; j < 8; j++ )
363 for( k = 0; k < 8; k++ )
365 kb[6-i][1+j] |= newbit[j*8+k] << (7-k);
371 for( i = 0; i < 7; i++ )
373 for( j = 0; j < 8; j++ )
375 kk[1+i*8+j] = kb[1+i][1+j] ^ i;
381 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};
382 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};
383 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};
384 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};
385 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};
386 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};
387 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};
389 static void csa_StreamCypher( csa_t *c, int b_init, uint8_t *ck, uint8_t *sb, uint8_t *cb )
393 int s1,s2,s3,s4,s5,s6,s7;
400 // load first 32 bits of CK into A[1]..A[8]
401 // load last 32 bits of CK into B[1]..B[8]
402 // all other regs = 0
403 for( i = 0; i < 4; i++ )
405 c->A[1+2*i+0] = ( ck[i] >> 4 )&0x0f;
406 c->A[1+2*i+1] = ( ck[i] >> 0 )&0x0f;
408 c->B[1+2*i+0] = ( ck[4+i] >> 4 )&0x0f;
409 c->B[1+2*i+1] = ( ck[4+i] >> 0 )&0x0f;
412 c->A[9] = c->A[10] = 0;
413 c->B[9] = c->B[10] = 0;
415 c->X = c->Y = c->Z = 0;
416 c->D = c->E = c->F = 0;
417 c->p = c->q = c->r = 0;
420 // 8 bytes per operation
421 for( i = 0; i < 8; i++ )
424 int in1 = 0; /* gcc warn */
429 in1 = ( sb[i] >> 4 )&0x0f;
430 in2 = ( sb[i] >> 0 )&0x0f;
433 // 2 bits per iteration
434 for( j = 0; j < 4; j++ )
436 // from A[1]..A[10], 35 bits are selected as inputs to 7 s-boxes
437 // 5 bits input per s-box, 2 bits output per s-box
438 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) ];
439 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) ];
440 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) ];
441 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) ];
442 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) ];
443 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) ];
444 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) ];
446 /* use 4x4 xor to produce extra nibble for T3 */
447 extra_B = ( ((c->B[3]&1)<<3) ^ ((c->B[6]&2)<<2) ^ ((c->B[7]&4)<<1) ^ ((c->B[9]&8)>>0) ) |
448 ( ((c->B[6]&1)<<2) ^ ((c->B[8]&2)<<1) ^ ((c->B[3]&8)>>1) ^ ((c->B[4]&4)>>0) ) |
449 ( ((c->B[5]&8)>>2) ^ ((c->B[8]&4)>>1) ^ ((c->B[4]&1)<<1) ^ ((c->B[5]&2)>>0) ) |
450 ( ((c->B[9]&4)>>2) ^ ((c->B[6]&8)>>3) ^ ((c->B[3]&2)>>1) ^ ((c->B[8]&1)>>0) ) ;
452 // T1 = xor all inputs
453 // in1,in2, D are only used in T1 during initialisation, not generation
454 next_A1 = c->A[10] ^ c->X;
455 if( b_init ) next_A1 = next_A1 ^ c->D ^ ((j % 2) ? in2 : in1);
457 // T2 = xor all inputs
458 // in1,in2 are only used in T1 during initialisation, not generation
459 // if p=0, use this, if p=1, rotate the result left
460 next_B1 = c->B[7] ^ c->B[10] ^ c->Y;
461 if( b_init) next_B1 = next_B1 ^ ((j % 2) ? in1 : in2);
463 // if p=1, rotate left
464 if( c->p ) next_B1 = ( (next_B1 << 1) | ((next_B1 >> 3) & 1) ) & 0xf;
466 // T3 = xor all inputs
467 c->D = c->E ^ c->Z ^ extra_B;
469 // T4 = sum, carry of Z + E + r
473 c->F = c->Z + c->E + c->r;
475 c->r = (c->F >> 4) & 1;
484 for( k = 10; k > 1; k-- )
492 c->X = ((s4&1)<<3) | ((s3&1)<<2) | (s2&2) | ((s1&2)>>1);
493 c->Y = ((s6&1)<<3) | ((s5&1)<<2) | (s4&2) | ((s3&2)>>1);
494 c->Z = ((s2&1)<<3) | ((s1&1)<<2) | (s6&2) | ((s5&2)>>1);
498 // require 4 loops per output byte
499 // 2 output bits are a function of the 4 bits of D
501 op = (op << 2)^ ( (((c->D^(c->D>>1))>>1)&2) | ((c->D^(c->D>>1))&1) );
503 // return input data during init
504 cb[i] = b_init ? sb[i] : op;
510 static const uint8_t block_sbox[256] =
512 0x3A,0xEA,0x68,0xFE,0x33,0xE9,0x88,0x1A,0x83,0xCF,0xE1,0x7F,0xBA,0xE2,0x38,0x12,
513 0xE8,0x27,0x61,0x95,0x0C,0x36,0xE5,0x70,0xA2,0x06,0x82,0x7C,0x17,0xA3,0x26,0x49,
514 0xBE,0x7A,0x6D,0x47,0xC1,0x51,0x8F,0xF3,0xCC,0x5B,0x67,0xBD,0xCD,0x18,0x08,0xC9,
515 0xFF,0x69,0xEF,0x03,0x4E,0x48,0x4A,0x84,0x3F,0xB4,0x10,0x04,0xDC,0xF5,0x5C,0xC6,
516 0x16,0xAB,0xAC,0x4C,0xF1,0x6A,0x2F,0x3C,0x3B,0xD4,0xD5,0x94,0xD0,0xC4,0x63,0x62,
517 0x71,0xA1,0xF9,0x4F,0x2E,0xAA,0xC5,0x56,0xE3,0x39,0x93,0xCE,0x65,0x64,0xE4,0x58,
518 0x6C,0x19,0x42,0x79,0xDD,0xEE,0x96,0xF6,0x8A,0xEC,0x1E,0x85,0x53,0x45,0xDE,0xBB,
519 0x7E,0x0A,0x9A,0x13,0x2A,0x9D,0xC2,0x5E,0x5A,0x1F,0x32,0x35,0x9C,0xA8,0x73,0x30,
521 0x29,0x3D,0xE7,0x92,0x87,0x1B,0x2B,0x4B,0xA5,0x57,0x97,0x40,0x15,0xE6,0xBC,0x0E,
522 0xEB,0xC3,0x34,0x2D,0xB8,0x44,0x25,0xA4,0x1C,0xC7,0x23,0xED,0x90,0x6E,0x50,0x00,
523 0x99,0x9E,0x4D,0xD9,0xDA,0x8D,0x6F,0x5F,0x3E,0xD7,0x21,0x74,0x86,0xDF,0x6B,0x05,
524 0x8E,0x5D,0x37,0x11,0xD2,0x28,0x75,0xD6,0xA7,0x77,0x24,0xBF,0xF0,0xB0,0x02,0xB7,
525 0xF8,0xFC,0x81,0x09,0xB1,0x01,0x76,0x91,0x7D,0x0F,0xC8,0xA0,0xF2,0xCB,0x78,0x60,
526 0xD1,0xF7,0xE0,0xB5,0x98,0x22,0xB3,0x20,0x1D,0xA6,0xDB,0x7B,0x59,0x9F,0xAE,0x31,
527 0xFB,0xD3,0xB6,0xCA,0x43,0x72,0x07,0xF4,0xD8,0x41,0x14,0x55,0x0D,0x54,0x8B,0xB9,
528 0xAD,0x46,0x0B,0xAF,0x80,0x52,0x2C,0xFA,0x8C,0x89,0x66,0xFD,0xB2,0xA9,0x9B,0xC0,
532 static const uint8_t block_perm[256] =
534 0x00,0x02,0x80,0x82,0x20,0x22,0xA0,0xA2, 0x10,0x12,0x90,0x92,0x30,0x32,0xB0,0xB2,
535 0x04,0x06,0x84,0x86,0x24,0x26,0xA4,0xA6, 0x14,0x16,0x94,0x96,0x34,0x36,0xB4,0xB6,
536 0x40,0x42,0xC0,0xC2,0x60,0x62,0xE0,0xE2, 0x50,0x52,0xD0,0xD2,0x70,0x72,0xF0,0xF2,
537 0x44,0x46,0xC4,0xC6,0x64,0x66,0xE4,0xE6, 0x54,0x56,0xD4,0xD6,0x74,0x76,0xF4,0xF6,
538 0x01,0x03,0x81,0x83,0x21,0x23,0xA1,0xA3, 0x11,0x13,0x91,0x93,0x31,0x33,0xB1,0xB3,
539 0x05,0x07,0x85,0x87,0x25,0x27,0xA5,0xA7, 0x15,0x17,0x95,0x97,0x35,0x37,0xB5,0xB7,
540 0x41,0x43,0xC1,0xC3,0x61,0x63,0xE1,0xE3, 0x51,0x53,0xD1,0xD3,0x71,0x73,0xF1,0xF3,
541 0x45,0x47,0xC5,0xC7,0x65,0x67,0xE5,0xE7, 0x55,0x57,0xD5,0xD7,0x75,0x77,0xF5,0xF7,
543 0x08,0x0A,0x88,0x8A,0x28,0x2A,0xA8,0xAA, 0x18,0x1A,0x98,0x9A,0x38,0x3A,0xB8,0xBA,
544 0x0C,0x0E,0x8C,0x8E,0x2C,0x2E,0xAC,0xAE, 0x1C,0x1E,0x9C,0x9E,0x3C,0x3E,0xBC,0xBE,
545 0x48,0x4A,0xC8,0xCA,0x68,0x6A,0xE8,0xEA, 0x58,0x5A,0xD8,0xDA,0x78,0x7A,0xF8,0xFA,
546 0x4C,0x4E,0xCC,0xCE,0x6C,0x6E,0xEC,0xEE, 0x5C,0x5E,0xDC,0xDE,0x7C,0x7E,0xFC,0xFE,
547 0x09,0x0B,0x89,0x8B,0x29,0x2B,0xA9,0xAB, 0x19,0x1B,0x99,0x9B,0x39,0x3B,0xB9,0xBB,
548 0x0D,0x0F,0x8D,0x8F,0x2D,0x2F,0xAD,0xAF, 0x1D,0x1F,0x9D,0x9F,0x3D,0x3F,0xBD,0xBF,
549 0x49,0x4B,0xC9,0xCB,0x69,0x6B,0xE9,0xEB, 0x59,0x5B,0xD9,0xDB,0x79,0x7B,0xF9,0xFB,
550 0x4D,0x4F,0xCD,0xCF,0x6D,0x6F,0xED,0xEF, 0x5D,0x5F,0xDD,0xDF,0x7D,0x7F,0xFD,0xFF,
553 static void csa_BlockDecypher( uint8_t kk[57], uint8_t ib[8], uint8_t bd[8] )
560 for( i = 0; i < 8; i++ )
565 // loop over kk[56]..kk[1]
566 for( i = 56; i > 0; i-- )
568 const int sbox_out = block_sbox[ kk[i]^R[7] ];
569 perm_out = block_perm[sbox_out];
572 R[7] = R[6] ^ perm_out;
574 R[5] = R[4] ^ R[8] ^ sbox_out;
575 R[4] = R[3] ^ R[8] ^ sbox_out;
576 R[3] = R[2] ^ R[8] ^ sbox_out;
578 R[1] = R[8] ^ sbox_out;
583 for( i = 0; i < 8; i++ )
589 static void csa_BlockCypher( uint8_t kk[57], uint8_t bd[8], uint8_t ib[8] )
596 for( i = 0; i < 8; i++ )
601 // loop over kk[1]..kk[56]
602 for( i = 1; i <= 56; i++ )
604 const int sbox_out = block_sbox[ kk[i]^R[8] ];
605 perm_out = block_perm[sbox_out];
612 R[6] = R[7] ^ perm_out;
614 R[8] = R[1] ^ sbox_out;
619 for( i = 0; i < 8; i++ )