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;
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)
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;
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)
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;
}
if (dr == NULL)
return -1;
+
count = failed = 0;
LIST_FOREACH(td, &t->s_descramblers, td_service_link) {
count++;
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) {
#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 )
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 )
int len;
int offset;
int n;
- int i;
- const uint8_t *t0;
pkt = csa->csa_tsbcluster + csa->csa_fill * 188;
memcpy(pkt, tsb, 188);
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++;
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
}
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:
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;