📄 csa.c
字号:
/***************************************************************************** * libcsa.c: CSA scrambler/descrambler ***************************************************************************** * Copyright (C) 2004-2005 Laurent Aimar * $Id$ * * Authors: Laurent Aimar <fenrir@via.ecp.fr> * Jean-Paul Saman <jpsaman #_at_# m2x.nl> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************//* * XXX: A great part is just a copy/past of deCSA but I can't find the * author and the license. If there is a problem with it please e-mail me. */#ifdef HAVE_CONFIG_H# include "config.h"#endif#include <vlc_common.h>#include "csa.h"struct csa_t{ /* odd and even keys */ uint8_t o_ck[8]; uint8_t e_ck[8]; uint8_t o_kk[57]; uint8_t e_kk[57]; /* cypher state */ int A[11]; int B[11]; int X, Y, Z; int D, E, F; int p, q, r; bool use_odd;};static void csa_ComputeKey( uint8_t kk[57], uint8_t ck[8] );static void csa_StreamCypher( csa_t *c, int b_init, uint8_t *ck, uint8_t *sb, uint8_t *cb );static void csa_BlockDecypher( uint8_t kk[57], uint8_t ib[8], uint8_t bd[8] );static void csa_BlockCypher( uint8_t kk[57], uint8_t bd[8], uint8_t ib[8] );/***************************************************************************** * csa_New: *****************************************************************************/csa_t *csa_New( void ){ csa_t *c = malloc( sizeof( csa_t ) ); memset( c, 0, sizeof( csa_t ) ); return c;}/***************************************************************************** * csa_Delete: *****************************************************************************/void csa_Delete( csa_t *c ){ free( c );}/***************************************************************************** * csa_SetCW: *****************************************************************************/int csa_SetCW( vlc_object_t *p_caller, csa_t *c, char *psz_ck, bool set_odd ){ if ( !c ) { msg_Dbg( p_caller, "no CSA found" ); return VLC_ENOOBJ; } /* skip 0x */ if( psz_ck[0] == '0' && ( psz_ck[1] == 'x' || psz_ck[1] == 'X' ) ) { psz_ck += 2; } if( strlen( psz_ck ) != 16 ) { msg_Warn( p_caller, "invalid csa ck (it must be 16 chars long)" ); return VLC_EBADVAR; } else {#ifndef UNDER_CE uint64_t i_ck = strtoull( psz_ck, NULL, 16 );#else uint64_t i_ck = strtoll( psz_ck, NULL, 16 );#endif uint8_t ck[8]; int i; for( i = 0; i < 8; i++ ) { ck[i] = ( i_ck >> ( 56 - 8*i) )&0xff; }#ifndef TS_NO_CSA_CK_MSG msg_Dbg( p_caller, "using CSA (de)scrambling with %s " "key=%x:%x:%x:%x:%x:%x:%x:%x", set_odd ? "odd" : "even", ck[0], ck[1], ck[2], ck[3], ck[4], ck[5], ck[6], ck[7] );#endif if( set_odd ) { memcpy( c->o_ck, ck, 8 ); csa_ComputeKey( c->o_kk, ck ); } else { memcpy( c->e_ck , ck, 8 ); csa_ComputeKey( c->e_kk , ck ); } return VLC_SUCCESS; }}/***************************************************************************** * csa_UseKey: *****************************************************************************/int csa_UseKey( vlc_object_t *p_caller, csa_t *c, bool use_odd ){ if ( !c ) return VLC_ENOOBJ; c->use_odd = use_odd;#ifndef TS_NO_CSA_CK_MSG msg_Dbg( p_caller, "using the %s key for scrambling", use_odd ? "odd" : "even" );#endif return VLC_SUCCESS;}/***************************************************************************** * csa_Decrypt: *****************************************************************************/void csa_Decrypt( csa_t *c, uint8_t *pkt, int i_pkt_size ){ uint8_t *ck; uint8_t *kk; uint8_t ib[8], stream[8], block[8]; int i_hdr, i_residue; int i, j, n; /* transport scrambling control */ if( (pkt[3]&0x80) == 0 ) { /* not scrambled */ return; } if( pkt[3]&0x40 ) { ck = c->o_ck; kk = c->o_kk; } else { ck = c->e_ck; kk = c->e_kk; } /* clear transport scrambling control */ pkt[3] &= 0x3f; i_hdr = 4; if( pkt[3]&0x20 ) { /* skip adaption field */ i_hdr += pkt[4] + 1; } if( 188 - i_hdr < 8 ) return; /* init csa state */ csa_StreamCypher( c, 1, ck, &pkt[i_hdr], ib ); /* */ n = (i_pkt_size - i_hdr) / 8; if( n < 0 ) return; i_residue = (i_pkt_size - i_hdr) % 8; for( i = 1; i < n + 1; i++ ) { csa_BlockDecypher( kk, ib, block ); if( i != n ) { csa_StreamCypher( c, 0, ck, NULL, stream ); for( j = 0; j < 8; j++ ) { /* xor ib with stream */ ib[j] = pkt[i_hdr+8*i+j] ^ stream[j]; } } else { /* last block */ for( j = 0; j < 8; j++ ) { ib[j] = 0; } } /* xor ib with block */ for( j = 0; j < 8; j++ ) { pkt[i_hdr+8*(i-1)+j] = ib[j] ^ block[j]; } } if( i_residue > 0 ) { csa_StreamCypher( c, 0, ck, NULL, stream ); for( j = 0; j < i_residue; j++ ) { pkt[i_pkt_size - i_residue + j] ^= stream[j]; } }}/***************************************************************************** * csa_Encrypt: *****************************************************************************/void csa_Encrypt( csa_t *c, uint8_t *pkt, int i_pkt_size ){ uint8_t *ck; uint8_t *kk; int i, j; int i_hdr = 4; /* hdr len */ uint8_t ib[184/8+2][8], stream[8], block[8]; int n, i_residue; /* set transport scrambling control */ pkt[3] |= 0x80; if( c->use_odd ) { pkt[3] |= 0x40; ck = c->o_ck; kk = c->o_kk; } else { ck = c->e_ck; kk = c->e_kk; } /* hdr len */ i_hdr = 4; if( pkt[3]&0x20 ) { /* skip adaption field */ i_hdr += pkt[4] + 1; } n = (i_pkt_size - i_hdr) / 8; i_residue = (i_pkt_size - i_hdr) % 8; if( n <= 0 ) { pkt[3] &= 0x3f; return; } /* */ for( i = 0; i < 8; i++ ) { ib[n+1][i] = 0; } for( i = n; i > 0; i-- ) { for( j = 0; j < 8; j++ ) { block[j] = pkt[i_hdr+8*(i-1)+j] ^ib[i+1][j]; } csa_BlockCypher( kk, block, ib[i] ); } /* init csa state */ csa_StreamCypher( c, 1, ck, ib[1], stream ); for( i = 0; i < 8; i++ ) { pkt[i_hdr+i] = ib[1][i]; } for( i = 2; i < n+1; i++ ) { csa_StreamCypher( c, 0, ck, NULL, stream ); for( j = 0; j < 8; j++ ) { pkt[i_hdr+8*(i-1)+j] = ib[i][j] ^ stream[j]; } } if( i_residue > 0 ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -