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 return calloc( 1, sizeof( csa_t ) );
72 /*****************************************************************************
74 *****************************************************************************/
75 void csa_Delete( csa_t *c )
80 /*****************************************************************************
82 *****************************************************************************/
83 int csa_SetCW( vlc_object_t *p_caller, csa_t *c, char *psz_ck, bool set_odd )
87 msg_Dbg( p_caller, "no CSA found" );
91 if( psz_ck[0] == '0' && ( psz_ck[1] == 'x' || psz_ck[1] == 'X' ) )
95 if( strlen( psz_ck ) != 16 )
97 msg_Warn( p_caller, "invalid csa ck (it must be 16 chars long)" );
103 uint64_t i_ck = strtoull( psz_ck, NULL, 16 );
105 uint64_t i_ck = strtoll( psz_ck, NULL, 16 );
110 for( i = 0; i < 8; i++ )
112 ck[i] = ( i_ck >> ( 56 - 8*i) )&0xff;
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] );
121 memcpy( c->o_ck, ck, 8 );
122 csa_ComputeKey( c->o_kk, ck );
126 memcpy( c->e_ck , ck, 8 );
127 csa_ComputeKey( c->e_kk , ck );
133 /*****************************************************************************
135 *****************************************************************************/
136 int csa_UseKey( vlc_object_t *p_caller, csa_t *c, bool use_odd )
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" );
147 /*****************************************************************************
149 *****************************************************************************/
150 void csa_Decrypt( csa_t *c, uint8_t *pkt, int i_pkt_size )
155 uint8_t ib[8], stream[8], block[8];
157 int i_hdr, i_residue;
160 /* transport scrambling control */
161 if( (pkt[3]&0x80) == 0 )
177 /* clear transport scrambling control */
183 /* skip adaption field */
187 if( 188 - i_hdr < 8 )
191 csa_StreamCypher( c, 1, ck, &pkt[i_hdr], ib );
194 n = (i_pkt_size - i_hdr) / 8;
198 i_residue = (i_pkt_size - i_hdr) % 8;
199 for( i = 1; i < n + 1; i++ )
201 csa_BlockDecypher( kk, ib, block );
204 csa_StreamCypher( c, 0, ck, NULL, stream );
205 for( j = 0; j < 8; j++ )
207 /* xor ib with stream */
208 ib[j] = pkt[i_hdr+8*i+j] ^ stream[j];
214 for( j = 0; j < 8; j++ )
219 /* xor ib with block */
220 for( j = 0; j < 8; j++ )
222 pkt[i_hdr+8*(i-1)+j] = ib[j] ^ block[j];
228 csa_StreamCypher( c, 0, ck, NULL, stream );
229 for( j = 0; j < i_residue; j++ )
231 pkt[i_pkt_size - i_residue + j] ^= stream[j];
236 /*****************************************************************************
238 *****************************************************************************/
239 void csa_Encrypt( csa_t *c, uint8_t *pkt, int i_pkt_size )
245 int i_hdr = 4; /* hdr len */
246 uint8_t ib[184/8+2][8], stream[8], block[8];
249 /* set transport scrambling control */
268 /* skip adaption field */
271 n = (i_pkt_size - i_hdr) / 8;
272 i_residue = (i_pkt_size - i_hdr) % 8;
281 for( i = 0; i < 8; i++ )
285 for( i = n; i > 0; i-- )
287 for( j = 0; j < 8; j++ )
289 block[j] = pkt[i_hdr+8*(i-1)+j] ^ib[i+1][j];
291 csa_BlockCypher( kk, block, ib[i] );
295 csa_StreamCypher( c, 1, ck, ib[1], stream );
297 for( i = 0; i < 8; i++ )
299 pkt[i_hdr+i] = ib[1][i];
301 for( i = 2; i < n+1; i++ )
303 csa_StreamCypher( c, 0, ck, NULL, stream );
304 for( j = 0; j < 8; j++ )
306 pkt[i_hdr+8*(i-1)+j] = ib[i][j] ^ stream[j];
311 csa_StreamCypher( c, 0, ck, NULL, stream );
312 for( j = 0; j < i_residue; j++ )
314 pkt[i_pkt_size - i_residue + j] ^= stream[j];
319 /*****************************************************************************
321 *****************************************************************************/
322 static const uint8_t key_perm[0x40] =
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,
330 static void csa_ComputeKey( uint8_t kk[57], uint8_t ck[8] )
337 /* from a cw create 56 key bytes, here kk[1..56] */
339 /* load ck into kb[7][1..8] */
340 for( i = 0; i < 8; i++ )
345 /* calculate all kb[6..1][*] */
346 for( i = 0; i < 7; i++ )
348 /* do a 64 bit perm on kb */
349 for( j = 0; j < 8; j++ )
351 for( k = 0; k < 8; k++ )
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];
357 for( j = 0; j < 8; j++ )
360 for( k = 0; k < 8; k++ )
362 kb[6-i][1+j] |= newbit[j*8+k] << (7-k);
368 for( i = 0; i < 7; i++ )
370 for( j = 0; j < 8; j++ )
372 kk[1+i*8+j] = kb[1+i][1+j] ^ i;
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};
386 static void csa_StreamCypher( csa_t *c, int b_init, uint8_t *ck, uint8_t *sb, uint8_t *cb )
390 int s1,s2,s3,s4,s5,s6,s7;
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++ )
402 c->A[1+2*i+0] = ( ck[i] >> 4 )&0x0f;
403 c->A[1+2*i+1] = ( ck[i] >> 0 )&0x0f;
405 c->B[1+2*i+0] = ( ck[4+i] >> 4 )&0x0f;
406 c->B[1+2*i+1] = ( ck[4+i] >> 0 )&0x0f;
409 c->A[9] = c->A[10] = 0;
410 c->B[9] = c->B[10] = 0;
412 c->X = c->Y = c->Z = 0;
413 c->D = c->E = c->F = 0;
414 c->p = c->q = c->r = 0;
417 // 8 bytes per operation
418 for( i = 0; i < 8; i++ )
421 int in1 = 0; /* gcc warn */
426 in1 = ( sb[i] >> 4 )&0x0f;
427 in2 = ( sb[i] >> 0 )&0x0f;
430 // 2 bits per iteration
431 for( j = 0; j < 4; j++ )
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) ];
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) ) ;
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);
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);
460 // if p=1, rotate left
461 if( c->p ) next_B1 = ( (next_B1 << 1) | ((next_B1 >> 3) & 1) ) & 0xf;
463 // T3 = xor all inputs
464 c->D = c->E ^ c->Z ^ extra_B;
466 // T4 = sum, carry of Z + E + r
470 c->F = c->Z + c->E + c->r;
472 c->r = (c->F >> 4) & 1;
481 for( k = 10; k > 1; k-- )
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);
495 // require 4 loops per output byte
496 // 2 output bits are a function of the 4 bits of D
498 op = (op << 2)^ ( (((c->D^(c->D>>1))>>1)&2) | ((c->D^(c->D>>1))&1) );
500 // return input data during init
501 cb[i] = b_init ? sb[i] : op;
507 static const uint8_t block_sbox[256] =
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,
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,
529 static const uint8_t block_perm[256] =
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,
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,
550 static void csa_BlockDecypher( uint8_t kk[57], uint8_t ib[8], uint8_t bd[8] )
557 for( i = 0; i < 8; i++ )
562 // loop over kk[56]..kk[1]
563 for( i = 56; i > 0; i-- )
565 const int sbox_out = block_sbox[ kk[i]^R[7] ];
566 perm_out = block_perm[sbox_out];
569 R[7] = R[6] ^ perm_out;
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;
575 R[1] = R[8] ^ sbox_out;
580 for( i = 0; i < 8; i++ )
586 static void csa_BlockCypher( uint8_t kk[57], uint8_t bd[8], uint8_t ib[8] )
593 for( i = 0; i < 8; i++ )
598 // loop over kk[1]..kk[56]
599 for( i = 1; i <= 56; i++ )
601 const int sbox_out = block_sbox[ kk[i]^R[8] ];
602 perm_out = block_perm[sbox_out];
609 R[6] = R[7] ^ perm_out;
611 R[8] = R[1] ^ sbox_out;
616 for( i = 0; i < 8; i++ )