Add support for Irdeto EMM

Patch by: opdenkamp
This commit is contained in:
Andreas Öman 2010-03-21 10:47:17 +00:00
parent d57985481c
commit e472434d01
2 changed files with 121 additions and 16 deletions

2
debian/changelog vendored
View file

@ -41,6 +41,8 @@ hts-tvheadend (2.11-WIP) hts; urgency=low
there are errors. Also recordings that do not complete successfully
are correctly reported as failed entries. Ticket #131
* Add support for Irdeto EMM
hts-tvheadend (2.10) hts; urgency=high
* Fix a crash in HTSP server.

135
src/cwc.c
View file

@ -49,6 +49,15 @@
#define CWS_NETMSGSIZE 256
#define CWS_FIRSTCMDNO 0xe0
/**
* cards for which emm updates are handled
*/
typedef enum {
CARD_IRDETO,
CARD_CONAX,
CARD_UNKNOWN
} card_type_t;
typedef enum {
MSG_CLIENT_2_SERVER_LOGIN = CWS_FIRSTCMDNO,
MSG_CLIENT_2_SERVER_LOGIN_ACK,
@ -195,6 +204,9 @@ typedef struct cwc {
/* Emm forwarding */
int cwc_forward_emm;
/* Card type */
card_type_t cwc_card_type;
/* From configuration */
uint8_t cwc_confedkey[14];
@ -221,7 +233,9 @@ typedef struct cwc {
static void cwc_transport_destroy(th_descrambler_t *td);
extern char *cwc_krypt(const char *key, const char *salt);
static void cwc_detect_card_type(cwc_t *cwc);
void cwc_emm_conax(cwc_t *cwc, uint8_t *data, int len);
void cwc_emm_irdeto(cwc_t *cwc, uint8_t *data, int len);
/**
*
@ -516,6 +530,8 @@ cwc_decode_card_data_reply(cwc_t *cwc, uint8_t *msg, int len)
cwc->cwc_ua[0], cwc->cwc_ua[1], cwc->cwc_ua[2], cwc->cwc_ua[3], cwc->cwc_ua[4], cwc->cwc_ua[5], cwc->cwc_ua[6], cwc->cwc_ua[7],
nprov);
cwc_detect_card_type(cwc);
msg += 15;
plen -= 12;
@ -554,22 +570,54 @@ cwc_decode_card_data_reply(cwc_t *cwc, uint8_t *msg, int len)
cwc->cwc_ua[4] || cwc->cwc_ua[5] ||
cwc->cwc_ua[6] || cwc->cwc_ua[7]);
if (!emm_allowed)
tvhlog(LOG_INFO, "cwc", "%s: Will not forward EMMs (not allowed by server)",
if (!emm_allowed) {
tvhlog(LOG_INFO, "cwc",
"%s: Will not forward EMMs (not allowed by server)",
cwc->cwc_hostname);
else if ((cwc->cwc_caid>>8) != 0x0b)
tvhlog(LOG_INFO, "cwc", "%s: Will not forward EMMs (unsupported ca system)",
cwc->cwc_hostname);
else {
} else if (cwc->cwc_card_type != CARD_UNKNOWN) {
tvhlog(LOG_INFO, "cwc", "%s: Will forward EMMs",
cwc->cwc_hostname);
cwc->cwc_forward_emm = 1;
} else {
tvhlog(LOG_INFO, "cwc",
"%s: Will not forward EMMs (unsupported CA system)",
cwc->cwc_hostname);
}
}
return 0;
}
/**
* Detects the cam card type
* If you want to add another card, have a look at
* http://www.dvbservices.com/identifiers/ca_system_id?page=3
*
* based on the equivalent in sasc-ng
*/
static void
cwc_detect_card_type(cwc_t *cwc)
{
uint8_t c_sys = cwc->cwc_caid >> 8;
switch(c_sys) {
case 0x17:
case 0x06:
cwc->cwc_card_type = CARD_IRDETO;
tvhlog(LOG_INFO, "cwc", "%s: irdeto card",
cwc->cwc_hostname);
break;
case 0x0b:
cwc->cwc_card_type = CARD_CONAX;
tvhlog(LOG_INFO, "cwc", "%s: conax card",
cwc->cwc_hostname);
break;
default:
cwc->cwc_card_type = CARD_UNKNOWN;
tvhlog(LOG_INFO, "cwc", "%s: unknown card",
cwc->cwc_hostname);
}
}
/**
* Login command
@ -1036,16 +1084,71 @@ cwc_emm(uint8_t *data, int len)
lock_assert(&global_lock);
TAILQ_FOREACH(cwc, &cwcs, cwc_link)
if(cwc->cwc_forward_emm && cwc->cwc_writer_running &&
data[0] == 0x82 /* Conax */ ) {
int i;
for (i=0; i < cwc->cwc_num_providers; i++)
if (memcmp(&data[3], &cwc->cwc_providers[i].sa[1], 7) == 0) {
cwc_send_msg(cwc, data, len, 0, 1);
break;
}
TAILQ_FOREACH(cwc, &cwcs, cwc_link) {
if(cwc->cwc_forward_emm && cwc->cwc_writer_running) {
switch (cwc->cwc_card_type) {
case CARD_CONAX:
cwc_emm_conax(cwc, data, len);
break;
case CARD_IRDETO:
cwc_emm_irdeto(cwc, data, len);
break;
case CARD_UNKNOWN:
break;
}
}
}
}
/**
* conax emm handler
*/
void
cwc_emm_conax(cwc_t *cwc, uint8_t *data, int len)
{
if (data[0] == 0x82) {
int i;
for (i=0; i < cwc->cwc_num_providers; i++) {
if (memcmp(&data[3], &cwc->cwc_providers[i].sa[1], 7) == 0) {
cwc_send_msg(cwc, data, len, 0, 1);
break;
}
}
}
}
/**
* irdeto emm handler
* inspired by opensasc-ng, https://opensvn.csie.org/traccgi/opensascng/
*/
void
cwc_emm_irdeto(cwc_t *cwc, uint8_t *data, int len)
{
int emm_mode = data[3] >> 3;
int emm_len = data[3] & 0x07;
int match = 0;
if (emm_mode & 0x10){
// try to match card
match = (emm_mode == cwc->cwc_ua[4] &&
(!emm_len || // zero length
!memcmp(&data[4], &cwc->cwc_ua[5], emm_len))); // exact match
} else {
// try to match provider
int i;
for(i=0; i < cwc->cwc_num_providers; i++) {
match = (emm_mode == cwc->cwc_providers[i].sa[4] &&
(!emm_len || // zero length
!memcmp(&data[4], &cwc->cwc_providers[i].sa[5], emm_len)));
// exact match
if (match) break;
}
}
if (match)
cwc_send_msg(cwc, data, len, 0, 1);
}