]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
descrambler: implement proper TS queue flush before key change, fixes #2171
authorJaroslav Kysela <perex@perex.cz>
Mon, 8 Dec 2014 19:20:39 +0000 (20:20 +0100)
committerJaroslav Kysela <perex@perex.cz>
Mon, 8 Dec 2014 19:20:39 +0000 (20:20 +0100)
src/descrambler.h
src/descrambler/descrambler.c
src/descrambler/tvhcsa.c
src/descrambler/tvhcsa.h

index 97af08114b570a8e8a6223e1be3dc23216fde96f..8ce3e98e12f77713c4f3185fc89cc40bfdecee02 100755 (executable)
@@ -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)
index a15aa64726b69433cbba08a3266c9faa63111d68..6c690ffd09e06331c7ad8be0f7819a4875da0c1e 100755 (executable)
@@ -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) {
index ee634c9e0f5257ae8c579450ecaa340dd0277e90..ac4e137332cfeb15df3f85b757d09592c12168b8 100644 (file)
 #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:
index 0025f04a3bc29647447c785225cb507ba404b9fd..e50ea3f7fcd1f0ef6c7b33cad430b303007eba99 100644 (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;