descrambler: implement proper TS queue flush before key change, fixes #2171
This commit is contained in:
parent
3535d7d22e
commit
67938bc9d9
4 changed files with 108 additions and 66 deletions
|
@ -66,6 +66,7 @@ typedef struct th_descrambler_runtime {
|
|||
uint32_t dr_key_first:1;
|
||||
uint8_t dr_key_index;
|
||||
uint8_t dr_key_valid;
|
||||
uint8_t dr_key_changed;
|
||||
time_t dr_key_start;
|
||||
time_t dr_key_timestamp[2];
|
||||
time_t dr_ecm_start;
|
||||
|
@ -73,6 +74,8 @@ typedef struct th_descrambler_runtime {
|
|||
time_t dr_last_err;
|
||||
sbuf_t dr_buf;
|
||||
tvhlog_limit_t dr_loglimit_key;
|
||||
uint8_t dr_key_even[16];
|
||||
uint8_t dr_key_odd[16];
|
||||
} th_descrambler_runtime_t;
|
||||
|
||||
typedef void (*descrambler_section_callback_t)
|
||||
|
|
|
@ -166,10 +166,11 @@ void
|
|||
descrambler_keys ( th_descrambler_t *td, int type,
|
||||
const uint8_t *even, const uint8_t *odd )
|
||||
{
|
||||
static uint8_t empty[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
service_t *t = td->td_service;
|
||||
th_descrambler_runtime_t *dr;
|
||||
th_descrambler_t *td2;
|
||||
int i, j = 0;
|
||||
int j = 0;
|
||||
|
||||
if (t == NULL || (dr = t->s_descramble) == NULL) {
|
||||
td->td_keystate = DS_FORBIDDEN;
|
||||
|
@ -195,22 +196,20 @@ descrambler_keys ( th_descrambler_t *td, int type,
|
|||
goto fin;
|
||||
}
|
||||
|
||||
for (i = 0; i < dr->dr_csa.csa_keylen; i++)
|
||||
if (even[i]) {
|
||||
j++;
|
||||
tvhcsa_set_key_even(&dr->dr_csa, even);
|
||||
dr->dr_key_valid |= 0x40;
|
||||
dr->dr_key_timestamp[0] = dispatch_clock;
|
||||
break;
|
||||
}
|
||||
for (i = 0; i < dr->dr_csa.csa_keylen; i++)
|
||||
if (odd[i]) {
|
||||
j++;
|
||||
tvhcsa_set_key_odd(&dr->dr_csa, odd);
|
||||
dr->dr_key_valid |= 0x80;
|
||||
dr->dr_key_timestamp[1] = dispatch_clock;
|
||||
break;
|
||||
}
|
||||
if (memcmp(empty, even, dr->dr_csa.csa_keylen)) {
|
||||
j++;
|
||||
memcpy(dr->dr_key_even, even, dr->dr_csa.csa_keylen);
|
||||
dr->dr_key_changed |= 1;
|
||||
dr->dr_key_valid |= 0x40;
|
||||
dr->dr_key_timestamp[0] = dispatch_clock;
|
||||
}
|
||||
if (memcmp(empty, odd, dr->dr_csa.csa_keylen)) {
|
||||
j++;
|
||||
memcpy(dr->dr_key_odd, odd, dr->dr_csa.csa_keylen);
|
||||
dr->dr_key_changed |= 2;
|
||||
dr->dr_key_valid |= 0x80;
|
||||
dr->dr_key_timestamp[1] = dispatch_clock;
|
||||
}
|
||||
|
||||
if (j) {
|
||||
if (td->td_keystate != DS_RESOLVED)
|
||||
|
@ -322,7 +321,7 @@ key_update( th_descrambler_runtime_t *dr, uint8_t key )
|
|||
if (dr->dr_key_start)
|
||||
dr->dr_key_start = dispatch_clock;
|
||||
else
|
||||
/* We don't knoe the exact start key switch time */
|
||||
/* We don't know the exact start key switch time */
|
||||
dr->dr_key_start = dispatch_clock - 60;
|
||||
}
|
||||
|
||||
|
@ -362,6 +361,7 @@ descrambler_descramble ( service_t *t,
|
|||
|
||||
if (dr == NULL)
|
||||
return -1;
|
||||
|
||||
count = failed = 0;
|
||||
LIST_FOREACH(td, &t->s_descramblers, td_service_link) {
|
||||
count++;
|
||||
|
@ -403,6 +403,16 @@ descrambler_descramble ( service_t *t,
|
|||
service_reset_streaming_status_flags(t, TSS_NO_ACCESS);
|
||||
sbuf_free(&dr->dr_buf);
|
||||
}
|
||||
|
||||
if (dr->dr_key_changed) {
|
||||
dr->dr_csa.csa_flush(&dr->dr_csa, (mpegts_service_t *)td->td_service);
|
||||
if (dr->dr_key_changed & 1)
|
||||
tvhcsa_set_key_even(&dr->dr_csa, dr->dr_key_even);
|
||||
if (dr->dr_key_changed & 2)
|
||||
tvhcsa_set_key_odd(&dr->dr_csa, dr->dr_key_odd);
|
||||
dr->dr_key_changed = 0;
|
||||
}
|
||||
|
||||
ki = tsb[3];
|
||||
if ((ki & 0x80) != 0x00) {
|
||||
if (key_valid(dr, ki) == 0) {
|
||||
|
|
|
@ -24,6 +24,13 @@
|
|||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
|
||||
static void
|
||||
tvhcsa_aes_flush
|
||||
( tvhcsa_t *csa, struct mpegts_service *s )
|
||||
{
|
||||
/* empty - no queue */
|
||||
}
|
||||
|
||||
static void
|
||||
tvhcsa_aes_descramble
|
||||
( tvhcsa_t *csa, struct mpegts_service *s, const uint8_t *tsb )
|
||||
|
@ -32,6 +39,70 @@ tvhcsa_aes_descramble
|
|||
ts_recv_packet2(s, tsb);
|
||||
}
|
||||
|
||||
static void
|
||||
tvhcsa_des_flush
|
||||
( tvhcsa_t *csa, struct mpegts_service *s )
|
||||
{
|
||||
#if ENABLE_DVBCSA
|
||||
|
||||
int i;
|
||||
const uint8_t *t0;
|
||||
|
||||
if(csa->csa_fill_even) {
|
||||
csa->csa_tsbbatch_even[csa->csa_fill_even].data = NULL;
|
||||
dvbcsa_bs_decrypt(csa->csa_key_even, csa->csa_tsbbatch_even, 184);
|
||||
csa->csa_fill_even = 0;
|
||||
}
|
||||
if(csa->csa_fill_odd) {
|
||||
csa->csa_tsbbatch_odd[csa->csa_fill_odd].data = NULL;
|
||||
dvbcsa_bs_decrypt(csa->csa_key_odd, csa->csa_tsbbatch_odd, 184);
|
||||
csa->csa_fill_odd = 0;
|
||||
}
|
||||
|
||||
t0 = csa->csa_tsbcluster;
|
||||
|
||||
for(i = 0; i < csa->csa_fill; i++) {
|
||||
ts_recv_packet2(s, t0);
|
||||
t0 += 188;
|
||||
}
|
||||
csa->csa_fill = 0;
|
||||
|
||||
#else
|
||||
|
||||
int r;
|
||||
unsigned char *vec[3];
|
||||
|
||||
while(1) {
|
||||
|
||||
vec[0] = csa->csa_tsbcluster;
|
||||
vec[1] = csa->csa_tsbcluster + csa->csa_fill * 188;
|
||||
vec[2] = NULL;
|
||||
|
||||
r = decrypt_packets(csa->csa_keys, vec);
|
||||
if(r > 0) {
|
||||
int i;
|
||||
const uint8_t *t0 = csa->csa_tsbcluster;
|
||||
|
||||
for(i = 0; i < r; i++) {
|
||||
ts_recv_packet2(s, t0);
|
||||
t0 += 188;
|
||||
}
|
||||
|
||||
r = csa->csa_fill - r;
|
||||
assert(r >= 0);
|
||||
|
||||
if(r > 0)
|
||||
memmove(csa->csa_tsbcluster, t0, r * 188);
|
||||
csa->csa_fill = r;
|
||||
} else {
|
||||
csa->csa_fill = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
tvhcsa_des_descramble
|
||||
( tvhcsa_t *csa, struct mpegts_service *s, const uint8_t *tsb )
|
||||
|
@ -43,8 +114,6 @@ tvhcsa_des_descramble
|
|||
int len;
|
||||
int offset;
|
||||
int n;
|
||||
int i;
|
||||
const uint8_t *t0;
|
||||
|
||||
pkt = csa->csa_tsbcluster + csa->csa_fill * 188;
|
||||
memcpy(pkt, tsb, 188);
|
||||
|
@ -90,28 +159,9 @@ tvhcsa_des_descramble
|
|||
if(csa->csa_fill != csa->csa_cluster_size)
|
||||
return;
|
||||
|
||||
if(csa->csa_fill_even) {
|
||||
csa->csa_tsbbatch_even[csa->csa_fill_even].data = NULL;
|
||||
dvbcsa_bs_decrypt(csa->csa_key_even, csa->csa_tsbbatch_even, 184);
|
||||
csa->csa_fill_even = 0;
|
||||
}
|
||||
if(csa->csa_fill_odd) {
|
||||
csa->csa_tsbbatch_odd[csa->csa_fill_odd].data = NULL;
|
||||
dvbcsa_bs_decrypt(csa->csa_key_odd, csa->csa_tsbbatch_odd, 184);
|
||||
csa->csa_fill_odd = 0;
|
||||
}
|
||||
|
||||
t0 = csa->csa_tsbcluster;
|
||||
|
||||
for(i = 0; i < csa->csa_fill; i++) {
|
||||
ts_recv_packet2(s, t0);
|
||||
t0 += 188;
|
||||
}
|
||||
csa->csa_fill = 0;
|
||||
tvhcsa_des_flush(csa, s);
|
||||
|
||||
#else
|
||||
int r;
|
||||
unsigned char *vec[3];
|
||||
|
||||
memcpy(csa->csa_tsbcluster + csa->csa_fill * 188, tsb, 188);
|
||||
csa->csa_fill++;
|
||||
|
@ -119,33 +169,8 @@ tvhcsa_des_descramble
|
|||
if(csa->csa_fill != csa->csa_cluster_size)
|
||||
return;
|
||||
|
||||
while(1) {
|
||||
tvhcsa_des_flush(csa, s);
|
||||
|
||||
vec[0] = csa->csa_tsbcluster;
|
||||
vec[1] = csa->csa_tsbcluster + csa->csa_fill * 188;
|
||||
vec[2] = NULL;
|
||||
|
||||
r = decrypt_packets(csa->csa_keys, vec);
|
||||
if(r > 0) {
|
||||
int i;
|
||||
const uint8_t *t0 = csa->csa_tsbcluster;
|
||||
|
||||
for(i = 0; i < r; i++) {
|
||||
ts_recv_packet2(s, t0);
|
||||
t0 += 188;
|
||||
}
|
||||
|
||||
r = csa->csa_fill - r;
|
||||
assert(r >= 0);
|
||||
|
||||
if(r > 0)
|
||||
memmove(csa->csa_tsbcluster, t0, r * 188);
|
||||
csa->csa_fill = r;
|
||||
} else {
|
||||
csa->csa_fill = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -159,10 +184,12 @@ tvhcsa_set_type( tvhcsa_t *csa, int type )
|
|||
switch (type) {
|
||||
case DESCRAMBLER_DES:
|
||||
csa->csa_descramble = tvhcsa_des_descramble;
|
||||
csa->csa_flush = tvhcsa_des_flush;
|
||||
csa->csa_keylen = 8;
|
||||
break;
|
||||
case DESCRAMBLER_AES:
|
||||
csa->csa_descramble = tvhcsa_aes_descramble;
|
||||
csa->csa_flush = tvhcsa_aes_flush;
|
||||
csa->csa_keylen = 16;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -42,6 +42,8 @@ typedef struct tvhcsa
|
|||
int csa_keylen;
|
||||
void (*csa_descramble)
|
||||
( struct tvhcsa *csa, struct mpegts_service *s, const uint8_t *tsb );
|
||||
void (*csa_flush)
|
||||
( struct tvhcsa *csa, struct mpegts_service *s );
|
||||
|
||||
int csa_cluster_size;
|
||||
uint8_t *csa_tsbcluster;
|
||||
|
|
Loading…
Add table
Reference in a new issue