From 88928a45cdd8a505f6c31637894baf98016cb513 Mon Sep 17 00:00:00 2001 From: Catalin Toda Date: Tue, 3 Jan 2023 16:49:54 -0800 Subject: [PATCH] Support icam ecm with a patched libdvbcsa #1003 --- src/ca.c | 11 ++++++----- src/csa.c | 13 ++++++++++++- src/dvbapi.c | 20 +++++++++++--------- src/dvbapi.h | 1 + src/pmt.c | 13 ++++++++----- src/pmt.h | 4 ++-- src/tables.c | 5 ++++- 7 files changed, 44 insertions(+), 23 deletions(-) diff --git a/src/ca.c b/src/ca.c index e9aa3ec080..6b7ee26a41 100644 --- a/src/ca.c +++ b/src/ca.c @@ -253,11 +253,11 @@ void send_cw_to_all_pmts(ca_device_t *d, int parity) { for (i = 0; i < d->max_ca_pmt; i++) { if (PMT_ID_IS_VALID(d->capmt[i].pmt_id)) { send_cw(d->capmt[i].pmt_id, CA_ALGO_AES128_CBC, parity, - d->key[parity], d->iv[parity], 3720); + d->key[parity], d->iv[parity], 3720, NULL); } if (PMT_ID_IS_VALID(d->capmt[i].other_id)) { send_cw(d->capmt[i].other_id, CA_ALGO_AES128_CBC, parity, - d->key[parity], d->iv[parity], 3720); + d->key[parity], d->iv[parity], 3720, NULL); } } } @@ -522,10 +522,11 @@ int dvbca_process_pmt(adapter *ad, SPMT *spmt) { LOG_AND_RETURN(TABLES_RESULT_ERROR_NORETRY, "send_capmt failed"); if (d->key[0][0]) - send_cw(spmt->id, CA_ALGO_AES128_CBC, 0, d->key[0], d->iv[0], - 3600); // 1 hour + send_cw(spmt->id, CA_ALGO_AES128_CBC, 0, d->key[0], d->iv[0], 3600, + NULL); // 1 hour if (d->key[1][0]) - send_cw(spmt->id, CA_ALGO_AES128_CBC, 1, d->key[1], d->iv[1], 3600); + send_cw(spmt->id, CA_ALGO_AES128_CBC, 1, d->key[1], d->iv[1], 3600, + NULL); return 0; } diff --git a/src/csa.c b/src/csa.c index d0d5f7c7bd..da75298aa3 100644 --- a/src/csa.c +++ b/src/csa.c @@ -47,12 +47,23 @@ #define DEFAULT_LOG LOG_DVBCA +void dvbcsa_bs_key_set_ecm(unsigned char ecm, const dvbcsa_cw_t cw, + struct dvbcsa_bs_key_s *key) __attribute__((weak)); void dvbcsa_create_key(SCW *cw) { cw->key = dvbcsa_bs_key_alloc(); } void dvbcsa_delete_key(SCW *cw) { dvbcsa_key_free(cw->key); } void dvbcsa_set_cw(SCW *cw, SPMT *pmt) { - dvbcsa_bs_key_set((unsigned char *)cw->cw, cw->key); + unsigned char ecm = *(unsigned char *)cw->opaque; + if (!dvbcsa_bs_key_set_ecm) { + dvbcsa_bs_key_set((unsigned char *)cw->cw, cw->key); + if (ecm) + LOGL(1, "minisatip required libdvbcsa with ICAM support. Please " + "see https://github.com/catalinii/minisatip/issues/1003 " + "for more details"); + } else { + dvbcsa_bs_key_set_ecm(ecm, (unsigned char *)cw->cw, cw->key); + } } void copy_batch(struct dvbcsa_bs_batch_s *d, SPMT_batch *s, int len) { diff --git a/src/dvbapi.c b/src/dvbapi.c index 7af19e677b..efbc354ea1 100644 --- a/src/dvbapi.c +++ b/src/dvbapi.c @@ -20,14 +20,14 @@ #include "dvbapi.h" #include "adapter.h" +#include "api/symbols.h" +#include "api/variables.h" #include "dvb.h" #include "minisatip.h" #include "pmt.h" #include "socketworks.h" #include "tables.h" #include "utils.h" -#include "api/symbols.h" -#include "api/variables.h" #include "utils/ticks.h" #include @@ -318,7 +318,7 @@ int dvbapi_reply(sockets *s) { k_id, parity, index, correct ? "OK" : "NOK", cw[0], cw[1], cw[2], cw[3], cw[4], cw[5], cw[6], cw[7]); - send_cw(k->pmt_id, k->algo, parity, cw, NULL, 0); + send_cw(k->pmt_id, k->algo, parity, cw, NULL, 0, &k->icam_ecm); mutex_unlock(&k->mutex); } else @@ -651,12 +651,14 @@ int send_ecm(int filter_id, unsigned char *b, int len, void *opaque) { len = ((b[1] & 0xF) << 8) + b[2]; len += 3; k->last_ecm = getTick(); - LOG("dvbapi: sending ECM key %d for pid %04X (%d), current ecm_parity = " - "%d, " - "previous parity %d, demux = %d, filter = %d, len = %d [%02X %02X %02X " + if (b[2] - b[4] == 4) + k->icam_ecm = b[0x15]; + LOG("dvbapi: sending ECM key %d for pid %04X (%d), ecm_parity = %d, " + "previous parity %d, demux = %d, filter = %d, icam_ecm %d, len = %d " + "[%02X %02X %02X " "%02X]", - k->id, pid, pid, k->ecm_parity[i], old_parity, demux, filter, len, b[0], - b[1], b[2], b[3]); + k->id, pid, pid, k->ecm_parity[i], old_parity, demux, filter, + k->icam_ecm, len, b[0], b[1], b[2], b[3]); if (demux < 0) return 0; @@ -677,7 +679,6 @@ int send_ecm(int filter_id, unsigned char *b, int len, void *opaque) { int set_algo(SKey *k, int algo, int mode) { if (algo == CA_ALGO_AES128 && mode == CA_MODE_CBC) algo = CA_ALGO_AES128_CBC; - k->algo = algo; return 0; @@ -724,6 +725,7 @@ int keys_add(int i, int adapter, int pmt_id) { k->last_dmx_stop = 0; k->onid = 0; k->tsid = 0; + k->icam_ecm = 0; memset(k->cw[0], 0, 16); memset(k->cw[1], 0, 16); memset(k->filter_id, -1, sizeof(k->filter_id)); diff --git a/src/dvbapi.h b/src/dvbapi.h index db4f9fa659..bb45eb65cd 100644 --- a/src/dvbapi.h +++ b/src/dvbapi.h @@ -77,6 +77,7 @@ typedef struct struct_key { demux[MAX_KEY_FILTERS], pid[MAX_KEY_FILTERS], ecm_parity[MAX_KEY_FILTERS]; int64_t last_parity_change; + unsigned char icam_ecm; } SKey; void init_dvbapi(); diff --git a/src/pmt.c b/src/pmt.c index e88e34e94f..cd3c7a7405 100644 --- a/src/pmt.c +++ b/src/pmt.c @@ -625,11 +625,13 @@ char *cw_to_string(SCW *cw, char *buf) { } int64_t ctime = getTick(); sprintf(buf, - "id %d, parity %d, pmt %d, time %jd ms ago, expiry in %jd ms, " + "id %d, parity %d, pmt %d,%s time %jd ms ago, expiry in " + "%jd ms, " "CW: %02X %02X %02X %02X %02X %02X %02X %02X", - cw->id, cw->parity, cw->pmt, ctime - cw->time, cw->expiry - ctime, - cw->cw[0], cw->cw[1], cw->cw[2], cw->cw[3], cw->cw[4], cw->cw[5], - cw->cw[6], cw->cw[7]); + cw->id, cw->parity, cw->pmt, + cw->opaque && *(uint8_t *)cw->opaque ? " ICAM," : "", + ctime - cw->time, cw->expiry - ctime, cw->cw[0], cw->cw[1], + cw->cw[2], cw->cw[3], cw->cw[4], cw->cw[5], cw->cw[6], cw->cw[7]); if (cw->iv[0]) sprintf(buf + strlen(buf), ", IV: %02X %02X %02X %02X %02X %02X %02X %02X", cw->iv[0], @@ -871,7 +873,7 @@ void update_cw(SPMT *pmt) { } int send_cw(int pmt_id, int algo, int parity, uint8_t *cw, uint8_t *iv, - int64_t expiry) { + int64_t expiry, void *opaque) { char buf[300]; int i, master_pmt; SCW_op *op = get_op_for_algo(algo); @@ -933,6 +935,7 @@ int send_cw(int pmt_id, int algo, int parity, uint8_t *cw, uint8_t *iv, c->cw_len = 16; c->time = getTick(); c->set_time = 0; + c->opaque = opaque; if (expiry == 0) c->expiry = c->time + MAX_CW_TIME; else diff --git a/src/pmt.h b/src/pmt.h index c84ca30818..a9e9ca05ba 100644 --- a/src/pmt.h +++ b/src/pmt.h @@ -93,7 +93,7 @@ typedef struct struct_cw { char cw_len; int16_t id; int64_t expiry, set_time; - + void *opaque; } SCW; typedef struct struct_stream_pid { @@ -176,7 +176,7 @@ typedef struct struct_filter { int register_algo(SCW_op *o); int send_cw(int pmt_id, int algo, int parity, uint8_t *cw, uint8_t *iv, - int64_t expiry); + int64_t expiry, void *opaque); extern int npmts; static inline SPMT *get_pmt(int id) { diff --git a/src/tables.c b/src/tables.c index d10e3056a1..25ab031080 100644 --- a/src/tables.c +++ b/src/tables.c @@ -20,7 +20,6 @@ #include "tables.h" #include "adapter.h" -#include "ca.h" #include "dvb.h" #include "dvbapi.h" #include "minisatip.h" @@ -47,6 +46,10 @@ #include "ddci.h" #endif +#ifndef DISABLE_DVBCA +#include "ca.h" +#endif + #define DEFAULT_LOG LOG_TABLES SCA ca[MAX_CA];