Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEAT] Compile libdvbcsa with icam support #249

Closed
1 task done
Chris230291 opened this issue Jan 30, 2024 · 5 comments
Closed
1 task done

[FEAT] Compile libdvbcsa with icam support #249

Chris230291 opened this issue Jan 30, 2024 · 5 comments

Comments

@Chris230291
Copy link
Contributor

Is this a new feature request?

  • I have searched the existing issues

Wanted change

TVHeadend can now detect icam support added to libdvbcsa tvheadend/tvheadend#1593
libdvbcsa is outdated and requires patching to support icam.
Here is a working example that I am using now, based on your image, but I think it would be better if it was built in.
What do you think?

FROM lscr.io/linuxserver/tvheadend:latest

COPY patches/ /tmp/patches/

RUN \
  echo "**** install build packages ****" && \
  apk add --no-cache \
    autoconf \
    automake \
    build-base \
    git \
    libtool

RUN \
  echo "**** compile libdvbcsa ****" && \
  git clone https://github.com/glenvt18/libdvbcsa.git /tmp/libdvbcsa && \
  cd /tmp/libdvbcsa && \
  git checkout 2a1e61e569a621c55c2426f235f42c2398b7f18f && \
  echo "**** patch libdvbcsa ****" && \
  git config apply.whitespace nowarn && git apply /tmp/patches/libdvbcsa.patch && sed 's# == 4)# > 0)#' -i src/dvbcsa_pv.h && \
  ./bootstrap && \
  ./configure \
    --enable-ssse3 \
    --with-pic \
    --prefix=/usr \
    --sysconfdir=/etc \
    --mandir=/usr/share/man \
    --infodir=/usr/share/info \
    --localstatedir=/var && \
  make -j 2 && \
  make check && \
  make DESTDIR=/tmp/libdvbcsa-build install && \
  echo "**** copy to /usr for tvheadend dependency ****" && \
  cp -pr /tmp/libdvbcsa-build/usr/* /usr/

  RUN \
  echo "**** remove build packages ****" && \
  apk del \
    autoconf \
    automake \
    build-base \
    git \
    libtool

And the patch

--- a/README
+++ b/README
@@ -135,6 +135,12 @@ Example:
     dvbcsa_bs_encrypt(key, b, 184);
 
 
+    DVBCSA_KEY_ECM
+
+    unsigned char ecm = (ecm_caid >> 8 == 0x09 && (ecm_data[2] - ecm_data[4]) == 4) ? ecm_data[21] : 0;
+    dvbcsa_bs_key_set_ecm(ecm, cw, key);
+
+
 Portability
 ===========
 
--- a/src/dvbcsa/dvbcsa.h
+++ b/src/dvbcsa/dvbcsa.h
@@ -93,6 +93,11 @@ void dvbcsa_bs_key_free(struct dvbcsa_bs_key_s *key);
 
 void dvbcsa_bs_key_set(const dvbcsa_cw_t cw, struct dvbcsa_bs_key_s *key);
 
+#ifndef DVBCSA_KEY_ECM
+#define DVBCSA_KEY_ECM 1
+#endif
+void dvbcsa_bs_key_set_ecm(const unsigned char ecm, const dvbcsa_cw_t cw, struct dvbcsa_bs_key_s *key);
+
 /** get maximum number of packet per batch */
 
 unsigned int dvbcsa_bs_batch_size(void);
--- a/src/dvbcsa_bs_key.c
+++ b/src/dvbcsa_bs_key.c
@@ -63,3 +63,40 @@ dvbcsa_bs_key_set (const dvbcsa_cw_t cw, struct dvbcsa_bs_key_s *key)
     }
 }
 
+void
+dvbcsa_bs_key_set_ecm (const unsigned char ecm, const dvbcsa_cw_t cw, struct dvbcsa_bs_key_s *key)
+{
+  dvbcsa_keys_t kk;
+  int i;
+
+  /* precalculations for stream */
+
+  uint64_t ck = dvbcsa_load_le64(cw);
+
+  for (i = 0; i < DVBCSA_CWBITS_SIZE; i++)
+    key->stream[i] = (ck >> (i^4)) & 1 ? BS_VAL8(ff) : BS_VAL8(00);
+
+  /* precalculations for block */
+
+  dvbcsa_key_schedule_block_ecm(ecm, cw, kk);
+
+  for (i = 0; i < DVBCSA_KEYSBUFF_SIZE; i++)
+    {
+#if BS_BATCH_SIZE == 32
+      *(dvbcsa_u32_aliasing_t *)(key->block + i) = kk[i] * 0x01010101;
+
+#elif BS_BATCH_SIZE == 64
+      *(dvbcsa_u64_aliasing_t *)(key->block + i) = kk[i] * 0x0101010101010101ULL;
+
+#elif BS_BATCH_SIZE > 64 && BS_BATCH_SIZE % 64 == 0
+      uint64_t v = kk[i] * 0x0101010101010101ULL;
+      int j;
+
+      for (j = 0; j < BS_BATCH_BYTES / 8; j++)
+        *((dvbcsa_u64_aliasing_t *)(key->block + i) + j) = v;
+#else
+# error
+#endif
+    }
+}
+
--- a/src/dvbcsa_key.c
+++ b/src/dvbcsa_key.c
@@ -585,3 +585,18 @@ dvbcsa_key_schedule_block(const dvbcsa_cw_t cw, uint8_t * kk)
       kk[i*8+j] = (k[i]>>(j*8)) ^ i;
 }
 
+void
+dvbcsa_key_schedule_block_ecm(const unsigned char ecm, const dvbcsa_cw_t cw, uint8_t * kk)
+{
+  uint64_t k[7];
+  int i, j;
+
+  k[6] = dvbcsa_load_le64_ecm(ecm, cw);
+  for (i = 6; i > 0; i--)
+    k[i - 1] = dvbcsa_key_permute_block(k[i]);
+
+  for (i = 0; i < 7; i++)
+    for (j = 0; j < 8; j++)
+      kk[i*8+j] = (k[i]>>(j*8)) ^ i;
+}
+
--- a/src/dvbcsa_pv.h
+++ b/src/dvbcsa_pv.h
@@ -87,6 +87,25 @@ struct dvbcsa_key_s
 };
 
 extern const uint8_t dvbcsa_block_sbox[256];
+static const uint8_t csa_block_perm_ecm[256] =
+{
+    0x00, 0x02, 0x80, 0x82, 0x20, 0x22, 0xa0, 0xa2, 0x04, 0x06, 0x84, 0x86, 0x24, 0x26, 0xa4, 0xa6,
+    0x40, 0x42, 0xc0, 0xc2, 0x60, 0x62, 0xe0, 0xe2, 0x44, 0x46, 0xc4, 0xc6, 0x64, 0x66, 0xe4, 0xe6,
+    0x01, 0x03, 0x81, 0x83, 0x21, 0x23, 0xa1, 0xa3, 0x05, 0x07, 0x85, 0x87, 0x25, 0x27, 0xa5, 0xa7,
+    0x41, 0x43, 0xc1, 0xc3, 0x61, 0x63, 0xe1, 0xe3, 0x45, 0x47, 0xc5, 0xc7, 0x65, 0x67, 0xe5, 0xe7,
+    0x08, 0x0a, 0x88, 0x8a, 0x28, 0x2a, 0xa8, 0xaa, 0x0c, 0x0e, 0x8c, 0x8e, 0x2c, 0x2e, 0xac, 0xae,
+    0x48, 0x4a, 0xc8, 0xca, 0x68, 0x6a, 0xe8, 0xea, 0x4c, 0x4e, 0xcc, 0xce, 0x6c, 0x6e, 0xec, 0xee,
+    0x09, 0x0b, 0x89, 0x8b, 0x29, 0x2b, 0xa9, 0xab, 0x0d, 0x0f, 0x8d, 0x8f, 0x2d, 0x2f, 0xad, 0xaf,
+    0x49, 0x4b, 0xc9, 0xcb, 0x69, 0x6b, 0xe9, 0xeb, 0x4d, 0x4f, 0xcd, 0xcf, 0x6d, 0x6f, 0xed, 0xef,
+    0x10, 0x12, 0x90, 0x92, 0x30, 0x32, 0xb0, 0xb2, 0x14, 0x16, 0x94, 0x96, 0x34, 0x36, 0xb4, 0xb6,
+    0x50, 0x52, 0xd0, 0xd2, 0x70, 0x72, 0xf0, 0xf2, 0x54, 0x56, 0xd4, 0xd6, 0x74, 0x76, 0xf4, 0xf6,
+    0x11, 0x13, 0x91, 0x93, 0x31, 0x33, 0xb1, 0xb3, 0x15, 0x17, 0x95, 0x97, 0x35, 0x37, 0xb5, 0xb7,
+    0x51, 0x53, 0xd1, 0xd3, 0x71, 0x73, 0xf1, 0xf3, 0x55, 0x57, 0xd5, 0xd7, 0x75, 0x77, 0xf5, 0xf7,
+    0x18, 0x1a, 0x98, 0x9a, 0x38, 0x3a, 0xb8, 0xba, 0x1c, 0x1e, 0x9c, 0x9e, 0x3c, 0x3e, 0xbc, 0xbe,
+    0x58, 0x5a, 0xd8, 0xda, 0x78, 0x7a, 0xf8, 0xfa, 0x5c, 0x5e, 0xdc, 0xde, 0x7c, 0x7e, 0xfc, 0xfe,
+    0x19, 0x1b, 0x99, 0x9b, 0x39, 0x3b, 0xb9, 0xbb, 0x1d, 0x1f, 0x9d, 0x9f, 0x3d, 0x3f, 0xbd, 0xbf,
+    0x59, 0x5b, 0xd9, 0xdb, 0x79, 0x7b, 0xf9, 0xfb, 0x5d, 0x5f, 0xdd, 0xdf, 0x7d, 0x7f, 0xfd, 0xff
+};
 
 void dvbcsa_block_decrypt (const dvbcsa_keys_t key, const dvbcsa_block_t in, dvbcsa_block_t out);
 void dvbcsa_block_encrypt (const dvbcsa_keys_t key, const dvbcsa_block_t in, dvbcsa_block_t out);
@@ -95,6 +114,7 @@ void dvbcsa_stream_xor (const dvbcsa_cw_t cw, const dvbcsa_block_t iv,
                         uint8_t *stream, unsigned int len);
 
 void dvbcsa_key_schedule_block(const dvbcsa_cw_t cw, uint8_t * kk);
+void dvbcsa_key_schedule_block_ecm(const unsigned char ecm, const dvbcsa_cw_t cw, uint8_t * kk);
 
 DVBCSA_INLINE static inline void
 dvbcsa_xor_64 (uint8_t *b, const uint8_t *a)
@@ -141,6 +161,33 @@ dvbcsa_load_le64(const uint8_t *p)
 #endif
 }
 
+DVBCSA_INLINE static inline uint64_t
+dvbcsa_load_le64_ecm(const unsigned char ecm, const uint8_t *p)
+{
+  dvbcsa_block_t W;
+  memcpy(W, p, sizeof(W));
+  if (ecm == 4)
+    {
+      W[0] = csa_block_perm_ecm[p[0]];
+      W[4] = csa_block_perm_ecm[p[4]];
+    }
+#if defined(DVBCSA_ENDIAN_LITTLE)
+  uint64_t i;
+  memcpy(&i, W, 8);
+  return i;
+#else
+  return (uint64_t)( ((uint64_t)W[7] << 56) |
+                     ((uint64_t)W[6] << 48) |
+                     ((uint64_t)W[5] << 40) |
+                     ((uint64_t)W[4] << 32) |
+                     ((uint64_t)W[3] << 24) |
+                     ((uint64_t)W[2] << 16) |
+                     ((uint64_t)W[1] << 8 ) |
+                      (uint64_t)W[0]
+                     );
+#endif
+}
+
 DVBCSA_INLINE static inline void
 dvbcsa_store_le64(uint8_t *p, const uint64_t w)
 {

I can only test what I have, and that's amd64.
I believe ARM could be made to work like this.

  ./configure \
    --enable-neon \
    --with-pic \
    --prefix=/usr \
    --sysconfdir=/etc \
    --mandir=/usr/share/man \
    --infodir=/usr/share/info \
    --localstatedir=/var && \

Reason for change

Support newer DVB standards

Proposed code change

No response

@TonKro
Copy link

TonKro commented Feb 24, 2024

Is there a certain setting extra needed? While working with Chris tvheadend docker ICAM support is working. While using this docker it is not working.

NCAM returns found (163 ms) by ForeverCam1 - Sky Sport F1 HD ant the service is not clear

Sometimes it gives:

2024/02/24 15:46:47 7E8978E2 c (dvbapi) Demuxer 0 trying to descramble PID 0 CAID 098D PROVID 000000 ECMPID 1CBA ANY CHID PMTPID 0066 VPID 06FF
2024/02/24 15:47:01 7E8978E2 c (dvbapi) Demuxer 0 stopped descrambling for program 0011 (Sky Sport F1 HD)
2024/02/24 15:47:05 7E8978E2 c (dvbapi) Demuxer 0 ecmpid 0 CAID: 098D ECM_PID: 1CBA PROVID: 000000
2024/02/24 15:47:05 7E8978E2 c (dvbapi) Demuxer 0 ecmpid 1 CAID: 09F0 ECM_PID: 1FBA PROVID: 000000
2024/02/24 15:47:05 7E8978E2 c (dvbapi) Demuxer 0 ecmpid 2 CAID: 098C ECM_PID: 1ABA PROVID: 000000
2024/02/24 15:47:05 7E8978E2 c (dvbapi) Demuxer 0 ecmpid 3 CAID: 09C4 ECM_PID: 1BBA PROVID: 000000

With Chris's docker NCAM adds ICAM and the service is clear.

What am I doing wrong?

@Chris230291
Copy link
Contributor Author

iCAM doesn't work with the @linuxserver image.
I opened this issue to see if they would build in the patched libdvbcsa, but no one has replied yet.
Until then, you can just use my image… But I don't keep it up to date like these guys do, and It doesn't support multiple architectures.

@TonKro
Copy link

TonKro commented Mar 6, 2024

Do you have a description how to build tvheadend myself with icam support?

@LinuxServer-CI
Copy link
Collaborator

This issue has been automatically marked as stale because it has not had recent activity. This might be due to missing feedback from OP. It will be closed if no further activity occurs. Thank you for your contributions.

@LinuxServer-CI LinuxServer-CI closed this as not planned Won't fix, can't repro, duplicate, stale Jun 5, 2024
@LinuxServer-CI LinuxServer-CI moved this from Issues to Done in Issue & PR Tracker Jun 5, 2024
Copy link

github-actions bot commented Jul 5, 2024

This issue is locked due to inactivity

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jul 5, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
Archived in project
Development

No branches or pull requests

3 participants