struct mpegts_mux;
struct th_descrambler_data;
-#define DESCRAMBLER_NONE 0
-#define DESCRAMBLER_DES 1
-#define DESCRAMBLER_AES 2
+#define DESCRAMBLER_NONE 0
+#define DESCRAMBLER_CSA_CBC 1
+#define DESCRAMBLER_DES_NCB 2 /* no block cipher mode! */
+#define DESCRAMBLER_AES_ECB 3
/**
* Descrambler superclass
&caclient_capmt_class,
#endif
#if ENABLE_CONSTCW
- &caclient_ccw_des_class,
- &caclient_ccw_aes_class,
+ &caclient_ccw_csa_cbc_class,
+ &caclient_ccw_des_ncb_class,
+ &caclient_ccw_aes_ecb_class,
#endif
NULL
};
if ((s = htsmsg_get_str(conf, "class")) != NULL)
c = caclient_class_find(s);
if (c == NULL) {
- tvherror(LS_CACLIENT, "wrong class %s!", s);
- abort();
+ tvherror(LS_CACLIENT, "unknown class %s!", s);
+ return NULL;
}
#if ENABLE_CWC
if (c == &caclient_cwc_class)
cac = capmt_create();
#endif
#if ENABLE_CONSTCW
- if (c == &caclient_ccw_des_class)
- cac = constcw_create();
- if (c == &caclient_ccw_aes_class)
+ if (c == &caclient_ccw_csa_cbc_class ||
+ c == &caclient_ccw_des_ncb_class ||
+ c == &caclient_ccw_aes_ecb_class)
cac = constcw_create();
#endif
if (cac == NULL) {
extern const idclass_t caclient_cwc_class;
extern const idclass_t caclient_cccam_class;
extern const idclass_t caclient_capmt_class;
-extern const idclass_t caclient_ccw_des_class;
-extern const idclass_t caclient_ccw_aes_class;
+extern const idclass_t caclient_ccw_csa_cbc_class;
+extern const idclass_t caclient_ccw_des_ncb_class;
+extern const idclass_t caclient_ccw_aes_ecb_class;
TAILQ_HEAD(caclient_entry_queue, caclient);
if (adapter >= MAX_CA || index >= MAX_INDEX)
return;
if (parity == 0) {
- capmt_process_key(capmt, adapter, index, DESCRAMBLER_DES, cw, empty, 1);
+ capmt_process_key(capmt, adapter, index, DESCRAMBLER_CSA_CBC, cw, empty, 1);
} else if (parity == 1) {
- capmt_process_key(capmt, adapter, index, DESCRAMBLER_DES, empty, cw, 1);
+ capmt_process_key(capmt, adapter, index, DESCRAMBLER_CSA_CBC, empty, cw, 1);
} else
tvherror(LS_CAPMT, "%s: Invalid parity %d in CA_SET_DESCR for adapter%d", capmt_name(capmt), parity, adapter);
if (adapter >= MAX_CA || index >= MAX_INDEX)
return;
if (parity == 0) {
- capmt_process_key(capmt, adapter, index, DESCRAMBLER_AES, cw, empty, 1);
+ capmt_process_key(capmt, adapter, index, DESCRAMBLER_AES_ECB, cw, empty, 1);
} else if (parity == 1) {
- capmt_process_key(capmt, adapter, index, DESCRAMBLER_AES, empty, cw, 1);
+ capmt_process_key(capmt, adapter, index, DESCRAMBLER_AES_ECB, empty, cw, 1);
} else
tvherror(LS_CAPMT, "%s: Invalid parity %d in CA_SET_DESCR_AES for adapter%d", capmt_name(capmt), parity, adapter);
capmt_process_key(capmt, 0,
buffer[0] | ((uint16_t)buffer[1] << 8),
- DESCRAMBLER_DES,
+ DESCRAMBLER_CSA_CBC,
buffer + 2, buffer + 10,
ret == 18);
}
es3 = *es;
pthread_mutex_unlock(&cccam->cccam_mutex);
descrambler_keys((th_descrambler_t *)ct,
- off == 16 ? DESCRAMBLER_AES : DESCRAMBLER_DES,
+ off == 16 ? DESCRAMBLER_AES_ECB : DESCRAMBLER_CSA_CBC,
dcw, dcw + off);
snprintf(chaninfo, sizeof(chaninfo), "%s:%i", cccam->cccam_hostname, cccam->cccam_port);
descrambler_notify((th_descrambler_t *)ct,
return idnode_get_title(&ccw->cac_id, NULL);
}
+/**
+ *
+ */
+static int
+constcw_algo(caclient_t *cac)
+{
+ constcw_t *ccw = (constcw_t *)cac;
+
+ if (idnode_is_instance(&ccw->cac_id, &caclient_ccw_des_ncb_class))
+ return DESCRAMBLER_DES_NCB;
+ if (idnode_is_instance(&ccw->cac_id, &caclient_ccw_aes_ecb_class))
+ return DESCRAMBLER_AES_ECB;
+ return DESCRAMBLER_CSA_CBC;
+}
+
/**
*
*/
{
constcw_t *ccw = (constcw_t *)cac;
- if (idnode_is_instance(&ccw->cac_id, &caclient_ccw_des_class))
+ if (idnode_is_instance(&ccw->cac_id, &caclient_ccw_csa_cbc_class))
+ return 8;
+ if (idnode_is_instance(&ccw->cac_id, &caclient_ccw_des_ncb_class))
return 8;
return 16;
}
LIST_INSERT_HEAD(&ccw->ccw_services, ct, cs_link);
- descrambler_keys(td, constcw_key_size(cac) == 8 ?
- DESCRAMBLER_DES : DESCRAMBLER_AES,
+ descrambler_keys(td, constcw_algo(cac),
ccw->ccw_key_even, ccw->ccw_key_odd);
}
return constcw_class_key_get(o, ccw->ccw_key_odd);
}
-const idclass_t caclient_ccw_des_class =
+const idclass_t caclient_ccw_csa_cbc_class =
+{
+ .ic_super = &caclient_class,
+ .ic_class = "caclient_ccw_csa_cbc",
+ .ic_caption = N_("CSA CBC Constant Code Word"),
+ .ic_properties = (const property_t[]){
+ {
+ .type = PT_U16,
+ .id = "caid",
+ .name = N_("CA ID"),
+ .desc = N_("Conditional Access Identification."),
+ .off = offsetof(constcw_t, ccw_caid),
+ .opts = PO_HEXA,
+ .def.u16 = 0x2600
+ },
+ {
+ .type = PT_U32,
+ .id = "providerid",
+ .name = N_("Provider ID"),
+ .desc = N_("The provider's ID."),
+ .off = offsetof(constcw_t, ccw_providerid),
+ .opts = PO_HEXA,
+ .def.u32 = 0
+ },
+ {
+ .type = PT_U16,
+ .id = "tsid",
+ .name = N_("Transponder ID"),
+ .desc = N_("The transponder ID."),
+ .off = offsetof(constcw_t, ccw_tsid),
+ .opts = PO_HEXA,
+ .def.u16 = 1,
+ },
+ {
+ .type = PT_U16,
+ .id = "sid",
+ .name = N_("Service ID"),
+ .desc = N_("The service ID."),
+ .off = offsetof(constcw_t, ccw_sid),
+ .opts = PO_HEXA,
+ .def.u16 = 1,
+ },
+ {
+ .type = PT_STR,
+ .id = "key_even",
+ .name = N_("Even key"),
+ .desc = N_("Even key."),
+ .set = constcw_class_key_even_set,
+ .get = constcw_class_key_even_get,
+ .opts = PO_PASSWORD,
+ .def.s = "00:00:00:00:00:00:00:00",
+ },
+ {
+ .type = PT_STR,
+ .id = "key_odd",
+ .name = N_("Odd key"),
+ .desc = N_("Odd key."),
+ .set = constcw_class_key_odd_set,
+ .get = constcw_class_key_odd_get,
+ .opts = PO_PASSWORD,
+ .def.s = "00:00:00:00:00:00:00:00",
+ },
+ { }
+ }
+};
+
+const idclass_t caclient_ccw_des_ncb_class =
{
.ic_super = &caclient_class,
- .ic_class = "caclient_ccw_des",
- .ic_caption = N_("DES Constant Code Word"),
+ .ic_class = "caclient_ccw_des_ncb",
+ .ic_caption = N_("DES NCB Constant Code Word"),
.ic_properties = (const property_t[]){
{
.type = PT_U16,
}
};
-const idclass_t caclient_ccw_aes_class =
+const idclass_t caclient_ccw_aes_ecb_class =
{
.ic_super = &caclient_class,
- .ic_class = "caclient_ccw_aes",
- .ic_caption = N_("AES Constant Code Word"),
+ .ic_class = "caclient_ccw_aes_ecb",
+ .ic_caption = N_("AES ECB Constant Code Word"),
.ic_properties = (const property_t[]){
{
.type = PT_U16,
es3 = *es;
pthread_mutex_unlock(&cwc->cwc_mutex);
descrambler_keys((th_descrambler_t *)ct,
- off == 16 ? DESCRAMBLER_AES : DESCRAMBLER_DES,
+ off == 16 ? DESCRAMBLER_AES_ECB : DESCRAMBLER_CSA_CBC,
msg + 3, msg + 3 + off);
snprintf(chaninfo, sizeof(chaninfo), "%s:%i", cwc->cwc_hostname, cwc->cwc_port);
descrambler_notify((th_descrambler_t *)ct,
}
static void
-tvhcsa_des_flush
+tvhcsa_csa_cbc_flush
( tvhcsa_t *csa, struct mpegts_service *s )
{
#if ENABLE_DVBCSA
}
static void
-tvhcsa_des_descramble
+tvhcsa_csa_cbc_descramble
( tvhcsa_t *csa, struct mpegts_service *s, const uint8_t *tsb, int tsb_len )
{
const uint8_t *tsb_end = tsb + tsb_len;
} while(0);
if(csa->csa_fill == csa->csa_cluster_size)
- tvhcsa_des_flush(csa, s);
+ tvhcsa_csa_cbc_flush(csa, s);
}
csa->csa_fill++;
if(csa->csa_fill == csa->csa_cluster_size)
- tvhcsa_des_flush(csa, s);
+ tvhcsa_csa_cbc_flush(csa, s);
}
if (csa->csa_descramble)
return -1;
switch (type) {
- case DESCRAMBLER_DES:
- csa->csa_descramble = tvhcsa_des_descramble;
- csa->csa_flush = tvhcsa_des_flush;
+ case DESCRAMBLER_CSA_CBC:
+ csa->csa_descramble = tvhcsa_csa_cbc_descramble;
+ csa->csa_flush = tvhcsa_csa_cbc_flush;
csa->csa_keylen = 8;
break;
- case DESCRAMBLER_AES:
+ case DESCRAMBLER_AES_ECB:
csa->csa_descramble = tvhcsa_aes_descramble;
csa->csa_flush = tvhcsa_aes_flush;
csa->csa_keylen = 16;
void tvhcsa_set_key_even( tvhcsa_t *csa, const uint8_t *even )
{
switch (csa->csa_type) {
- case DESCRAMBLER_DES:
+ case DESCRAMBLER_CSA_CBC:
#if ENABLE_DVBCSA
dvbcsa_bs_key_set(even, csa->csa_key_even);
#else
set_even_control_word((csa)->csa_keys, even);
#endif
break;
- case DESCRAMBLER_AES:
+ case DESCRAMBLER_AES_ECB:
aes_set_even_control_word(csa->csa_aes_keys, even);
break;
default:
{
assert(csa->csa_type);
switch (csa->csa_type) {
- case DESCRAMBLER_DES:
+ case DESCRAMBLER_CSA_CBC:
#if ENABLE_DVBCSA
dvbcsa_bs_key_set(odd, csa->csa_key_odd);
#else
set_odd_control_word((csa)->csa_keys, odd);
#endif
break;
- case DESCRAMBLER_AES:
+ case DESCRAMBLER_AES_ECB:
aes_set_odd_control_word(csa->csa_aes_keys, odd);
break;
default: