Commit 320337e0 authored by Kaloyan Kovachev's avatar Kaloyan Kovachev Committed by Rémi Denis-Courmont

Dynamic two-keys CSA

N.B.: I suspect there is a small race condition whereby the callbacks are
invoked while being deleted, but this looks like yet another LibVLC
objects insanity.
Signed-off-by: default avatarRémi Denis-Courmont <rdenis@simphalempin.com>
parent 75bd4e63
...@@ -87,6 +87,11 @@ ...@@ -87,6 +87,11 @@
* - ... * - ...
*/ */
/*****************************************************************************
* Callback prototypes
*****************************************************************************/
static int ChangeKeyCallback ( vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void * );
/***************************************************************************** /*****************************************************************************
* Module descriptor * Module descriptor
*****************************************************************************/ *****************************************************************************/
...@@ -113,6 +118,10 @@ static void Close ( vlc_object_t * ); ...@@ -113,6 +118,10 @@ static void Close ( vlc_object_t * );
#define CSA_TEXT N_("CSA ck") #define CSA_TEXT N_("CSA ck")
#define CSA_LONGTEXT N_("Control word for the CSA encryption algorithm") #define CSA_LONGTEXT N_("Control word for the CSA encryption algorithm")
#define CSA2_TEXT N_("Second CSA Key")
#define CSA2_LONGTEXT N_("The even CSA encryption key. This must be a " \
"16 char string (8 hexadecimal bytes).")
#define SILENT_TEXT N_("Silent mode") #define SILENT_TEXT N_("Silent mode")
#define SILENT_LONGTEXT N_("Do not complain on encrypted PES.") #define SILENT_LONGTEXT N_("Do not complain on encrypted PES.")
...@@ -149,6 +158,7 @@ vlc_module_begin(); ...@@ -149,6 +158,7 @@ vlc_module_begin();
add_integer( "ts-out-mtu", 1400, NULL, MTUOUT_TEXT, add_integer( "ts-out-mtu", 1400, NULL, MTUOUT_TEXT,
MTUOUT_LONGTEXT, true ); MTUOUT_LONGTEXT, true );
add_string( "ts-csa-ck", NULL, NULL, CSA_TEXT, CSA_LONGTEXT, true ); add_string( "ts-csa-ck", NULL, NULL, CSA_TEXT, CSA_LONGTEXT, true );
add_string( "ts-csa2-ck", NULL, NULL, CSA_TEXT, CSA_LONGTEXT, true );
add_integer( "ts-csa-pkt", 188, NULL, CPKT_TEXT, CPKT_LONGTEXT, true ); add_integer( "ts-csa-pkt", 188, NULL, CPKT_TEXT, CPKT_LONGTEXT, true );
add_bool( "ts-silent", 0, NULL, SILENT_TEXT, SILENT_LONGTEXT, true ); add_bool( "ts-silent", 0, NULL, SILENT_TEXT, SILENT_LONGTEXT, true );
...@@ -311,6 +321,8 @@ typedef struct ...@@ -311,6 +321,8 @@ typedef struct
struct demux_sys_t struct demux_sys_t
{ {
vlc_mutex_t csa_lock;
/* TS packet size (188, 192, 204) */ /* TS packet size (188, 192, 204) */
int i_packet_size; int i_packet_size;
...@@ -539,6 +551,7 @@ static int Open( vlc_object_t *p_this ) ...@@ -539,6 +551,7 @@ static int Open( vlc_object_t *p_this )
return VLC_ENOMEM; return VLC_ENOMEM;
memset( p_sys, 0, sizeof( demux_sys_t ) ); memset( p_sys, 0, sizeof( demux_sys_t ) );
p_sys->i_packet_size = i_packet_size; p_sys->i_packet_size = i_packet_size;
vlc_mutex_init( &p_sys->csa_lock );
/* Fill dump mode fields */ /* Fill dump mode fields */
p_sys->i_write = 0; p_sys->i_write = 0;
...@@ -773,24 +786,42 @@ static int Open( vlc_object_t *p_this ) ...@@ -773,24 +786,42 @@ static int Open( vlc_object_t *p_this )
} }
free( val.psz_string ); free( val.psz_string );
var_Create( p_demux, "ts-csa-ck", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); var_Create( p_demux, "ts-csa-ck", VLC_VAR_STRING | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );
var_Get( p_demux, "ts-csa-ck", &val ); var_Get( p_demux, "ts-csa-ck", &val );
if( val.psz_string && *val.psz_string ) if( val.psz_string && *val.psz_string )
{ {
int i_res; int i_res;
vlc_value_t csa2;
p_sys->csa = csa_New(); p_sys->csa = csa_New();
i_res = csa_SetCW( (vlc_object_t*)p_demux, p_sys->csa, val.psz_string, 1 ); var_Create( p_demux, "ts-csa2-ck", VLC_VAR_STRING | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND);
if( i_res != VLC_SUCCESS || csa_SetCW( (vlc_object_t*)p_demux, p_sys->csa, val.psz_string, 0 ) != VLC_SUCCESS ) var_Get( p_demux, "ts-csa2-ck", &csa2 );
i_res = csa_SetCW( (vlc_object_t*)p_demux, p_sys->csa, val.psz_string, true );
if( i_res == VLC_SUCCESS && csa2.psz_string && *csa2.psz_string )
{
if( csa_SetCW( (vlc_object_t*)p_demux, p_sys->csa, csa2.psz_string, false ) != VLC_SUCCESS )
{
csa_SetCW( (vlc_object_t*)p_demux, p_sys->csa, val.psz_string, false );
}
}
else if ( i_res == VLC_SUCCESS )
{
csa_SetCW( (vlc_object_t*)p_demux, p_sys->csa, val.psz_string, false );
}
else
{ {
csa_Delete( p_sys->csa ); csa_Delete( p_sys->csa );
p_sys->csa = NULL;
} }
if( p_sys->csa ) if( p_sys->csa )
{ {
vlc_value_t pkt_val; vlc_value_t pkt_val;
var_AddCallback( p_demux, "ts-csa-ck", ChangeKeyCallback, (void *)1 );
var_AddCallback( p_demux, "ts-csa2-ck", ChangeKeyCallback, NULL );
var_Create( p_demux, "ts-csa-pkt", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); var_Create( p_demux, "ts-csa-pkt", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
var_Get( p_demux, "ts-csa-pkt", &pkt_val ); var_Get( p_demux, "ts-csa-pkt", &pkt_val );
if( pkt_val.i_int < 4 || pkt_val.i_int > 188 ) if( pkt_val.i_int < 4 || pkt_val.i_int > 188 )
...@@ -802,6 +833,7 @@ static int Open( vlc_object_t *p_this ) ...@@ -802,6 +833,7 @@ static int Open( vlc_object_t *p_this )
else p_sys->i_csa_pkt_size = pkt_val.i_int; else p_sys->i_csa_pkt_size = pkt_val.i_int;
msg_Dbg( p_demux, "decrypting %d bytes of packet", p_sys->i_csa_pkt_size ); msg_Dbg( p_demux, "decrypting %d bytes of packet", p_sys->i_csa_pkt_size );
} }
free( csa2.psz_string );
} }
free( val.psz_string ); free( val.psz_string );
...@@ -873,10 +905,15 @@ static void Close( vlc_object_t *p_this ) ...@@ -873,10 +905,15 @@ static void Close( vlc_object_t *p_this )
net_Close( p_sys->fd ); net_Close( p_sys->fd );
free( p_sys->buffer ); free( p_sys->buffer );
} }
vlc_mutex_lock( &p_sys->csa_lock );
if( p_sys->csa ) if( p_sys->csa )
{ {
var_DelCallback( p_demux, "ts-csa-ck", ChangeKeyCallback, NULL );
var_DelCallback( p_demux, "ts-csa2-ck", ChangeKeyCallback, NULL );
csa_Delete( p_sys->csa ); csa_Delete( p_sys->csa );
p_sys->csa = NULL;
} }
vlc_mutex_unlock( &p_sys->csa_lock );
if( p_sys->i_pmt ) free( p_sys->pmt ); if( p_sys->i_pmt ) free( p_sys->pmt );
...@@ -905,9 +942,32 @@ static void Close( vlc_object_t *p_this ) ...@@ -905,9 +942,32 @@ static void Close( vlc_object_t *p_this )
free( p_sys->psz_file ); free( p_sys->psz_file );
p_sys->psz_file = NULL; p_sys->psz_file = NULL;
vlc_mutex_destroy( &p_sys->csa_lock );
free( p_sys ); free( p_sys );
} }
/*****************************************************************************
* ChangeKeyCallback: called when changing the odd encryption key on the fly.
*****************************************************************************/
static int ChangeKeyCallback( vlc_object_t *p_this, char const *psz_cmd,
vlc_value_t oldval, vlc_value_t newval,
void *p_data )
{
VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval);
demux_t *p_demux = (demux_t*)p_this;
demux_sys_t *p_sys = p_demux->p_sys;
int i_tmp = (intptr_t)p_data;
vlc_mutex_lock( &p_sys->csa_lock );
if ( i_tmp )
i_tmp = csa_SetCW( p_this, p_sys->csa, newval.psz_string, true );
else
i_tmp = csa_SetCW( p_this, p_sys->csa, newval.psz_string, false );
vlc_mutex_unlock( &p_sys->csa_lock );
return i_tmp;
}
/***************************************************************************** /*****************************************************************************
* DemuxFile: * DemuxFile:
*****************************************************************************/ *****************************************************************************/
...@@ -997,7 +1057,11 @@ static int DemuxFile( demux_t *p_demux ) ...@@ -997,7 +1057,11 @@ static int DemuxFile( demux_t *p_demux )
/* Test if user wants to decrypt it first */ /* Test if user wants to decrypt it first */
if( p_sys->csa ) if( p_sys->csa )
{
vlc_mutex_lock( &p_sys->csa_lock );
csa_Decrypt( p_demux->p_sys->csa, &p_buffer[i_pos], p_demux->p_sys->i_csa_pkt_size ); csa_Decrypt( p_demux->p_sys->csa, &p_buffer[i_pos], p_demux->p_sys->i_csa_pkt_size );
vlc_mutex_unlock( &p_sys->csa_lock );
}
i_pos += p_sys->i_packet_size; i_pos += p_sys->i_packet_size;
} }
...@@ -1789,7 +1853,9 @@ static bool GatherPES( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk ) ...@@ -1789,7 +1853,9 @@ static bool GatherPES( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk )
if( p_demux->p_sys->csa ) if( p_demux->p_sys->csa )
{ {
vlc_mutex_lock( &p_demux->p_sys->csa_lock );
csa_Decrypt( p_demux->p_sys->csa, p_bk->p_buffer, p_demux->p_sys->i_csa_pkt_size ); csa_Decrypt( p_demux->p_sys->csa, p_bk->p_buffer, p_demux->p_sys->i_csa_pkt_size );
vlc_mutex_unlock( &p_demux->p_sys->csa_lock );
} }
if( !b_adaptation ) if( !b_adaptation )
......
...@@ -50,6 +50,8 @@ struct csa_t ...@@ -50,6 +50,8 @@ struct csa_t
int X, Y, Z; int X, Y, Z;
int D, E, F; int D, E, F;
int p, q, r; int p, q, r;
bool use_odd;
}; };
static void csa_ComputeKey( uint8_t kk[57], uint8_t ck[8] ); static void csa_ComputeKey( uint8_t kk[57], uint8_t ck[8] );
...@@ -81,12 +83,12 @@ void csa_Delete( csa_t *c ) ...@@ -81,12 +83,12 @@ void csa_Delete( csa_t *c )
/***************************************************************************** /*****************************************************************************
* csa_SetCW: * csa_SetCW:
*****************************************************************************/ *****************************************************************************/
int csa_SetCW( vlc_object_t *p_caller, csa_t *c, char *psz_ck, int set_odd ) int csa_SetCW( vlc_object_t *p_caller, csa_t *c, char *psz_ck, bool set_odd )
{ {
if ( !c ) if ( !c )
{ {
msg_Dbg( p_caller, "no CSA found" ); msg_Dbg( p_caller, "no CSA found" );
return VLC_EGENERIC; return VLC_ENOOBJ;
} }
/* skip 0x */ /* skip 0x */
if( psz_ck[0] == '0' && ( psz_ck[1] == 'x' || psz_ck[1] == 'X' ) ) if( psz_ck[0] == '0' && ( psz_ck[1] == 'x' || psz_ck[1] == 'X' ) )
...@@ -96,7 +98,7 @@ int csa_SetCW( vlc_object_t *p_caller, csa_t *c, char *psz_ck, int set_odd ) ...@@ -96,7 +98,7 @@ int csa_SetCW( vlc_object_t *p_caller, csa_t *c, char *psz_ck, int set_odd )
if( strlen( psz_ck ) != 16 ) if( strlen( psz_ck ) != 16 )
{ {
msg_Warn( p_caller, "invalid csa ck (it must be 16 chars long)" ); msg_Warn( p_caller, "invalid csa ck (it must be 16 chars long)" );
return VLC_EGENERIC; return VLC_EBADVAR;
} }
else else
{ {
...@@ -113,10 +115,11 @@ int csa_SetCW( vlc_object_t *p_caller, csa_t *c, char *psz_ck, int set_odd ) ...@@ -113,10 +115,11 @@ int csa_SetCW( vlc_object_t *p_caller, csa_t *c, char *psz_ck, int set_odd )
ck[i] = ( i_ck >> ( 56 - 8*i) )&0xff; ck[i] = ( i_ck >> ( 56 - 8*i) )&0xff;
} }
#ifndef TS_NO_CSA_CK_MSG #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 == 1) ? "odd" : "even" ), 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] ); ck[0], ck[1], ck[2], ck[3], ck[4], ck[5], ck[6], ck[7] );
#endif #endif
if ( set_odd == 1 ) if( set_odd )
{ {
memcpy( c->o_ck, ck, 8 ); memcpy( c->o_ck, ck, 8 );
csa_ComputeKey( c->o_kk, ck ); csa_ComputeKey( c->o_kk, ck );
...@@ -130,6 +133,20 @@ int csa_SetCW( vlc_object_t *p_caller, csa_t *c, char *psz_ck, int set_odd ) ...@@ -130,6 +133,20 @@ int csa_SetCW( vlc_object_t *p_caller, csa_t *c, char *psz_ck, int set_odd )
} }
} }
/*****************************************************************************
* 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: * csa_Decrypt:
*****************************************************************************/ *****************************************************************************/
...@@ -222,7 +239,7 @@ void csa_Decrypt( csa_t *c, uint8_t *pkt, int i_pkt_size ) ...@@ -222,7 +239,7 @@ void csa_Decrypt( csa_t *c, uint8_t *pkt, int i_pkt_size )
/***************************************************************************** /*****************************************************************************
* csa_Encrypt: * csa_Encrypt:
*****************************************************************************/ *****************************************************************************/
void csa_Encrypt( csa_t *c, uint8_t *pkt, int i_pkt_size, int b_odd ) void csa_Encrypt( csa_t *c, uint8_t *pkt, int i_pkt_size )
{ {
uint8_t *ck; uint8_t *ck;
uint8_t *kk; uint8_t *kk;
...@@ -234,13 +251,10 @@ void csa_Encrypt( csa_t *c, uint8_t *pkt, int i_pkt_size, int b_odd ) ...@@ -234,13 +251,10 @@ void csa_Encrypt( csa_t *c, uint8_t *pkt, int i_pkt_size, int b_odd )
/* set transport scrambling control */ /* set transport scrambling control */
pkt[3] |= 0x80; pkt[3] |= 0x80;
if( b_odd )
{
pkt[3] |= 0x40;
}
if( b_odd ) if( c->use_odd )
{ {
pkt[3] |= 0x40;
ck = c->o_ck; ck = c->o_ck;
kk = c->o_kk; kk = c->o_kk;
} }
......
...@@ -28,15 +28,17 @@ typedef struct csa_t csa_t; ...@@ -28,15 +28,17 @@ typedef struct csa_t csa_t;
#define csa_New __csa_New #define csa_New __csa_New
#define csa_Delete __csa_Delete #define csa_Delete __csa_Delete
#define csa_SetCW __csa_SetCW #define csa_SetCW __csa_SetCW
#define csa_UseKey __csa_UseKey
#define csa_Decrypt __csa_decrypt #define csa_Decrypt __csa_decrypt
#define csa_Encrypt __csa_encrypt #define csa_Encrypt __csa_encrypt
csa_t *csa_New( void ); csa_t *csa_New( void );
void csa_Delete( csa_t * ); void csa_Delete( csa_t * );
int csa_SetCW( vlc_object_t *p_caller, csa_t *c, char *psz_ck, int set_odd ); int csa_SetCW( vlc_object_t *p_caller, csa_t *c, char *psz_ck, bool odd );
int csa_UseKey( vlc_object_t *p_caller, csa_t *, bool use_odd );
void csa_Decrypt( csa_t *, uint8_t *pkt, int i_pkt_size ); void csa_Decrypt( csa_t *, uint8_t *pkt, int i_pkt_size );
void csa_Encrypt( csa_t *, uint8_t *pkt, int i_pkt_size, int b_odd ); void csa_Encrypt( csa_t *, uint8_t *pkt, int i_pkt_size );
#endif /* _CSA_H */ #endif /* _CSA_H */
...@@ -79,6 +79,13 @@ ...@@ -79,6 +79,13 @@
* if they arrive a bit late * if they arrive a bit late
* (We cannot rely on the fact that the fifo should be full) * (We cannot rely on the fact that the fifo should be full)
*/ */
/*****************************************************************************
* Callback prototypes
*****************************************************************************/
static int ChangeKeyCallback ( vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void * );
static int ActiveKeyCallback ( vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void * );
/***************************************************************************** /*****************************************************************************
* Module descriptor * Module descriptor
*****************************************************************************/ *****************************************************************************/
...@@ -160,6 +167,14 @@ static void Close ( vlc_object_t * ); ...@@ -160,6 +167,14 @@ static void Close ( vlc_object_t * );
#define CK_LONGTEXT N_("CSA encryption key. This must be a " \ #define CK_LONGTEXT N_("CSA encryption key. This must be a " \
"16 char string (8 hexadecimal bytes).") "16 char string (8 hexadecimal bytes).")
#define CK2_TEXT N_("Second CSA Key")
#define CK2_LONGTEXT N_("The even CSA encryption key. This must be a " \
"16 char string (8 hexadecimal bytes).")
#define CU_TEXT N_("CSA Key in use")
#define CU_LONGTEXT N_("CSA encryption key used. It can be the odd/first/1 " \
"(default) or the even/second/2 one.")
#define CPKT_TEXT N_("Packet size in bytes to encrypt") #define CPKT_TEXT N_("Packet size in bytes to encrypt")
#define CPKT_LONGTEXT N_("Size of the TS packet to encrypt. " \ #define CPKT_LONGTEXT N_("Size of the TS packet to encrypt. " \
"The encryption routines subtract the TS-header from the value before " \ "The encryption routines subtract the TS-header from the value before " \
...@@ -227,6 +242,10 @@ vlc_module_begin(); ...@@ -227,6 +242,10 @@ vlc_module_begin();
add_string( SOUT_CFG_PREFIX "csa-ck", NULL, NULL, CK_TEXT, CK_LONGTEXT, add_string( SOUT_CFG_PREFIX "csa-ck", NULL, NULL, CK_TEXT, CK_LONGTEXT,
true ); true );
add_string( SOUT_CFG_PREFIX "csa2-ck", NULL, NULL, CK2_TEXT, CK2_LONGTEXT,
true );
add_string( SOUT_CFG_PREFIX "csa-use", "1", NULL, CU_TEXT, CU_LONGTEXT,
true );
add_integer( SOUT_CFG_PREFIX "csa-pkt", 188, NULL, CPKT_TEXT, CPKT_LONGTEXT, true ); add_integer( SOUT_CFG_PREFIX "csa-pkt", 188, NULL, CPKT_TEXT, CPKT_LONGTEXT, true );
set_callbacks( Open, Close ); set_callbacks( Open, Close );
...@@ -238,7 +257,7 @@ vlc_module_end(); ...@@ -238,7 +257,7 @@ vlc_module_end();
static const char *const ppsz_sout_options[] = { static const char *const ppsz_sout_options[] = {
"pid-video", "pid-audio", "pid-spu", "pid-pmt", "tsid", "netid", "pid-video", "pid-audio", "pid-spu", "pid-pmt", "tsid", "netid",
"es-id-pid", "shaping", "pcr", "bmin", "bmax", "use-key-frames", "es-id-pid", "shaping", "pcr", "bmin", "bmax", "use-key-frames",
"dts-delay", "csa-ck", "csa-pkt", "crypt-audio", "crypt-video", "dts-delay", "csa-ck", "csa2-ck", "csa-use", "csa-pkt", "crypt-audio", "crypt-video",
"muxpmt", "sdtdesc", "program-pmt", "alignment", "muxpmt", "sdtdesc", "program-pmt", "alignment",
NULL NULL
}; };
...@@ -356,6 +375,8 @@ struct sout_mux_sys_t ...@@ -356,6 +375,8 @@ struct sout_mux_sys_t
int i_pcr_pid; int i_pcr_pid;
sout_input_t *p_pcr_input; sout_input_t *p_pcr_input;
vlc_mutex_t csa_lock;
int i_audio_bound; int i_audio_bound;
int i_video_bound; int i_video_bound;
...@@ -493,6 +514,8 @@ static int Open( vlc_object_t *p_this ) ...@@ -493,6 +514,8 @@ static int Open( vlc_object_t *p_this )
p_sys->dvbpmt = NULL; p_sys->dvbpmt = NULL;
memset( &p_sys->pmtmap, 0, sizeof(p_sys->pmtmap) ); memset( &p_sys->pmtmap, 0, sizeof(p_sys->pmtmap) );
vlc_mutex_init( &p_sys->csa_lock );
p_mux->pf_control = Control; p_mux->pf_control = Control;
p_mux->pf_addstream = AddStream; p_mux->pf_addstream = AddStream;
p_mux->pf_delstream = DelStream; p_mux->pf_delstream = DelStream;
...@@ -768,22 +791,49 @@ static int Open( vlc_object_t *p_this ) ...@@ -768,22 +791,49 @@ static int Open( vlc_object_t *p_this )
p_sys->i_pcr = 0; p_sys->i_pcr = 0;
p_sys->csa = NULL; p_sys->csa = NULL;
var_Create( p_mux, SOUT_CFG_PREFIX "csa-ck", VLC_VAR_STRING | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );
var_Get( p_mux, SOUT_CFG_PREFIX "csa-ck", &val ); var_Get( p_mux, SOUT_CFG_PREFIX "csa-ck", &val );
if( val.psz_string && *val.psz_string ) if( val.psz_string && *val.psz_string )
{ {
int i_res; int i_res;
vlc_value_t csa2;
p_sys->csa = csa_New(); p_sys->csa = csa_New();
i_res = csa_SetCW( (vlc_object_t*)p_mux, p_sys->csa, val.psz_string, 1 ); var_Create( p_mux, SOUT_CFG_PREFIX "csa2-ck", VLC_VAR_STRING | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );
if( i_res != VLC_SUCCESS || csa_SetCW( (vlc_object_t*)p_mux, p_sys->csa, val.psz_string, 0 ) != VLC_SUCCESS ) var_Get( p_mux, SOUT_CFG_PREFIX "csa2-ck", &csa2 );
i_res = csa_SetCW( (vlc_object_t*)p_mux, p_sys->csa, val.psz_string, true );
if( i_res == VLC_SUCCESS && csa2.psz_string && *csa2.psz_string )
{
if( csa_SetCW( (vlc_object_t*)p_mux, p_sys->csa, csa2.psz_string, false ) != VLC_SUCCESS )
{
csa_SetCW( (vlc_object_t*)p_mux, p_sys->csa, val.psz_string, false );
}
}
else if( i_res == VLC_SUCCESS )
{
csa_SetCW( (vlc_object_t*)p_mux, p_sys->csa, val.psz_string, false );
}
else
{ {
csa_Delete( p_sys->csa ); csa_Delete( p_sys->csa );
} }
if( p_sys->csa ) if( p_sys->csa )
{ {
vlc_value_t pkt_val; vlc_value_t use_val, pkt_val;
var_Create( p_mux, SOUT_CFG_PREFIX "csa-use", VLC_VAR_STRING | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );
var_Get( p_mux, SOUT_CFG_PREFIX "csa-use", &use_val );
var_AddCallback( p_mux, SOUT_CFG_PREFIX "csa-use", ActiveKeyCallback, NULL );
var_AddCallback( p_mux, SOUT_CFG_PREFIX "csa-ck", ChangeKeyCallback, (void *)1 );
var_AddCallback( p_mux, SOUT_CFG_PREFIX "csa2-ck", ChangeKeyCallback, NULL );
if ( var_Set( p_mux, SOUT_CFG_PREFIX "csa-use", use_val ) != VLC_SUCCESS )
{
var_SetString( p_mux, SOUT_CFG_PREFIX "csa-use", "odd" );
}
free( use_val.psz_string );
var_Get( p_mux, SOUT_CFG_PREFIX "csa-pkt", &pkt_val ); var_Get( p_mux, SOUT_CFG_PREFIX "csa-pkt", &pkt_val );
if( pkt_val.i_int < 12 || pkt_val.i_int > 188 ) if( pkt_val.i_int < 12 || pkt_val.i_int > 188 )
...@@ -795,6 +845,7 @@ static int Open( vlc_object_t *p_this ) ...@@ -795,6 +845,7 @@ static int Open( vlc_object_t *p_this )
else p_sys->i_csa_pkt_size = pkt_val.i_int; else p_sys->i_csa_pkt_size = pkt_val.i_int;
msg_Dbg( p_mux, "encrypting %d bytes of packet", p_sys->i_csa_pkt_size ); msg_Dbg( p_mux, "encrypting %d bytes of packet", p_sys->i_csa_pkt_size );
} }
free( csa2.psz_string );
} }
free( val.psz_string ); free( val.psz_string );
...@@ -816,10 +867,17 @@ static void Close( vlc_object_t * p_this ) ...@@ -816,10 +867,17 @@ static void Close( vlc_object_t * p_this )
sout_mux_sys_t *p_sys = p_mux->p_sys; sout_mux_sys_t *p_sys = p_mux->p_sys;
int i; int i;
vlc_mutex_lock( &p_sys->csa_lock );
if( p_sys->csa ) if( p_sys->csa )
{ {
var_DelCallback( p_mux, SOUT_CFG_PREFIX "csa-ck", ChangeKeyCallback, NULL );
var_DelCallback( p_mux, SOUT_CFG_PREFIX "csa2-ck", ChangeKeyCallback, NULL );
var_DelCallback( p_mux, SOUT_CFG_PREFIX "csa-use", ActiveKeyCallback, NULL );
csa_Delete( p_sys->csa ); csa_Delete( p_sys->csa );
} }
vlc_mutex_unlock( &p_sys->csa_lock );
vlc_mutex_destroy( &p_sys->csa_lock );
for( i = 0; i < MAX_PMT; i++ ) for( i = 0; i < MAX_PMT; i++ )
{ {
free( p_sys->sdt_descriptors[i].psz_service_name ); free( p_sys->sdt_descriptors[i].psz_service_name );
...@@ -830,6 +888,58 @@ static void Close( vlc_object_t * p_this ) ...@@ -830,6 +888,58 @@ static void Close( vlc_object_t * p_this )
free( p_sys ); free( p_sys );
} }
/*****************************************************************************
* ChangeKeyCallback: called when changing the odd encryption key on the fly.
*****************************************************************************/
static int ChangeKeyCallback( vlc_object_t *p_this, char const *psz_cmd,
vlc_value_t oldval, vlc_value_t newval,
void *p_data )
{
VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval);
sout_mux_t *p_mux = (sout_mux_t*)p_this;
sout_mux_sys_t *p_sys = p_mux->p_sys;
int i_tmp = (int)p_data;
vlc_mutex_lock( &p_sys->csa_lock );
if ( i_tmp )
{
i_tmp = csa_SetCW( p_this, p_sys->csa, newval.psz_string, true );
}
else
{
i_tmp = csa_SetCW( p_this, p_sys->csa, newval.psz_string, false );
}
vlc_mutex_unlock( &p_sys->csa_lock );
return i_tmp;
}
/*****************************************************************************
* ActiveKeyCallback: called when changing the active (in use) encryption key on the fly.
*****************************************************************************/
static int ActiveKeyCallback( vlc_object_t *p_this, char const *psz_cmd,
vlc_value_t oldval, vlc_value_t newval,
void *p_data )
{
VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_data);
sout_mux_t *p_mux = (sout_mux_t*)p_this;
sout_mux_sys_t *p_sys = p_mux->p_sys;
int i_res = VLC_EBADVAR;
vlc_mutex_lock( &p_sys->csa_lock );
if( !strcmp(newval.psz_string, "odd" ) || !strcmp(newval.psz_string, "first" ) || !strcmp(newval.psz_string, "1" ) )
{
i_res = csa_UseKey( (vlc_object_t*)p_mux, p_sys->csa, 1 );
}
else if( !strcmp(newval.psz_string, "even" ) || !strcmp(newval.psz_string, "second" ) || !strcmp(newval.psz_string, "2" ) )
{
i_res = csa_UseKey( (vlc_object_t*)p_mux, p_sys->csa, 0 );
}
vlc_mutex_unlock( &p_sys->csa_lock );
return i_res;
}
/***************************************************************************** /*****************************************************************************
* Control: * Control:
*****************************************************************************/ *****************************************************************************/
...@@ -1869,7 +1979,9 @@ static void TSDate( sout_mux_t *p_mux, sout_buffer_chain_t *p_chain_ts, ...@@ -1869,7 +1979,9 @@ static void TSDate( sout_mux_t *p_mux, sout_buffer_chain_t *p_chain_ts,
} }
if( p_ts->i_flags & BLOCK_FLAG_SCRAMBLED ) if( p_ts->i_flags & BLOCK_FLAG_SCRAMBLED )
{ {
csa_Encrypt( p_sys->csa, p_ts->p_buffer, p_sys->i_csa_pkt_size, 0 ); vlc_mutex_lock( &p_sys->csa_lock );
csa_Encrypt( p_sys->csa, p_ts->p_buffer, p_sys->i_csa_pkt_size );
vlc_mutex_unlock( &p_sys->csa_lock );
} }
/* latency */ /* latency */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment