]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
descrambler: add libdesdec
authorJaroslav Kysela <perex@perex.cz>
Wed, 24 May 2017 13:32:33 +0000 (15:32 +0200)
committerJaroslav Kysela <perex@perex.cz>
Wed, 24 May 2017 13:45:24 +0000 (15:45 +0200)
Makefile
src/descrambler/algo/libaesdec.c
src/descrambler/algo/libaesdec.h
src/descrambler/algo/libdesdec.c [new file with mode: 0644]
src/descrambler/algo/libdesdec.h [new file with mode: 0644]
src/descrambler/tvhcsa.c
src/descrambler/tvhcsa.h

index cbeb707726b2d5f8c90b4084206fa630e68e173f..97f45513a360991d525e2e3069e50fe6dd99c90a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -544,8 +544,9 @@ ${BUILDDIR}/src/descrambler/ffdecsa/ffdecsa_mmx.o  : CFLAGS += -mmmx
 ${BUILDDIR}/src/descrambler/ffdecsa/ffdecsa_sse2.o : CFLAGS += -msse2
 endif
 
-# libaesdec
+# crypto algorithms
 SRCS-${CONFIG_SSL} += src/descrambler/algo/libaesdec.c
+SRCS-${CONFIG_SSL} += src/descrambler/algo/libdesdec.c
 
 # DBUS
 SRCS-${CONFIG_DBUS_1}  += src/dbus.c
index 3a41a827c583764c8cf39101948b8f95b59ffe6e..cab1d5f51e4be8919a92e453685865df0c9a308a 100644 (file)
@@ -41,7 +41,7 @@ void aes_set_control_words(void *keys,
 }
 
 /* allocate key structure */
-void * aes_get_key_struct(void)
+void * aes_get_priv_struct(void)
 {
   aes_priv_t *keys;
 
@@ -54,13 +54,13 @@ void * aes_get_key_struct(void)
 }
 
 /* free key structure */
-void aes_free_key_struct(void *keys)
+void aes_free_priv_struct(void *keys)
 {
   free(keys);
 }
 
 /* decrypt */
