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.
37 /* odd and even keys */
52 static void csa_ComputeKey( uint8_t kk[57], uint8_t ck[8] );
54 static void csa_StreamCypher( csa_t *c, int b_init, uint8_t *ck, uint8_t *sb, uint8_t *cb );
56 static void csa_BlockDecypher( uint8_t kk[57], uint8_t ib[8], uint8_t bd[8] );
57 static void csa_BlockCypher( uint8_t kk[57], uint8_t bd[8], uint8_t ib[8] );
59 /*****************************************************************************
61 *****************************************************************************/
64 csa_t *c = malloc( sizeof( csa_t ) );
65 memset( c, 0, sizeof( csa_t ) );
70 /*****************************************************************************
72 *****************************************************************************/
73 void csa_Delete( csa_t *c )
78 /*****************************************************************************
80 *****************************************************************************/
81 void csa_SetCW( csa_t *c, uint8_t o_ck[8], uint8_t e_ck[8] )
83 memcpy( c->o_ck, o_ck, 8 );
84 csa_ComputeKey( c->o_kk, o_ck );
86 memcpy( c->e_ck, e_ck, 8 );
87 csa_ComputeKey( c->e_kk, e_ck );
90 /*****************************************************************************
92 *****************************************************************************/
93 void csa_Decrypt( csa_t *c, uint8_t *pkt, int i_pkt_size )
98 uint8_t ib[8], stream[8], block[8];
100 int i_hdr, i_residue;
103 /* transport scrambling control */
104 if( (pkt[3]&0x80) == 0 )
120 /* clear transport scrambling control */
126 /* skip adaption field */
130 if( 188 - i_hdr < 8 )
134 csa_StreamCypher( c, 1, ck, &pkt[i_hdr], ib );
137 n = (i_pkt_size - i_hdr) / 8;
141 i_residue = (i_pkt_size - i_hdr) % 8;
142 for( i = 1; i < n + 1; i++ )
144 csa_BlockDecypher( kk, ib, block );
147 csa_StreamCypher( c, 0, ck, NULL, stream );
148 for( j = 0; j < 8; j++ )
150 /* xor ib with stream */
151 ib[j] = pkt[i_hdr+8*i+j] ^ stream[j];
157 for( j = 0; j < 8; j++ )
162 /* xor ib with block */
163 for( j = 0; j < 8; j++ )
165 pkt[i_hdr+8*(i-1)+j] = ib[j] ^ block[j];
171 csa_StreamCypher( c, 0, ck, NULL, stream );
172 for( j = 0; j < i_residue; j++ )
174 pkt[i_pkt_size - i_residue + j] ^= stream[j];
179 /*****************************************************************************
181 *****************************************************************************/
182 void csa_Encrypt( csa_t *c, uint8_t *pkt, int i_pkt_size, int b_odd )
188 int i_hdr = 4; /* hdr len */
189 uint8_t ib[184/8+2][8], stream[8], block[8];
192 /* set transport scrambling control */
214 /* skip adaption field */
217 n = (i_pkt_size - i_hdr) / 8;
218 i_residue = (i_pkt_size - i_hdr) % 8;
227 for( i = 0; i < 8; i++ )
231 for( i = n; i > 0; i-- )
233 for( j = 0; j < 8; j++ )
235 block[j] = pkt[i_hdr+8*(i-1)+j] ^ib[i+1][j];
237 csa_BlockCypher( kk, block, ib[i] );
241 csa_StreamCypher( c, 1, ck, ib[1], stream );
243 for( i = 0; i < 8; i++ )
245 pkt[i_hdr+i] = ib[1][i];
247 for( i = 2; i < n+1; i++ )
249 csa_StreamCypher( c, 0, ck, NULL, stream );
250 for( j = 0; j < 8; j++ )
252 pkt[i_hdr+8*(i-1)+j] = ib[i][j] ^ stream[j];
257 csa_StreamCypher( c, 0, ck, NULL, stream );
258 for( j = 0; j < i_residue; j++ )
260 pkt[i_pkt_size - i_residue + j] ^= stream[j];
265 /*****************************************************************************
267 *****************************************************************************/
268 static const uint8_t key_perm[0x40] =
270 0x12,0x24,0x09,0x07,0x2A,0x31,0x1D,0x15,0x1C,0x36,0x3E,0x32,0x13,0x21,0x3B,0x40,
271 0x18,0x14,0x25,0x27,0x02,0x35,0x1B,0x01,0x22,0x04,0x0D,0x0E,0x39,0x28,0x1A,0x29,
272 0x33,0x23,0x34,0x0C,0x16,0x30,0x1E,0x3A,0x2D,0x1F,0x08,0x19,0x17,0x2F,0x3D,0x11,
273 0x3C,0x05,0x38,0x2B,0x0B,0x06,0x0A,0x2C,0x20,0x3F,0x2E,0x0F,0x03,0x26,0x10,0x37,
276 static void csa_ComputeKey( uint8_t kk[57], uint8_t ck[8] )
283 /* from a cw create 56 key bytes, here kk[1..56] */
285 /* load ck into kb[7][1..8] */
286 for( i = 0; i < 8; i++ )
291 /* calculate all kb[6..1][*] */
292 for( i = 0; i < 7; i++ )
294 /* do a 64 bit perm on kb */
295 for( j = 0; j < 8; j++ )
297 for( k = 0; k < 8; k++ )
299 bit[j*8+k] = (kb[7-i][1+j] >> (7-k)) & 1;
300 newbit[key_perm[j*8+k]-1] = bit[j*8+k];
303 for( j = 0; j < 8; j++ )
306 for( k = 0; k < 8; k++ )
308 kb[6-i][1+j] |= newbit[j*8+k] << (7-k);
314 for( i = 0; i < 7; i++ )
316 for( j = 0; j < 8; j++ )
318 kk[1+i*8+j] = kb[1+i][1+j] ^ i;
324 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};
325 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};
326 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};
327 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};
328 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};
329 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};
330 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};
332 static void csa_StreamCypher( csa_t *c, int b_init, uint8_t *ck, uint8_t *sb, uint8_t *cb )
336 int s1,s2,s3,s4,s5,s6,s7;
343 // load first 32 bits of CK into A[1]..A[8]
344 // load last 32 bits of CK into B[1]..B[8]
345 // all other regs = 0
346 for( i = 0; i < 4; i++ )
348 c->A[1+2*i+0] = ( ck[i] >> 4 )&0x0f;
349 c->A[1+2*i+1] = ( ck[i] >> 0 )&0x0f;
351 c->B[1+2*i+0] = ( ck[4+i] >> 4 )&0x0f;
352 c->B[1+2*i+1] = ( ck[4+i] >> 0 )&0x0f;
355 c->A[9] = c->A[10] = 0;
356 c->B[9] = c->B[10] = 0;
358 c->X = c->Y = c->Z = 0;
359 c->D = c->E = c->F = 0;
360 c->p = c->q = c->r = 0;
363 // 8 bytes per operation
364 for( i = 0; i < 8; i++ )
367 int in1 = 0; /* gcc warn */
372 in1 = ( sb[i] >> 4 )&0x0f;
373 in2 = ( sb[i] >> 0 )&0x0f;
376 // 2 bits per iteration
377 for( j = 0; j < 4; j++ )
379 // from A[1]..A[10], 35 bits are selected as inputs to 7 s-boxes
380 // 5 bits input per s-box, 2 bits output per s-box
381 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) ];
382 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) ];
383 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) ];
384 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) ];
385 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) ];
386 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) ];
387 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) ];
389 /* use 4x4 xor to produce extra nibble for T3 */
390 extra_B = ( ((c->B[3]&1)<<3) ^ ((c->B[6]&2)<<2) ^ ((c->B[7]&4)<<1) ^ ((c->B[9]&8)>>0) ) |
391 ( ((c->B[6]&1)<<2) ^ ((c->B[8]&2)<<1) ^ ((c->B[3]&8)>>1) ^ ((c->B[4]&4)>>0) ) |
392 ( ((c->B[5]&8)>>2) ^ ((c->B[8]&4)>>1) ^ ((c->B[4]&1)<<1) ^ ((c->B[5]&2)>>0) ) |
393 ( ((c->B[9]&4)>>2) ^ ((c->B[6]&8)>>3) ^ ((c->B[3]&2)>>1) ^ ((c->B[8]&1)>>0) ) ;
395 // T1 = xor all inputs
396 // in1,in2, D are only used in T1 during initialisation, not generation
397 next_A1 = c->A[10] ^ c->X;
398 if( b_init ) next_A1 = next_A1 ^ c->D ^ ((j % 2) ? in2 : in1);
400 // T2 = xor all inputs
401 // in1,in2 are only used in T1 during initialisation, not generation
402 // if p=0, use this, if p=1, rotate the result left
403 next_B1 = c->B[7] ^ c->B[10] ^ c->Y;
404 if( b_init) next_B1 = next_B1 ^ ((j % 2) ? in1 : in2);
406 // if p=1, rotate left
407 if( c->p ) next_B1 = ( (next_B1 << 1) | ((next_B1 >> 3) & 1) ) & 0xf;
409 // T3 = xor all inputs
410 c->D = c->E ^ c->Z ^ extra_B;
412 // T4 = sum, carry of Z + E + r
416 c->F = c->Z + c->E + c->r;
418 c->r = (c->F >> 4) & 1;
427 for( k = 10; k > 1; k-- )
435 c->X = ((s4&1)<<3) | ((s3&1)<<2) | (s2&2) | ((s1&2)>>1);
436 c->Y = ((s6&1)<<3) | ((s5&1)<<2) | (s4&2) | ((s3&2)>>1);
437 c->Z = ((s2&1)<<3) | ((s1&1)<<2) | (s6&2) | ((s5&2)>>1);
441 // require 4 loops per output byte
442 // 2 output bits are a function of the 4 bits of D
444 op = (op << 2)^ ( (((c->D^(c->D>>1))>>1)&2) | ((c->D^(c->D>>1))&1) );
446 // return input data during init
447 cb[i] = b_init ? sb[i] : op;
453 static const uint8_t block_sbox[256] =
455 0x3A,0xEA,0x68,0xFE,0x33,0xE9,0x88,0x1A,0x83,0xCF,0xE1,0x7F,0xBA,0xE2,0x38,0x12,
456 0xE8,0x27,0x61,0x95,0x0C,0x36,0xE5,0x70,0xA2,0x06,0x82,0x7C,0x17,0xA3,0x26,0x49,
457 0xBE,0x7A,0x6D,0x47,0xC1,0x51,0x8F,0xF3,0xCC,0x5B,0x67,0xBD,0xCD,0x18,0x08,0xC9,
458 0xFF,0x69,0xEF,0x03,0x4E,0x48,0x4A,0x84,0x3F,0xB4,0x10,0x04,0xDC,0xF5,0x5C,0xC6,
459 0x16,0xAB,0xAC,0x4C,0xF1,0x6A,0x2F,0x3C,0x3B,0xD4,0xD5,0x94,0xD0,0xC4,0x63,0x62,
460 0x71,0xA1,0xF9,0x4F,0x2E,0xAA,0xC5,0x56,0xE3,0x39,0x93,0xCE,0x65,0x64,0xE4,0x58,
461 0x6C,0x19,0x42,0x79,0xDD,0xEE,0x96,0xF6,0x8A,0xEC,0x1E,0x85,0x53,0x45,0xDE,0xBB,
462 0x7E,0x0A,0x9A,0x13,0x2A,0x9D,0xC2,0x5E,0x5A,0x1F,0x32,0x35,0x9C,0xA8,0x73,0x30,
464 0x29,0x3D,0xE7,0x92,0x87,0x1B,0x2B,0x4B,0xA5,0x57,0x97,0x40,0x15,0xE6,0xBC,0x0E,
465 0xEB,0xC3,0x34,0x2D,0xB8,0x44,0x25,0xA4,0x1C,0xC7,0x23,0xED,0x90,0x6E,0x50,0x00,
466 0x99,0x9E,0x4D,0xD9,0xDA,0x8D,0x6F,0x5F,0x3E,0xD7,0x21,0x74,0x86,0xDF,0x6B,0x05,
467 0x8E,0x5D,0x37,0x11,0xD2,0x28,0x75,0xD6,0xA7,0x77,0x24,0xBF,0xF0,0xB0,0x02,0xB7,
468 0xF8,0xFC,0x81,0x09,0xB1,0x01,0x76,0x91,0x7D,0x0F,0xC8,0xA0,0xF2,0xCB,0x78,0x60,
469 0xD1,0xF7,0xE0,0xB5,0x98,0x22,0xB3,0x20,0x1D,0xA6,0xDB,0x7B,0x59,0x9F,0xAE,0x31,
470 0xFB,0xD3,0xB6,0xCA,0x43,0x72,0x07,0xF4,0xD8,0x41,0x14,0x55,0x0D,0x54,0x8B,0xB9,
471 0xAD,0x46,0x0B,0xAF,0x80,0x52,0x2C,0xFA,0x8C,0x89,0x66,0xFD,0xB2,0xA9,0x9B,0xC0,
475 static const uint8_t block_perm[256] =
477 0x00,0x02,0x80,0x82,0x20,0x22,0xA0,0xA2, 0x10,0x12,0x90,0x92,0x30,0x32,0xB0,0xB2,
478 0x04,0x06,0x84,0x86,0x24,0x26,0xA4,0xA6, 0x14,0x16,0x94,0x96,0x34,0x36,0xB4,0xB6,
479 0x40,0x42,0xC0,0xC2,0x60,0x62,0xE0,0xE2, 0x50,0x52,0xD0,0xD2,0x70,0x72,0xF0,0xF2,
480 0x44,0x46,0xC4,0xC6,0x64,0x66,0xE4,0xE6, 0x54,0x56,0xD4,0xD6,0x74,0x76,0xF4,0xF6,
481 0x01,0x03,0x81,0x83,0x21,0x23,0xA1,0xA3, 0x11,0x13,0x91,0x93,0x31,0x33,0xB1,0xB3,
482 0x05,0x07,0x85,0x87,0x25,0x27,0xA5,0xA7, 0x15,0x17,0x95,0x97,0x35,0x37,0xB5,0xB7,
483 0x41,0x43,0xC1,0xC3,0x61,0x63,0xE1,0xE3, 0x51,0x53,0xD1,0xD3,0x71,0x73,0xF1,0xF3,
484 0x45,0x47,0xC5,0xC7,0x65,0x67,0xE5,0xE7, 0x55,0x57,0xD5,0xD7,0x75,0x77,0xF5,0xF7,
486 0x08,0x0A,0x88,0x8A,0x28,0x2A,0xA8,0xAA, 0x18,0x1A,0x98,0x9A,0x38,0x3A,0xB8,0xBA,
487 0x0C,0x0E,0x8C,0x8E,0x2C,0x2E,0xAC,0xAE, 0x1C,0x1E,0x9C,0x9E,0x3C,0x3E,0xBC,0xBE,
488 0x48,0x4A,0xC8,0xCA,0x68,0x6A,0xE8,0xEA, 0x58,0x5A,0xD8,0xDA,0x78,0x7A,0xF8,0xFA,
489 0x4C,0x4E,0xCC,0xCE,0x6C,0x6E,0xEC,0xEE, 0x5C,0x5E,0xDC,0xDE,0x7C,0x7E,0xFC,0xFE,
490 0x09,0x0B,0x89,0x8B,0x29,0x2B,0xA9,0xAB, 0x19,0x1B,0x99,0x9B,0x39,0x3B,0xB9,0xBB,
491 0x0D,0x0F,0x8D,0x8F,0x2D,0x2F,0xAD,0xAF, 0x1D,0x1F,0x9D,0x9F,0x3D,0x3F,0xBD,0xBF,
492 0x49,0x4B,0xC9,0xCB,0x69,0x6B,0xE9,0xEB, 0x59,0x5B,0xD9,0xDB,0x79,0x7B,0xF9,0xFB,
493 0x4D,0x4F,0xCD,0xCF,0x6D,0x6F,0xED,0xEF, 0x5D,0x5F,0xDD,0xDF,0x7D,0x7F,0xFD,0xFF,
496 static void csa_BlockDecypher( uint8_t kk[57], uint8_t ib[8], uint8_t bd[8] )
503 for( i = 0; i < 8; i++ )
508 // loop over kk[56]..kk[1]
509 for( i = 56; i > 0; i-- )
511 const int sbox_out = block_sbox[ kk[i]^R[7] ];
512 perm_out = block_perm[sbox_out];
515 R[7] = R[6] ^ perm_out;
517 R[5] = R[4] ^ R[8] ^ sbox_out;
518 R[4] = R[3] ^ R[8] ^ sbox_out;
519 R[3] = R[2] ^ R[8] ^ sbox_out;
521 R[1] = R[8] ^ sbox_out;
526 for( i = 0; i < 8; i++ )
532 static void csa_BlockCypher( uint8_t kk[57], uint8_t bd[8], uint8_t ib[8] )
539 for( i = 0; i < 8; i++ )
544 // loop over kk[1]..kk[56]
545 for( i = 1; i <= 56; i++ )
547 const int sbox_out = block_sbox[ kk[i]^R[8] ];
548 perm_out = block_perm[sbox_out];
555 R[6] = R[7] ^ perm_out;
557 R[8] = R[1] ^ sbox_out;
562 for( i = 0; i < 8; i++ )