descrambler: implement proper TS queue flush before key change, fixes #2171

This commit is contained in:
Jaroslav Kysela 2014-12-08 20:20:39 +01:00
parent 3535d7d22e
commit 67938bc9d9
4 changed files with 108 additions and 66 deletions

View file

@ -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)

View file

@ -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) {

View file

@ -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:

View file

@ -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;