-void aes_decrypt_packet(void *keys, uint8_t *pkt)
+void aes_decrypt_packet(void *keys, const uint8_t *pkt)
 {
   uint8_t ev_od = 0;
   uint_fast8_t xc0, offset, n;
@@ -78,7 +78,7 @@ void aes_decrypt_packet(void *keys, uint8_t *pkt)
 
   if (xc0 == 0x80 || xc0 == 0xc0) { // encrypted
     ev_od = (xc0 & 0x40) >> 6; // 0 even, 1 odd
-    pkt[3] &= 0x3f;  // consider it decrypted now
+    ((uint8_t *)pkt)[3] &= 0x3f;  // consider it decrypted now
     if (pkt[3] & 0x20) { // incomplete packet
       offset = 4 + pkt[4] + 1;
       n = (188 - offset) >> 4;
@@ -94,6 +94,6 @@ void aes_decrypt_packet(void *keys, uint8_t *pkt)
 
   k = &((aes_priv_t *) keys)->keys[ev_od];
   for (; offset <= (188 - 16); offset += 16) {
-    AES_ecb_encrypt(pkt + offset, pkt + offset, k, AES_DECRYPT);
+    AES_ecb_encrypt(pkt + offset, (uint8_t *)(pkt + offset), k, AES_DECRYPT);
   }
 }
index 1577ed29897d916b7a0356a94d28efed81be407f..a3198f3275624ea7ebe084e7159219866f318d31 100644 (file)
 
 #if ENABLE_SSL
 
-void *aes_get_key_struct(void);
-void aes_free_key_struct(void *keys);
+void *aes_get_priv_struct(void);
+void aes_free_priv_struct(void *keys);
 void aes_set_control_words(void *keys, const uint8_t *even, const uint8_t *odd);
 void aes_set_even_control_word(void *keys, const uint8_t *even);
 void aes_set_odd_control_word(void *keys, const uint8_t *odd);
-void aes_decrypt_packet(void *keys, uint8_t *pkt);
+void aes_decrypt_packet(void *keys, const uint8_t *pkt);
 
 #else
 
 // empty functions
-static inline void *aes_get_key_struct(void)  { return 0; };
-static inline void aes_free_key_struct(void *keys) { return; };
+static inline void *aes_get_priv_struct(void)  { return NULL; };
+static inline void aes_free_priv_struct(void *keys) { return; };
 static inline void aes_set_control_words(void *keys, const uint8_t *even, const uint8_t *odd) { return; };
 static inline void aes_set_even_control_word(void *keys, const uint8_t *even) { return; };
 static inline void aes_set_odd_control_word(void *keys, const uint8_t *odd) { return; };
-static inline void aes_decrypt_packet(void *keys, uint8_t *pkt) { return; };
+static inline void aes_decrypt_packet(void *keys, const uint8_t *pkt) { return; };
 
 #endif
 
diff --git a/src/descrambler/algo/libdesdec.c b/src/descrambler/algo/libdesdec.c
new file mode 100644 (file)
index 0000000..8e6e00f
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * libaesdec.c
+ */
+
+#include <sys/types.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "openssl/des.h"
+
+#include "libdesdec.h"
+
+/* key structure */
+typedef struct des_priv {
+  DES_key_schedule sched[2]; /* 0 = even, 1 = odd */
+} des_priv_t;
+
+/* even cw represents one 64-bit DES key */
+void des_set_even_control_word(void *priv, const uint8_t *pk)
+{
+  DES_set_key_unchecked((const_DES_cblock *)pk, &((des_priv_t *)priv)->sched[0]);
+}
+
+/* odd cw represents one 64-bit DES key */
+void des_set_odd_control_word(void *priv, const uint8_t *pk)
+{
+  DES_set_key_unchecked((const_DES_cblock *)pk, &((des_priv_t *)priv)->sched[1]);
+}
+
+/* set control words */
+void des_set_control_words(void *priv,
+                           const uint8_t *ev,
+                           const uint8_t *od)
+{
+  DES_set_key_unchecked((const_DES_cblock *)ev, &((des_priv_t *)priv)->sched[0]);
+  DES_set_key_unchecked((const_DES_cblock *)od, &((des_priv_t *)priv)->sched[1]);
+}
+
+/* allocate key structure */
+void * des_get_priv_struct(void)
+{
+  des_priv_t *priv;
+
+  priv = (des_priv_t *) malloc(sizeof(des_priv_t));
+  if (priv) {
+    static const uint8_t pk[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+    des_set_control_words(priv, pk, pk);
+  }
+  return priv;
+}
+
+/* free key structure */
+void des_free_priv_struct(void *priv)
+{
+  free(priv);
+}
+
+/* decrypt */
+void des_decrypt_packet(void *priv, const uint8_t *pkt)
+{
+  uint8_t ev_od = 0;
+  uint_fast8_t xc0, offset, offset2, n;
+  DES_key_schedule *sched;
+  uint8_t buf[188];
+
+  xc0 = pkt[3] & 0xc0;
+
+  //skip clear pkt
+  if (xc0 == 0x00)
+    return;
+
+  //skip reserved pkt
+  if (xc0 == 0x40)
+    return;
+
+  if (xc0 == 0x80 || xc0 == 0xc0) { // encrypted
+    ev_od = (xc0 & 0x40) >> 6; // 0 even, 1 odd
+    ((uint8_t *)pkt)[3] &= 0x3f;  // consider it decrypted now
+    if (pkt[3] & 0x20) { // incomplete packet
+      offset = 4 + pkt[4] + 1;
+      n = (188 - offset) >> 4;
+      if (n == 0) { // decrypted==encrypted!
+        return;  // this doesn't need more processing
+      }
+    } else {
+      offset = 4;
+    }
+  } else {
+    return;
+  }
+
+  sched = &((des_priv_t *)priv)->sched[ev_od];
+  if (offset & 3) {
+    /* data must be aligned for DES_encrypt2() */
+    offset2 = (offset + 3) & ~3;
+    memcpy(buf + offset2, pkt + offset, 188 - offset2);
+    for (; offset2 <= (188 - 8); offset2 += 8) {
+      DES_encrypt2((DES_LONG *)(buf + offset2), sched, 0);
+    }
+    memcpy((uint8_t *)(pkt + offset), buf + offset2, 188 - offset2);
+  } else {
+    for (; offset <= (188 - 8); offset += 8) {
+      DES_encrypt2((DES_LONG *)(pkt + offset), sched, 0);
+    }
+  }
+}
diff --git a/src/descrambler/algo/libdesdec.h b/src/descrambler/algo/libdesdec.h
new file mode 100644 (file)
index 0000000..80bdbd1
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * libdesdec.h
+ */
+
+#ifndef LIBDESDEC_H_
+#define LIBDESDEC_H_
+
+#include <stdint.h>
+#include "build.h"
+
+#if ENABLE_SSL
+
+void *des_get_priv_struct(void);
+void des_free_priv_struct(void *priv);
+void des_set_control_words(void *priv, const uint8_t *even, const uint8_t *odd);
+void des_set_even_control_word(void *priv, const uint8_t *even);
+void des_set_odd_control_word(void *priv, const uint8_t *odd);
+void des_decrypt_packet(void *priv, const uint8_t *pkt);
+
+#else
+
+// empty functions
+static inline void *des_get_priv_struct(void)  { return NULL; };
+static inline void des_free_priv_struct(void *priv) { return; };
+static inline void des_set_control_words(void *priv, const uint8_t *even, const uint8_t *odd) { return; };
+static inline void des_set_even_control_word(void *priv, const uint8_t *even) { return; };
+static inline void des_set_odd_control_word(void *priv, const uint8_t *odd) { return; };
+static inline void des_decrypt_packet(void *priv, const uint8_t *pkt) { return; };
+
+#endif
+
+#endif /* LIBDESDEC_H_ */
index 137823be487839d4af8a15497df4b5fcec8b5ec6..eccc1d4f451a1d43ff32fbfba132fc3188cb872f 100644 (file)
 #include <assert.h>
 
 static void
-tvhcsa_aes_flush
+tvhcsa_aes_ecb_flush
   ( tvhcsa_t *csa, struct mpegts_service *s )
 {
   /* empty - no queue */
 }
 
 static void
-tvhcsa_aes_descramble
+tvhcsa_aes_ecb_descramble
   ( tvhcsa_t *csa, struct mpegts_service *s, const uint8_t *tsb, int len )
 {
   const uint8_t *tsb2, *end2;
 
   for (tsb2 = tsb, end2 = tsb + len; tsb2 < end2; tsb2 += 188)
-    aes_decrypt_packet(csa->csa_aes_keys, (unsigned char *)tsb2);
+    aes_decrypt_packet(csa->csa_aes_priv, tsb2);
+  ts_recv_packet2(s, tsb, len);
+}
+
+static void
+tvhcsa_des_ncb_flush
+  ( tvhcsa_t *csa, struct mpegts_service *s )
+{
+  /* empty - no queue */
+}
+
+static void
+tvhcsa_des_ncb_descramble
+  ( tvhcsa_t *csa, struct mpegts_service *s, const uint8_t *tsb, int len )
+{
+  const uint8_t *tsb2, *end2;
+
+  for (tsb2 = tsb, end2 = tsb + len; tsb2 < end2; tsb2 += 188)
+    des_decrypt_packet(csa->csa_des_priv, tsb2);
   ts_recv_packet2(s, tsb, len);
 }
 
@@ -181,9 +199,14 @@ tvhcsa_set_type( tvhcsa_t *csa, int type )
     csa->csa_flush      = tvhcsa_csa_cbc_flush;
     csa->csa_keylen     = 8;
     break;
+  case DESCRAMBLER_DES_NCB:
+    csa->csa_descramble = tvhcsa_des_ncb_descramble;
+    csa->csa_flush      = tvhcsa_des_ncb_flush;
+    csa->csa_keylen     = 8;
+    break;
   case DESCRAMBLER_AES_ECB:
-    csa->csa_descramble = tvhcsa_aes_descramble;
-    csa->csa_flush      = tvhcsa_aes_flush;
+    csa->csa_descramble = tvhcsa_aes_ecb_descramble;
+    csa->csa_flush      = tvhcsa_aes_ecb_flush;
     csa->csa_keylen     = 16;
     break;
   default:
@@ -204,8 +227,11 @@ void tvhcsa_set_key_even( tvhcsa_t *csa, const uint8_t *even )
     set_even_control_word((csa)->csa_keys, even);
 #endif
     break;
+  case DESCRAMBLER_DES_NCB:
+    des_set_even_control_word(csa->csa_des_priv, even);
+    break;
   case DESCRAMBLER_AES_ECB:
-    aes_set_even_control_word(csa->csa_aes_keys, even);
+    aes_set_even_control_word(csa->csa_aes_priv, even);
     break;
   default:
     assert(0);
@@ -223,8 +249,11 @@ void tvhcsa_set_key_odd( tvhcsa_t *csa, const uint8_t *odd )
     set_odd_control_word((csa)->csa_keys, odd);
 #endif
     break;
+  case DESCRAMBLER_DES_NCB:
+    des_set_odd_control_word(csa->csa_des_priv, odd);
+    break;
   case DESCRAMBLER_AES_ECB:
-    aes_set_odd_control_word(csa->csa_aes_keys, odd);
+    aes_set_odd_control_word(csa->csa_aes_priv, odd);
     break;
   default:
     assert(0);
@@ -255,7 +284,8 @@ tvhcsa_init ( tvhcsa_t *csa )
 #else
   csa->csa_keys          = get_key_struct();
 #endif
-  csa->csa_aes_keys      = aes_get_key_struct();
+  csa->csa_aes_priv      = aes_get_priv_struct();
+  csa->csa_des_priv      = des_get_priv_struct();
 }
 
 void
@@ -269,6 +299,7 @@ tvhcsa_destroy ( tvhcsa_t *csa )
 #else
   free_key_struct(csa->csa_keys);
 #endif
-  aes_free_key_struct(csa->csa_aes_keys);
+  aes_free_priv_struct(csa->csa_aes_priv);
+  des_free_priv_struct(csa->csa_des_priv);
   free(csa->csa_tsbcluster);
 }
index 06d1e167eda71965dd9ebdf1aa05062d1a79e805..ef727b090ce39dfd2fa1cb37d9dfd44e2bb676c1 100644 (file)
@@ -31,6 +31,7 @@ struct elementary_stream;
 #endif
 
 #include "algo/libaesdec.h"
+#include "algo/libdesdec.h"
 
 typedef struct tvhcsa
 {
@@ -61,7 +62,8 @@ typedef struct tvhcsa
 #else
   void *csa_keys;
 #endif
-  void *csa_aes_keys;
+  void *csa_aes_priv;
+  void *csa_des_priv;
   
 } tvhcsa_t;