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 */
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 int csa_SetCW( vlc_object_t *p_caller, csa_t *c, char *psz_ck, int set_odd )
88 msg_Dbg( p_caller, "no CSA found" );
92 if( psz_ck[0] == '0' && ( psz_ck[1] == 'x' || psz_ck[1] == 'X' ) )
96 if( strlen( psz_ck ) != 16 )
98 msg_Warn( p_caller, "invalid csa ck (it must be 16 chars long)" );
104 uint64_t i_ck = strtoull( psz_ck, NULL, 16 );
106 uint64_t i_ck = strtoll( psz_ck, NULL, 16 );
111 for( i = 0; i < 8; i++ )
113 ck[i] = ( i_ck >> ( 56 - 8*i) )&0xff;
115 #ifndef TS_NO_CSA_CK_MSG
116 msg_Dbg( p_caller, "using CSA (de)scrambling with %s key=%x:%x:%x:%x:%x:%x:%x:%x", ((set_odd == 1) ? "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 void csa_Decrypt( csa_t *c, uint8_t *pkt, int i_pkt_size )
141 uint8_t ib[8], stream[8], block[8];
143 int i_hdr, i_residue;
146 /* transport scrambling control */
147 if( (pkt[3]&0x80) == 0 )
163 /* clear transport scrambling control */
169 /* skip adaption field */
173 if( 188 - i_hdr < 8 )
177 csa_StreamCypher( c, 1, ck, &pkt[i_hdr], ib );
180 n = (i_pkt_size - i_hdr) / 8;
184 i_residue = (i_pkt_size - i_hdr) % 8;
185 for( i = 1; i < n + 1; i++ )
187 csa_BlockDecypher( kk, ib, block );
190 csa_StreamCypher( c, 0, ck, NULL, stream );
191 for( j = 0; j < 8; j++ )
193 /* xor ib with stream */
194 ib[j] = pkt[i_hdr+8*i+j] ^ stream[j];
200 for( j = 0; j < 8; j++ )
205 /* xor ib with block */
206 for( j = 0; j < 8; j++ )
208 pkt[i_hdr+8*(i-1)+j] = ib[j] ^ block[j];
214 csa_StreamCypher( c, 0, ck, NULL, stream );
215 for( j = 0; j < i_residue; j++ )
217 pkt[i_pkt_size - i_residue + j] ^= stream[j];
222 /*****************************************************************************
224 *****************************************************************************/
225 void csa_Encrypt( csa_t *c, uint8_t *pkt, int i_pkt_size, int b_odd )
231 int i_hdr = 4; /* hdr len */
232 uint8_t ib[184/8+2][8], stream[8], block[8];
235 /* set transport scrambling control */
257 /* skip adaption field */
260 n = (i_pkt_size - i_hdr) / 8;
261 i_residue = (i_pkt_size - i_hdr) % 8;
270 for( i = 0; i < 8; i++ )
274 for( i = n; i > 0; i-- )
276 for( j = 0; j < 8; j++ )
278 block[j] = pkt[i_hdr+8*(i-1)+j] ^ib[i+1][j];
280 csa_BlockCypher( kk, block, ib[i] );
284 csa_StreamCypher( c, 1, ck, ib[1], stream );
286 for( i = 0; i < 8; i++ )
288 pkt[i_hdr+i] = ib[1][i];
290 for( i = 2; i < n+1; i++ )
292 csa_StreamCypher( c, 0, ck, NULL, stream );
293 for( j = 0; j < 8; j++ )
295 pkt[i_hdr+8*(i-1)+j] = ib[i][j] ^ stream[j];
300 csa_StreamCypher( c, 0, ck, NULL, stream );
301 for( j = 0; j < i_residue; j++ )
303 pkt[i_pkt_size - i_residue + j] ^= stream[j];
308 /*****************************************************************************
310 *****************************************************************************/
311 static const uint8_t key_perm[0x40] =
313 0x12,0x24,0x09,0x07,0x2A,0x31,0x1D,0x15,0x1C,0x36,0x3E,0x32,0x13,0x21,0x3B,0x40,
314 0x18,0x14,0x25,0x27,0x02,0x35,0x1B,0x01,0x22,0x04,0x0D,0x0E,0x39,0x28,0x1A,0x29,
315 0x33,0x23,0x34,0x0C,0x16,0x30,0x1E,0x3A,0x2D,0x1F,0x08,0x19,0x17,0x2F,0x3D,0x11,
316 0x3C,0x05,0x38,0x2B,0x0B,0x06,0x0A,0x2C,0x20,0x3F,0x2E,0x0F,0x03,0x26,0x10,0x37,
319 static void csa_ComputeKey( uint8_t kk[57], uint8_t ck[8] )
326 /* from a cw create 56 key bytes, here kk[1..56] */
328 /* load ck into kb[7][1..8] */
329 for( i = 0; i < 8; i++ )
334 /* calculate all kb[6..1][*] */
335 for( i = 0; i < 7; i++ )
337 /* do a 64 bit perm on kb */
338 for( j = 0; j < 8; j++ )
340 for( k = 0; k < 8; k++ )
342 bit[j*8+k] = (kb[7-i][1+j] >> (7-k)) & 1;
343 newbit[key_perm[j*8+k]-1] = bit[j*8+k];
346 for( j = 0; j < 8; j++ )
349 for( k = 0; k < 8; k++ )
351 kb[6-i][1+j] |= newbit[j*8+k] << (7-k);
357 for( i = 0; i < 7; i++ )
359 for( j = 0; j < 8; j++ )
361 kk[1+i*8+j] = kb[1+i][1+j] ^ i;
367 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};
368 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};
369 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};
370 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};
371 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};
372 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};
373 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};
375 static void csa_StreamCypher( csa_t *c, int b_init, uint8_t *ck, uint8_t *sb, uint8_t *cb )
379 int s1,s2,s3,s4,s5,s6,s7;
386 // load first 32 bits of CK into A[1]..A[8]
387 // load last 32 bits of CK into B[1]..B[8]
388 // all other regs = 0
389 for( i = 0; i < 4; i++ )
391 c->A[1+2*i+0] = ( ck[i] >> 4 )&0x0f;
392 c->A[1+2*i+1] = ( ck[i] >> 0 )&0x0f;
394 c->B[1+2*i+0] = ( ck[4+i] >> 4 )&0x0f;
395 c->B[1+2*i+1] = ( ck[4+i] >> 0 )&0x0f;
398 c->A[9] = c->A[10] = 0;
399 c->B[9] = c->B[10] = 0;
401 c->X = c->Y = c->Z = 0;
402 c->D = c->E = c->F = 0;
403 c->p = c->q = c->r = 0;
406 // 8 bytes per operation
407 for( i = 0; i < 8; i++ )
410 int in1 = 0; /* gcc warn */
415 in1 = ( sb[i] >> 4 )&0x0f;
416 in2 = ( sb[i] >> 0 )&0x0f;
419 // 2 bits per iteration
420 for( j = 0; j < 4; j++ )
422 // from A[1]..A[10], 35 bits are selected as inputs to 7 s-boxes
423 // 5 bits input per s-box, 2 bits output per s-box
424 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) ];
425 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) ];
426 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) ];
427 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) ];
428 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) ];
429 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) ];
430 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) ];
432 /* use 4x4 xor to produce extra nibble for T3 */
433 extra_B = ( ((c->B[3]&1)<<3) ^ ((c->B[6]&2)<<2) ^ ((c->B[7]&4)<<1) ^ ((c->B[9]&8)>>0) ) |
434 ( ((c->B[6]&1)<<2) ^ ((c->B[8]&2)<<1) ^ ((c->B[3]&8)>>1) ^ ((c->B[4]&4)>>0) ) |
435 ( ((c->B[5]&8)>>2) ^ ((c->B[8]&4)>>1) ^ ((c->B[4]&1)<<1) ^ ((c->B[5]&2)>>0) ) |
436 ( ((c->B[9]&4)>>2) ^ ((c->B[6]&8)>>3) ^ ((c->B[3]&2)>>1) ^ ((c->B[8]&1)>>0) ) ;
438 // T1 = xor all inputs
439 // in1,in2, D are only used in T1 during initialisation, not generation
440 next_A1 = c->A[10] ^ c->X;
441 if( b_init ) next_A1 = next_A1 ^ c->D ^ ((j % 2) ? in2 : in1);
443 // T2 = xor all inputs
444 // in1,in2 are only used in T1 during initialisation, not generation
445 // if p=0, use this, if p=1, rotate the result left
446 next_B1 = c->B[7] ^ c->B[10] ^ c->Y;
447 if( b_init) next_B1 = next_B1 ^ ((j % 2) ? in1 : in2);
449 // if p=1, rotate left
450 if( c->p ) next_B1 = ( (next_B1 << 1) | ((next_B1 >> 3) & 1) ) & 0xf;
452 // T3 = xor all inputs
453 c->D = c->E ^ c->Z ^ extra_B;
455 // T4 = sum, carry of Z + E + r
459 c->F = c->Z + c->E + c->r;
461 c->r = (c->F >> 4) & 1;
470 for( k = 10; k > 1; k-- )
478 c->X = ((s4&1)<<3) | ((s3&1)<<2) | (s2&2) | ((s1&2)>>1);
479 c->Y = ((s6&1)<<3) | ((s5&1)<<2) | (s4&2) | ((s3&2)>>1);
480 c->Z = ((s2&1)<<3) | ((s1&1)<<2) | (s6&2) | ((s5&2)>>1);
484 // require 4 loops per output byte
485 // 2 output bits are a function of the 4 bits of D
487 op = (op << 2)^ ( (((c->D^(c->D>>1))>>1)&2) | ((c->D^(c->D>>1))&1) );
489 // return input data during init
490 cb[i] = b_init ? sb[i] : op;
496 static const uint8_t block_sbox[256] =
498 0x3A,0xEA,0x68,0xFE,0x33,0xE9,0x88,0x1A,0x83,0xCF,0xE1,0x7F,0xBA,0xE2,0x38,0x12,
499 0xE8,0x27,0x61,0x95,0x0C,0x36,0xE5,0x70,0xA2,0x06,0x82,0x7C,0x17,0xA3,0x26,0x49,
500 0xBE,0x7A,0x6D,0x47,0xC1,0x51,0x8F,0xF3,0xCC,0x5B,0x67,0xBD,0xCD,0x18,0x08,0xC9,
501 0xFF,0x69,0xEF,0x03,0x4E,0x48,0x4A,0x84,0x3F,0xB4,0x10,0x04,0xDC,0xF5,0x5C,0xC6,
502 0x16,0xAB,0xAC,0x4C,0xF1,0x6A,0x2F,0x3C,0x3B,0xD4,0xD5,0x94,0xD0,0xC4,0x63,0x62,
503 0x71,0xA1,0xF9,0x4F,0x2E,0xAA,0xC5,0x56,0xE3,0x39,0x93,0xCE,0x65,0x64,0xE4,0x58,
504 0x6C,0x19,0x42,0x79,0xDD,0xEE,0x96,0xF6,0x8A,0xEC,0x1E,0x85,0x53,0x45,0xDE,0xBB,
505 0x7E,0x0A,0x9A,0x13,0x2A,0x9D,0xC2,0x5E,0x5A,0x1F,0x32,0x35,0x9C,0xA8,0x73,0x30,
507 0x29,0x3D,0xE7,0x92,0x87,0x1B,0x2B,0x4B,0xA5,0x57,0x97,0x40,0x15,0xE6,0xBC,0x0E,
508 0xEB,0xC3,0x34,0x2D,0xB8,0x44,0x25,0xA4,0x1C,0xC7,0x23,0xED,0x90,0x6E,0x50,0x00,
509 0x99,0x9E,0x4D,0xD9,0xDA,0x8D,0x6F,0x5F,0x3E,0xD7,0x21,0x74,0x86,0xDF,0x6B,0x05,
510 0x8E,0x5D,0x37,0x11,0xD2,0x28,0x75,0xD6,0xA7,0x77,0x24,0xBF,0xF0,0xB0,0x02,0xB7,
511 0xF8,0xFC,0x81,0x09,0xB1,0x01,0x76,0x91,0x7D,0x0F,0xC8,0xA0,0xF2,0xCB,0x78,0x60,
512 0xD1,0xF7,0xE0,0xB5,0x98,0x22,0xB3,0x20,0x1D,0xA6,0xDB,0x7B,0x59,0x9F,0xAE,0x31,
513 0xFB,0xD3,0xB6,0xCA,0x43,0x72,0x07,0xF4,0xD8,0x41,0x14,0x55,0x0D,0x54,0x8B,0xB9,
514 0xAD,0x46,0x0B,0xAF,0x80,0x52,0x2C,0xFA,0x8C,0x89,0x66,0xFD,0xB2,0xA9,0x9B,0xC0,
518 static const uint8_t block_perm[256] =
520 0x00,0x02,0x80,0x82,0x20,0x22,0xA0,0xA2, 0x10,0x12,0x90,0x92,0x30,0x32,0xB0,0xB2,
521 0x04,0x06,0x84,0x86,0x24,0x26,0xA4,0xA6, 0x14,0x16,0x94,0x96,0x34,0x36,0xB4,0xB6,
522 0x40,0x42,0xC0,0xC2,0x60,0x62,0xE0,0xE2, 0x50,0x52,0xD0,0xD2,0x70,0x72,0xF0,0xF2,
523 0x44,0x46,0xC4,0xC6,0x64,0x66,0xE4,0xE6, 0x54,0x56,0xD4,0xD6,0x74,0x76,0xF4,0xF6,
524 0x01,0x03,0x81,0x83,0x21,0x23,0xA1,0xA3, 0x11,0x13,0x91,0x93,0x31,0x33,0xB1,0xB3,
525 0x05,0x07,0x85,0x87,0x25,0x27,0xA5,0xA7, 0x15,0x17,0x95,0x97,0x35,0x37,0xB5,0xB7,
526 0x41,0x43,0xC1,0xC3,0x61,0x63,0xE1,0xE3, 0x51,0x53,0xD1,0xD3,0x71,0x73,0xF1,0xF3,
527 0x45,0x47,0xC5,0xC7,0x65,0x67,0xE5,0xE7, 0x55,0x57,0xD5,0xD7,0x75,0x77,0xF5,0xF7,
529 0x08,0x0A,0x88,0x8A,0x28,0x2A,0xA8,0xAA, 0x18,0x1A,0x98,0x9A,0x38,0x3A,0xB8,0xBA,
530 0x0C,0x0E,0x8C,0x8E,0x2C,0x2E,0xAC,0xAE, 0x1C,0x1E,0x9C,0x9E,0x3C,0x3E,0xBC,0xBE,
531 0x48,0x4A,0xC8,0xCA,0x68,0x6A,0xE8,0xEA, 0x58,0x5A,0xD8,0xDA,0x78,0x7A,0xF8,0xFA,
532 0x4C,0x4E,0xCC,0xCE,0x6C,0x6E,0xEC,0xEE, 0x5C,0x5E,0xDC,0xDE,0x7C,0x7E,0xFC,0xFE,
533 0x09,0x0B,0x89,0x8B,0x29,0x2B,0xA9,0xAB, 0x19,0x1B,0x99,0x9B,0x39,0x3B,0xB9,0xBB,
534 0x0D,0x0F,0x8D,0x8F,0x2D,0x2F,0xAD,0xAF, 0x1D,0x1F,0x9D,0x9F,0x3D,0x3F,0xBD,0xBF,
535 0x49,0x4B,0xC9,0xCB,0x69,0x6B,0xE9,0xEB, 0x59,0x5B,0xD9,0xDB,0x79,0x7B,0xF9,0xFB,
536 0x4D,0x4F,0xCD,0xCF,0x6D,0x6F,0xED,0xEF, 0x5D,0x5F,0xDD,0xDF,0x7D,0x7F,0xFD,0xFF,
539 static void csa_BlockDecypher( uint8_t kk[57], uint8_t ib[8], uint8_t bd[8] )
546 for( i = 0; i < 8; i++ )
551 // loop over kk[56]..kk[1]
552 for( i = 56; i > 0; i-- )
554 const int sbox_out = block_sbox[ kk[i]^R[7] ];
555 perm_out = block_perm[sbox_out];
558 R[7] = R[6] ^ perm_out;
560 R[5] = R[4] ^ R[8] ^ sbox_out;
561 R[4] = R[3] ^ R[8] ^ sbox_out;
562 R[3] = R[2] ^ R[8] ^ sbox_out;
564 R[1] = R[8] ^ sbox_out;
569 for( i = 0; i < 8; i++ )
575 static void csa_BlockCypher( uint8_t kk[57], uint8_t bd[8], uint8_t ib[8] )
582 for( i = 0; i < 8; i++ )
587 // loop over kk[1]..kk[56]
588 for( i = 1; i <= 56; i++ )
590 const int sbox_out = block_sbox[ kk[i]^R[8] ];
591 perm_out = block_perm[sbox_out];
598 R[6] = R[7] ^ perm_out;
600 R[8] = R[1] ^ sbox_out;
605 for( i = 0; i < 8; i++ )