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.
36 /* odd and even keys */
51 static void csa_ComputeKey( uint8_t kk[57], uint8_t ck[8] );
53 static void csa_StreamCypher( csa_t *c, int b_init, uint8_t *ck, uint8_t *sb, uint8_t *cb );
55 static void csa_BlockDecypher( uint8_t kk[57], uint8_t ib[8], uint8_t bd[8] );
56 static void csa_BlockCypher( uint8_t kk[57], uint8_t bd[8], uint8_t ib[8] );
58 /*****************************************************************************
60 *****************************************************************************/
61 csa_t *csa_New( void )
63 csa_t *c = malloc( sizeof( csa_t ) );
64 memset( c, 0, sizeof( csa_t ) );
69 /*****************************************************************************
71 *****************************************************************************/
72 void csa_Delete( csa_t *c )
77 /*****************************************************************************
79 *****************************************************************************/
80 void csa_SetCW( csa_t *c, uint8_t o_ck[8], uint8_t e_ck[8] )
82 memcpy( c->o_ck, o_ck, 8 );
83 csa_ComputeKey( c->o_kk, o_ck );
85 memcpy( c->e_ck, e_ck, 8 );
86 csa_ComputeKey( c->e_kk, e_ck );
89 /*****************************************************************************
91 *****************************************************************************/
92 void csa_Decrypt( csa_t *c, uint8_t *pkt, int i_pkt_size )
97 uint8_t ib[8], stream[8], block[8];
102 /* transport scrambling control */
103 if( (pkt[3]&0x80) == 0 )
119 /* clear transport scrambling control */
125 /* skip adaption field */
129 if( 188 - i_hdr < 8 )
133 csa_StreamCypher( c, 1, ck, &pkt[i_hdr], ib );
136 n = (i_pkt_size - i_hdr) / 8;
140 i_residue = (i_pkt_size - i_hdr) % 8;
141 for( i = 1; i < n + 1; i++ )
143 csa_BlockDecypher( kk, ib, block );
146 csa_StreamCypher( c, 0, ck, NULL, stream );
147 for( j = 0; j < 8; j++ )
149 /* xor ib with stream */
150 ib[j] = pkt[i_hdr+8*i+j] ^ stream[j];
156 for( j = 0; j < 8; j++ )
161 /* xor ib with block */
162 for( j = 0; j < 8; j++ )
164 pkt[i_hdr+8*(i-1)+j] = ib[j] ^ block[j];
170 csa_StreamCypher( c, 0, ck, NULL, stream );
171 for( j = 0; j < i_residue; j++ )
173 pkt[i_pkt_size - i_residue + j] ^= stream[j];
178 /*****************************************************************************
180 *****************************************************************************/
181 void csa_Encrypt( csa_t *c, uint8_t *pkt, int i_pkt_size, int b_odd )
187 int i_hdr = 4; /* hdr len */
188 uint8_t ib[184/8+2][8], stream[8], block[8];
191 /* set transport scrambling control */
213 /* skip adaption field */
216 n = (i_pkt_size - i_hdr) / 8;
217 i_residue = (i_pkt_size - i_hdr) % 8;
226 for( i = 0; i < 8; i++ )
230 for( i = n; i > 0; i-- )
232 for( j = 0; j < 8; j++ )
234 block[j] = pkt[i_hdr+8*(i-1)+j] ^ib[i+1][j];
236 csa_BlockCypher( kk, block, ib[i] );
240 csa_StreamCypher( c, 1, ck, ib[1], stream );
242 for( i = 0; i < 8; i++ )
244 pkt[i_hdr+i] = ib[1][i];
246 for( i = 2; i < n+1; i++ )
248 csa_StreamCypher( c, 0, ck, NULL, stream );
249 for( j = 0; j < 8; j++ )
251 pkt[i_hdr+8*(i-1)+j] = ib[i][j] ^ stream[j];
256 csa_StreamCypher( c, 0, ck, NULL, stream );
257 for( j = 0; j < i_residue; j++ )
259 pkt[i_pkt_size - i_residue + j] ^= stream[j];
264 /*****************************************************************************
266 *****************************************************************************/
267 static const uint8_t key_perm[0x40] =
269 0x12,0x24,0x09,0x07,0x2A,0x31,0x1D,0x15,0x1C,0x36,0x3E,0x32,0x13,0x21,0x3B,0x40,
270 0x18,0x14,0x25,0x27,0x02,0x35,0x1B,0x01,0x22,0x04,0x0D,0x0E,0x39,0x28,0x1A,0x29,
271 0x33,0x23,0x34,0x0C,0x16,0x30,0x1E,0x3A,0x2D,0x1F,0x08,0x19,0x17,0x2F,0x3D,0x11,
272 0x3C,0x05,0x38,0x2B,0x0B,0x06,0x0A,0x2C,0x20,0x3F,0x2E,0x0F,0x03,0x26,0x10,0x37,
275 static void csa_ComputeKey( uint8_t kk[57], uint8_t ck[8] )
282 /* from a cw create 56 key bytes, here kk[1..56] */
284 /* load ck into kb[7][1..8] */
285 for( i = 0; i < 8; i++ )
290 /* calculate all kb[6..1][*] */
291 for( i = 0; i < 7; i++ )
293 /* do a 64 bit perm on kb */
294 for( j = 0; j < 8; j++ )
296 for( k = 0; k < 8; k++ )
298 bit[j*8+k] = (kb[7-i][1+j] >> (7-k)) & 1;
299 newbit[key_perm[j*8+k]-1] = bit[j*8+k];
302 for( j = 0; j < 8; j++ )
305 for( k = 0; k < 8; k++ )
307 kb[6-i][1+j] |= newbit[j*8+k] << (7-k);
313 for( i = 0; i < 7; i++ )
315 for( j = 0; j < 8; j++ )
317 kk[1+i*8+j] = kb[1+i][1+j] ^ i;
323 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};
324 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};
325 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};
326 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};
327 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};
328 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};
329 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};
331 static void csa_StreamCypher( csa_t *c, int b_init, uint8_t *ck, uint8_t *sb, uint8_t *cb )
335 int s1,s2,s3,s4,s5,s6,s7;
342 // load first 32 bits of CK into A[1]..A[8]
343 // load last 32 bits of CK into B[1]..B[8]
344 // all other regs = 0
345 for( i = 0; i < 4; i++ )
347 c->A[1+2*i+0] = ( ck[i] >> 4 )&0x0f;
348 c->A[1+2*i+1] = ( ck[i] >> 0 )&0x0f;
350 c->B[1+2*i+0] = ( ck[4+i] >> 4 )&0x0f;
351 c->B[1+2*i+1] = ( ck[4+i] >> 0 )&0x0f;
354 c->A[9] = c->A[10] = 0;
355 c->B[9] = c->B[10] = 0;
357 c->X = c->Y = c->Z = 0;
358 c->D = c->E = c->F = 0;
359 c->p = c->q = c->r = 0;
362 // 8 bytes per operation
363 for( i = 0; i < 8; i++ )
366 int in1 = 0; /* gcc warn */
371 in1 = ( sb[i] >> 4 )&0x0f;
372 in2 = ( sb[i] >> 0 )&0x0f;
375 // 2 bits per iteration
376 for( j = 0; j < 4; j++ )
378 // from A[1]..A[10], 35 bits are selected as inputs to 7 s-boxes
379 // 5 bits input per s-box, 2 bits output per s-box
380 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) ];
381 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) ];
382 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) ];
383 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) ];
384 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) ];
385 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) ];
386 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) ];
388 /* use 4x4 xor to produce extra nibble for T3 */
389 extra_B = ( ((c->B[3]&1)<<3) ^ ((c->B[6]&2)<<2) ^ ((c->B[7]&4)<<1) ^ ((c->B[9]&8)>>0) ) |
390 ( ((c->B[6]&1)<<2) ^ ((c->B[8]&2)<<1) ^ ((c->B[3]&8)>>1) ^ ((c->B[4]&4)>>0) ) |
391 ( ((c->B[5]&8)>>2) ^ ((c->B[8]&4)>>1) ^ ((c->B[4]&1)<<1) ^ ((c->B[5]&2)>>0) ) |
392 ( ((c->B[9]&4)>>2) ^ ((c->B[6]&8)>>3) ^ ((c->B[3]&2)>>1) ^ ((c->B[8]&1)>>0) ) ;
394 // T1 = xor all inputs
395 // in1,in2, D are only used in T1 during initialisation, not generation
396 next_A1 = c->A[10] ^ c->X;
397 if( b_init ) next_A1 = next_A1 ^ c->D ^ ((j % 2) ? in2 : in1);
399 // T2 = xor all inputs
400 // in1,in2 are only used in T1 during initialisation, not generation
401 // if p=0, use this, if p=1, rotate the result left
402 next_B1 = c->B[7] ^ c->B[10] ^ c->Y;
403 if( b_init) next_B1 = next_B1 ^ ((j % 2) ? in1 : in2);
405 // if p=1, rotate left
406 if( c->p ) next_B1 = ( (next_B1 << 1) | ((next_B1 >> 3) & 1) ) & 0xf;
408 // T3 = xor all inputs
409 c->D = c->E ^ c->Z ^ extra_B;
411 // T4 = sum, carry of Z + E + r
415 c->F = c->Z + c->E + c->r;
417 c->r = (c->F >> 4) & 1;
426 for( k = 10; k > 1; k-- )
434 c->X = ((s4&1)<<3) | ((s3&1)<<2) | (s2&2) | ((s1&2)>>1);
435 c->Y = ((s6&1)<<3) | ((s5&1)<<2) | (s4&2) | ((s3&2)>>1);
436 c->Z = ((s2&1)<<3) | ((s1&1)<<2) | (s6&2) | ((s5&2)>>1);
440 // require 4 loops per output byte
441 // 2 output bits are a function of the 4 bits of D
443 op = (op << 2)^ ( (((c->D^(c->D>>1))>>1)&2) | ((c->D^(c->D>>1))&1) );
445 // return input data during init
446 cb[i] = b_init ? sb[i] : op;
452 static const uint8_t block_sbox[256] =
454 0x3A,0xEA,0x68,0xFE,0x33,0xE9,0x88,0x1A,0x83,0xCF,0xE1,0x7F,0xBA,0xE2,0x38,0x12,
455 0xE8,0x27,0x61,0x95,0x0C,0x36,0xE5,0x70,0xA2,0x06,0x82,0x7C,0x17,0xA3,0x26,0x49,
456 0xBE,0x7A,0x6D,0x47,0xC1,0x51,0x8F,0xF3,0xCC,0x5B,0x67,0xBD,0xCD,0x18,0x08,0xC9,
457 0xFF,0x69,0xEF,0x03,0x4E,0x48,0x4A,0x84,0x3F,0xB4,0x10,0x04,0xDC,0xF5,0x5C,0xC6,
458 0x16,0xAB,0xAC,0x4C,0xF1,0x6A,0x2F,0x3C,0x3B,0xD4,0xD5,0x94,0xD0,0xC4,0x63,0x62,
459 0x71,0xA1,0xF9,0x4F,0x2E,0xAA,0xC5,0x56,0xE3,0x39,0x93,0xCE,0x65,0x64,0xE4,0x58,
460 0x6C,0x19,0x42,0x79,0xDD,0xEE,0x96,0xF6,0x8A,0xEC,0x1E,0x85,0x53,0x45,0xDE,0xBB,
461 0x7E,0x0A,0x9A,0x13,0x2A,0x9D,0xC2,0x5E,0x5A,0x1F,0x32,0x35,0x9C,0xA8,0x73,0x30,
463 0x29,0x3D,0xE7,0x92,0x87,0x1B,0x2B,0x4B,0xA5,0x57,0x97,0x40,0x15,0xE6,0xBC,0x0E,
464 0xEB,0xC3,0x34,0x2D,0xB8,0x44,0x25,0xA4,0x1C,0xC7,0x23,0xED,0x90,0x6E,0x50,0x00,
465 0x99,0x9E,0x4D,0xD9,0xDA,0x8D,0x6F,0x5F,0x3E,0xD7,0x21,0x74,0x86,0xDF,0x6B,0x05,
466 0x8E,0x5D,0x37,0x11,0xD2,0x28,0x75,0xD6,0xA7,0x77,0x24,0xBF,0xF0,0xB0,0x02,0xB7,
467 0xF8,0xFC,0x81,0x09,0xB1,0x01,0x76,0x91,0x7D,0x0F,0xC8,0xA0,0xF2,0xCB,0x78,0x60,
468 0xD1,0xF7,0xE0,0xB5,0x98,0x22,0xB3,0x20,0x1D,0xA6,0xDB,0x7B,0x59,0x9F,0xAE,0x31,
469 0xFB,0xD3,0xB6,0xCA,0x43,0x72,0x07,0xF4,0xD8,0x41,0x14,0x55,0x0D,0x54,0x8B,0xB9,
470 0xAD,0x46,0x0B,0xAF,0x80,0x52,0x2C,0xFA,0x8C,0x89,0x66,0xFD,0xB2,0xA9,0x9B,0xC0,
474 static const uint8_t block_perm[256] =
476 0x00,0x02,0x80,0x82,0x20,0x22,0xA0,0xA2, 0x10,0x12,0x90,0x92,0x30,0x32,0xB0,0xB2,
477 0x04,0x06,0x84,0x86,0x24,0x26,0xA4,0xA6, 0x14,0x16,0x94,0x96,0x34,0x36,0xB4,0xB6,
478 0x40,0x42,0xC0,0xC2,0x60,0x62,0xE0,0xE2, 0x50,0x52,0xD0,0xD2,0x70,0x72,0xF0,0xF2,
479 0x44,0x46,0xC4,0xC6,0x64,0x66,0xE4,0xE6, 0x54,0x56,0xD4,0xD6,0x74,0x76,0xF4,0xF6,
480 0x01,0x03,0x81,0x83,0x21,0x23,0xA1,0xA3, 0x11,0x13,0x91,0x93,0x31,0x33,0xB1,0xB3,
481 0x05,0x07,0x85,0x87,0x25,0x27,0xA5,0xA7, 0x15,0x17,0x95,0x97,0x35,0x37,0xB5,0xB7,
482 0x41,0x43,0xC1,0xC3,0x61,0x63,0xE1,0xE3, 0x51,0x53,0xD1,0xD3,0x71,0x73,0xF1,0xF3,
483 0x45,0x47,0xC5,0xC7,0x65,0x67,0xE5,0xE7, 0x55,0x57,0xD5,0xD7,0x75,0x77,0xF5,0xF7,
485 0x08,0x0A,0x88,0x8A,0x28,0x2A,0xA8,0xAA, 0x18,0x1A,0x98,0x9A,0x38,0x3A,0xB8,0xBA,
486 0x0C,0x0E,0x8C,0x8E,0x2C,0x2E,0xAC,0xAE, 0x1C,0x1E,0x9C,0x9E,0x3C,0x3E,0xBC,0xBE,
487 0x48,0x4A,0xC8,0xCA,0x68,0x6A,0xE8,0xEA, 0x58,0x5A,0xD8,0xDA,0x78,0x7A,0xF8,0xFA,
488 0x4C,0x4E,0xCC,0xCE,0x6C,0x6E,0xEC,0xEE, 0x5C,0x5E,0xDC,0xDE,0x7C,0x7E,0xFC,0xFE,
489 0x09,0x0B,0x89,0x8B,0x29,0x2B,0xA9,0xAB, 0x19,0x1B,0x99,0x9B,0x39,0x3B,0xB9,0xBB,
490 0x0D,0x0F,0x8D,0x8F,0x2D,0x2F,0xAD,0xAF, 0x1D,0x1F,0x9D,0x9F,0x3D,0x3F,0xBD,0xBF,
491 0x49,0x4B,0xC9,0xCB,0x69,0x6B,0xE9,0xEB, 0x59,0x5B,0xD9,0xDB,0x79,0x7B,0xF9,0xFB,
492 0x4D,0x4F,0xCD,0xCF,0x6D,0x6F,0xED,0xEF, 0x5D,0x5F,0xDD,0xDF,0x7D,0x7F,0xFD,0xFF,
495 static void csa_BlockDecypher( uint8_t kk[57], uint8_t ib[8], uint8_t bd[8] )
502 for( i = 0; i < 8; i++ )
507 // loop over kk[56]..kk[1]
508 for( i = 56; i > 0; i-- )
510 const int sbox_out = block_sbox[ kk[i]^R[7] ];
511 perm_out = block_perm[sbox_out];
514 R[7] = R[6] ^ perm_out;
516 R[5] = R[4] ^ R[8] ^ sbox_out;
517 R[4] = R[3] ^ R[8] ^ sbox_out;
518 R[3] = R[2] ^ R[8] ^ sbox_out;
520 R[1] = R[8] ^ sbox_out;
525 for( i = 0; i < 8; i++ )
531 static void csa_BlockCypher( uint8_t kk[57], uint8_t bd[8], uint8_t ib[8] )
538 for( i = 0; i < 8; i++ )
543 // loop over kk[1]..kk[56]
544 for( i = 1; i <= 56; i++ )
546 const int sbox_out = block_sbox[ kk[i]^R[8] ];
547 perm_out = block_perm[sbox_out];
554 R[6] = R[7] ^ perm_out;
556 R[8] = R[1] ^ sbox_out;
561 for( i = 0; i < 8; i++ )