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)" );
102 uint64_t i_ck = strtoull( psz_ck, NULL, 16 );
106 for( i = 0; i < 8; i++ )
108 ck[i] = ( i_ck >> ( 56 - 8*i) )&0xff;
110 #ifndef TS_NO_CSA_CK_MSG
111 msg_Dbg( p_caller, "using CSA (de)scrambling with %s "
112 "key=%x:%x:%x:%x:%x:%x:%x:%x", set_odd ? "odd" : "even",
113 ck[0], ck[1], ck[2], ck[3], ck[4], ck[5], ck[6], ck[7] );
117 memcpy( c->o_ck, ck, 8 );
118 csa_ComputeKey( c->o_kk, ck );
122 memcpy( c->e_ck , ck, 8 );
123 csa_ComputeKey( c->e_kk , ck );
129 /*****************************************************************************
131 *****************************************************************************/
132 int csa_UseKey( vlc_object_t *p_caller, csa_t *c, bool use_odd )
134 if ( !c ) return VLC_ENOOBJ;
135 c->use_odd = use_odd;
136 #ifndef TS_NO_CSA_CK_MSG
137 msg_Dbg( p_caller, "using the %s key for scrambling",
138 use_odd ? "odd" : "even" );
143 /*****************************************************************************
145 *****************************************************************************/
146 void csa_Decrypt( csa_t *c, uint8_t *pkt, int i_pkt_size )
151 uint8_t ib[8], stream[8], block[8];
153 int i_hdr, i_residue;
156 /* transport scrambling control */
157 if( (pkt[3]&0x80) == 0 )
173 /* clear transport scrambling control */
179 /* skip adaption field */
183 if( 188 - i_hdr < 8 )
187 csa_StreamCypher( c, 1, ck, &pkt[i_hdr], ib );
190 n = (i_pkt_size - i_hdr) / 8;
194 i_residue = (i_pkt_size - i_hdr) % 8;
195 for( i = 1; i < n + 1; i++ )
197 csa_BlockDecypher( kk, ib, block );
200 csa_StreamCypher( c, 0, ck, NULL, stream );
201 for( j = 0; j < 8; j++ )
203 /* xor ib with stream */
204 ib[j] = pkt[i_hdr+8*i+j] ^ stream[j];
210 for( j = 0; j < 8; j++ )
215 /* xor ib with block */
216 for( j = 0; j < 8; j++ )
218 pkt[i_hdr+8*(i-1)+j] = ib[j] ^ block[j];
224 csa_StreamCypher( c, 0, ck, NULL, stream );
225 for( j = 0; j < i_residue; j++ )
227 pkt[i_pkt_size - i_residue + j] ^= stream[j];
232 /*****************************************************************************
234 *****************************************************************************/
235 void csa_Encrypt( csa_t *c, uint8_t *pkt, int i_pkt_size )
241 int i_hdr = 4; /* hdr len */
242 uint8_t ib[184/8+2][8], stream[8], block[8];
245 /* set transport scrambling control */
264 /* skip adaption field */
267 n = (i_pkt_size - i_hdr) / 8;
268 i_residue = (i_pkt_size - i_hdr) % 8;
277 for( i = 0; i < 8; i++ )
281 for( i = n; i > 0; i-- )
283 for( j = 0; j < 8; j++ )
285 block[j] = pkt[i_hdr+8*(i-1)+j] ^ib[i+1][j];
287 csa_BlockCypher( kk, block, ib[i] );
291 csa_StreamCypher( c, 1, ck, ib[1], stream );
293 for( i = 0; i < 8; i++ )
295 pkt[i_hdr+i] = ib[1][i];
297 for( i = 2; i < n+1; i++ )
299 csa_StreamCypher( c, 0, ck, NULL, stream );
300 for( j = 0; j < 8; j++ )
302 pkt[i_hdr+8*(i-1)+j] = ib[i][j] ^ stream[j];
307 csa_StreamCypher( c, 0, ck, NULL, stream );
308 for( j = 0; j < i_residue; j++ )
310 pkt[i_pkt_size - i_residue + j] ^= stream[j];
315 /*****************************************************************************
317 *****************************************************************************/
318 static const uint8_t key_perm[0x40] =
320 0x12,0x24,0x09,0x07,0x2A,0x31,0x1D,0x15,0x1C,0x36,0x3E,0x32,0x13,0x21,0x3B,0x40,
321 0x18,0x14,0x25,0x27,0x02,0x35,0x1B,0x01,0x22,0x04,0x0D,0x0E,0x39,0x28,0x1A,0x29,
322 0x33,0x23,0x34,0x0C,0x16,0x30,0x1E,0x3A,0x2D,0x1F,0x08,0x19,0x17,0x2F,0x3D,0x11,
323 0x3C,0x05,0x38,0x2B,0x0B,0x06,0x0A,0x2C,0x20,0x3F,0x2E,0x0F,0x03,0x26,0x10,0x37,
326 static void csa_ComputeKey( uint8_t kk[57], uint8_t ck[8] )
333 /* from a cw create 56 key bytes, here kk[1..56] */
335 /* load ck into kb[7][1..8] */
336 for( i = 0; i < 8; i++ )
341 /* calculate all kb[6..1][*] */
342 for( i = 0; i < 7; i++ )
344 /* do a 64 bit perm on kb */
345 for( j = 0; j < 8; j++ )
347 for( k = 0; k < 8; k++ )
349 bit[j*8+k] = (kb[7-i][1+j] >> (7-k)) & 1;
350 newbit[key_perm[j*8+k]-1] = bit[j*8+k];
353 for( j = 0; j < 8; j++ )
356 for( k = 0; k < 8; k++ )
358 kb[6-i][1+j] |= newbit[j*8+k] << (7-k);
364 for( i = 0; i < 7; i++ )
366 for( j = 0; j < 8; j++ )
368 kk[1+i*8+j] = kb[1+i][1+j] ^ i;
374 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};
375 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};
376 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};
377 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};
378 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};
379 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};
380 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};
382 static void csa_StreamCypher( csa_t *c, int b_init, uint8_t *ck, uint8_t *sb, uint8_t *cb )
386 int s1,s2,s3,s4,s5,s6,s7;
393 // load first 32 bits of CK into A[1]..A[8]
394 // load last 32 bits of CK into B[1]..B[8]
395 // all other regs = 0
396 for( i = 0; i < 4; i++ )
398 c->A[1+2*i+0] = ( ck[i] >> 4 )&0x0f;
399 c->A[1+2*i+1] = ( ck[i] >> 0 )&0x0f;
401 c->B[1+2*i+0] = ( ck[4+i] >> 4 )&0x0f;
402 c->B[1+2*i+1] = ( ck[4+i] >> 0 )&0x0f;
405 c->A[9] = c->A[10] = 0;
406 c->B[9] = c->B[10] = 0;
408 c->X = c->Y = c->Z = 0;
409 c->D = c->E = c->F = 0;
410 c->p = c->q = c->r = 0;
413 // 8 bytes per operation
414 for( i = 0; i < 8; i++ )
417 int in1 = 0; /* gcc warn */
422 in1 = ( sb[i] >> 4 )&0x0f;
423 in2 = ( sb[i] >> 0 )&0x0f;
426 // 2 bits per iteration
427 for( j = 0; j < 4; j++ )
429 // from A[1]..A[10], 35 bits are selected as inputs to 7 s-boxes
430 // 5 bits input per s-box, 2 bits output per s-box
431 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) ];
432 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) ];
433 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) ];
434 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) ];
435 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) ];
436 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) ];
437 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) ];
439 /* use 4x4 xor to produce extra nibble for T3 */
440 extra_B = ( ((c->B[3]&1)<<3) ^ ((c->B[6]&2)<<2) ^ ((c->B[7]&4)<<1) ^ ((c->B[9]&8)>>0) ) |
441 ( ((c->B[6]&1)<<2) ^ ((c->B[8]&2)<<1) ^ ((c->B[3]&8)>>1) ^ ((c->B[4]&4)>>0) ) |
442 ( ((c->B[5]&8)>>2) ^ ((c->B[8]&4)>>1) ^ ((c->B[4]&1)<<1) ^ ((c->B[5]&2)>>0) ) |
443 ( ((c->B[9]&4)>>2) ^ ((c->B[6]&8)>>3) ^ ((c->B[3]&2)>>1) ^ ((c->B[8]&1)>>0) ) ;
445 // T1 = xor all inputs
446 // in1,in2, D are only used in T1 during initialisation, not generation
447 next_A1 = c->A[10] ^ c->X;
448 if( b_init ) next_A1 = next_A1 ^ c->D ^ ((j % 2) ? in2 : in1);
450 // T2 = xor all inputs
451 // in1,in2 are only used in T1 during initialisation, not generation
452 // if p=0, use this, if p=1, rotate the result left
453 next_B1 = c->B[7] ^ c->B[10] ^ c->Y;
454 if( b_init) next_B1 = next_B1 ^ ((j % 2) ? in1 : in2);
456 // if p=1, rotate left
457 if( c->p ) next_B1 = ( (next_B1 << 1) | ((next_B1 >> 3) & 1) ) & 0xf;
459 // T3 = xor all inputs
460 c->D = c->E ^ c->Z ^ extra_B;
462 // T4 = sum, carry of Z + E + r
466 c->F = c->Z + c->E + c->r;
468 c->r = (c->F >> 4) & 1;
477 for( k = 10; k > 1; k-- )
485 c->X = ((s4&1)<<3) | ((s3&1)<<2) | (s2&2) | ((s1&2)>>1);
486 c->Y = ((s6&1)<<3) | ((s5&1)<<2) | (s4&2) | ((s3&2)>>1);
487 c->Z = ((s2&1)<<3) | ((s1&1)<<2) | (s6&2) | ((s5&2)>>1);
491 // require 4 loops per output byte
492 // 2 output bits are a function of the 4 bits of D
494 op = (op << 2)^ ( (((c->D^(c->D>>1))>>1)&2) | ((c->D^(c->D>>1))&1) );
496 // return input data during init
497 cb[i] = b_init ? sb[i] : op;
503 static const uint8_t block_sbox[256] =
505 0x3A,0xEA,0x68,0xFE,0x33,0xE9,0x88,0x1A,0x83,0xCF,0xE1,0x7F,0xBA,0xE2,0x38,0x12,
506 0xE8,0x27,0x61,0x95,0x0C,0x36,0xE5,0x70,0xA2,0x06,0x82,0x7C,0x17,0xA3,0x26,0x49,
507 0xBE,0x7A,0x6D,0x47,0xC1,0x51,0x8F,0xF3,0xCC,0x5B,0x67,0xBD,0xCD,0x18,0x08,0xC9,
508 0xFF,0x69,0xEF,0x03,0x4E,0x48,0x4A,0x84,0x3F,0xB4,0x10,0x04,0xDC,0xF5,0x5C,0xC6,
509 0x16,0xAB,0xAC,0x4C,0xF1,0x6A,0x2F,0x3C,0x3B,0xD4,0xD5,0x94,0xD0,0xC4,0x63,0x62,
510 0x71,0xA1,0xF9,0x4F,0x2E,0xAA,0xC5,0x56,0xE3,0x39,0x93,0xCE,0x65,0x64,0xE4,0x58,
511 0x6C,0x19,0x42,0x79,0xDD,0xEE,0x96,0xF6,0x8A,0xEC,0x1E,0x85,0x53,0x45,0xDE,0xBB,
512 0x7E,0x0A,0x9A,0x13,0x2A,0x9D,0xC2,0x5E,0x5A,0x1F,0x32,0x35,0x9C,0xA8,0x73,0x30,
514 0x29,0x3D,0xE7,0x92,0x87,0x1B,0x2B,0x4B,0xA5,0x57,0x97,0x40,0x15,0xE6,0xBC,0x0E,
515 0xEB,0xC3,0x34,0x2D,0xB8,0x44,0x25,0xA4,0x1C,0xC7,0x23,0xED,0x90,0x6E,0x50,0x00,
516 0x99,0x9E,0x4D,0xD9,0xDA,0x8D,0x6F,0x5F,0x3E,0xD7,0x21,0x74,0x86,0xDF,0x6B,0x05,
517 0x8E,0x5D,0x37,0x11,0xD2,0x28,0x75,0xD6,0xA7,0x77,0x24,0xBF,0xF0,0xB0,0x02,0xB7,
518 0xF8,0xFC,0x81,0x09,0xB1,0x01,0x76,0x91,0x7D,0x0F,0xC8,0xA0,0xF2,0xCB,0x78,0x60,
519 0xD1,0xF7,0xE0,0xB5,0x98,0x22,0xB3,0x20,0x1D,0xA6,0xDB,0x7B,0x59,0x9F,0xAE,0x31,
520 0xFB,0xD3,0xB6,0xCA,0x43,0x72,0x07,0xF4,0xD8,0x41,0x14,0x55,0x0D,0x54,0x8B,0xB9,
521 0xAD,0x46,0x0B,0xAF,0x80,0x52,0x2C,0xFA,0x8C,0x89,0x66,0xFD,0xB2,0xA9,0x9B,0xC0,
525 static const uint8_t block_perm[256] =
527 0x00,0x02,0x80,0x82,0x20,0x22,0xA0,0xA2, 0x10,0x12,0x90,0x92,0x30,0x32,0xB0,0xB2,
528 0x04,0x06,0x84,0x86,0x24,0x26,0xA4,0xA6, 0x14,0x16,0x94,0x96,0x34,0x36,0xB4,0xB6,
529 0x40,0x42,0xC0,0xC2,0x60,0x62,0xE0,0xE2, 0x50,0x52,0xD0,0xD2,0x70,0x72,0xF0,0xF2,
530 0x44,0x46,0xC4,0xC6,0x64,0x66,0xE4,0xE6, 0x54,0x56,0xD4,0xD6,0x74,0x76,0xF4,0xF6,
531 0x01,0x03,0x81,0x83,0x21,0x23,0xA1,0xA3, 0x11,0x13,0x91,0x93,0x31,0x33,0xB1,0xB3,
532 0x05,0x07,0x85,0x87,0x25,0x27,0xA5,0xA7, 0x15,0x17,0x95,0x97,0x35,0x37,0xB5,0xB7,
533 0x41,0x43,0xC1,0xC3,0x61,0x63,0xE1,0xE3, 0x51,0x53,0xD1,0xD3,0x71,0x73,0xF1,0xF3,
534 0x45,0x47,0xC5,0xC7,0x65,0x67,0xE5,0xE7, 0x55,0x57,0xD5,0xD7,0x75,0x77,0xF5,0xF7,
536 0x08,0x0A,0x88,0x8A,0x28,0x2A,0xA8,0xAA, 0x18,0x1A,0x98,0x9A,0x38,0x3A,0xB8,0xBA,
537 0x0C,0x0E,0x8C,0x8E,0x2C,0x2E,0xAC,0xAE, 0x1C,0x1E,0x9C,0x9E,0x3C,0x3E,0xBC,0xBE,
538 0x48,0x4A,0xC8,0xCA,0x68,0x6A,0xE8,0xEA, 0x58,0x5A,0xD8,0xDA,0x78,0x7A,0xF8,0xFA,
539 0x4C,0x4E,0xCC,0xCE,0x6C,0x6E,0xEC,0xEE, 0x5C,0x5E,0xDC,0xDE,0x7C,0x7E,0xFC,0xFE,
540 0x09,0x0B,0x89,0x8B,0x29,0x2B,0xA9,0xAB, 0x19,0x1B,0x99,0x9B,0x39,0x3B,0xB9,0xBB,
541 0x0D,0x0F,0x8D,0x8F,0x2D,0x2F,0xAD,0xAF, 0x1D,0x1F,0x9D,0x9F,0x3D,0x3F,0xBD,0xBF,
542 0x49,0x4B,0xC9,0xCB,0x69,0x6B,0xE9,0xEB, 0x59,0x5B,0xD9,0xDB,0x79,0x7B,0xF9,0xFB,
543 0x4D,0x4F,0xCD,0xCF,0x6D,0x6F,0xED,0xEF, 0x5D,0x5F,0xDD,0xDF,0x7D,0x7F,0xFD,0xFF,
546 static void csa_BlockDecypher( uint8_t kk[57], uint8_t ib[8], uint8_t bd[8] )
553 for( i = 0; i < 8; i++ )
558 // loop over kk[56]..kk[1]
559 for( i = 56; i > 0; i-- )
561 const int sbox_out = block_sbox[ kk[i]^R[7] ];
562 perm_out = block_perm[sbox_out];
565 R[7] = R[6] ^ perm_out;
567 R[5] = R[4] ^ R[8] ^ sbox_out;
568 R[4] = R[3] ^ R[8] ^ sbox_out;
569 R[3] = R[2] ^ R[8] ^ sbox_out;
571 R[1] = R[8] ^ sbox_out;
576 for( i = 0; i < 8; i++ )
582 static void csa_BlockCypher( uint8_t kk[57], uint8_t bd[8], uint8_t ib[8] )
589 for( i = 0; i < 8; i++ )
594 // loop over kk[1]..kk[56]
595 for( i = 1; i <= 56; i++ )
597 const int sbox_out = block_sbox[ kk[i]^R[8] ];
598 perm_out = block_perm[sbox_out];
605 R[6] = R[7] ^ perm_out;
607 R[8] = R[1] ^ sbox_out;
612 for( i = 0; i < 8; i++ )