From: Jaroslav Kysela Date: Wed, 24 May 2017 12:36:52 +0000 (+0200) Subject: descrambler: fix the descrambling modes (CSA CBC, DES NCB, AES ECB) X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=0b097324b0e74d3f5e9664f0c8cfbacb6b0dcbfe;p=thirdparty%2Ftvheadend.git descrambler: fix the descrambling modes (CSA CBC, DES NCB, AES ECB) --- diff --git a/src/descrambler.h b/src/descrambler.h index 7060469ec..e635bf3bf 100644 --- a/src/descrambler.h +++ b/src/descrambler.h @@ -31,9 +31,10 @@ struct mpegts_table; 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 diff --git a/src/descrambler/caclient.c b/src/descrambler/caclient.c index c16234f00..8432804d9 100644 --- a/src/descrambler/caclient.c +++ b/src/descrambler/caclient.c @@ -31,8 +31,9 @@ const idclass_t *caclient_classes[] = { &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 }; @@ -92,8 +93,8 @@ caclient_create 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) @@ -108,9 +109,9 @@ caclient_create 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) { diff --git a/src/descrambler/caclient.h b/src/descrambler/caclient.h index 0c96c8fd4..d7db76512 100644 --- a/src/descrambler/caclient.h +++ b/src/descrambler/caclient.h @@ -28,8 +28,9 @@ extern const idclass_t caclient_class; 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); diff --git a/src/descrambler/capmt.c b/src/descrambler/capmt.c index 2b8c728de..c84c3b282 100644 --- a/src/descrambler/capmt.c +++ b/src/descrambler/capmt.c @@ -1264,9 +1264,9 @@ capmt_analyze_cmd(capmt_t *capmt, int adapter, sbuf_t *sb, int offset) 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); @@ -1286,9 +1286,9 @@ capmt_analyze_cmd(capmt_t *capmt, int adapter, sbuf_t *sb, int offset) 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); @@ -1619,7 +1619,7 @@ handle_ca0_wrapper(capmt_t *capmt) capmt_process_key(capmt, 0, buffer[0] | ((uint16_t)buffer[1] << 8), - DESCRAMBLER_DES, + DESCRAMBLER_CSA_CBC, buffer + 2, buffer + 10, ret == 18); } diff --git a/src/descrambler/cccam.c b/src/descrambler/cccam.c index 8466e17b3..7af24f739 100644 --- a/src/descrambler/cccam.c +++ b/src/descrambler/cccam.c @@ -701,7 +701,7 @@ forbid: 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, diff --git a/src/descrambler/constcw.c b/src/descrambler/constcw.c index 8117d2000..14f9c5b7f 100644 --- a/src/descrambler/constcw.c +++ b/src/descrambler/constcw.c @@ -55,6 +55,21 @@ constcw_name(constcw_t *ccw) 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; +} + /** * */ @@ -63,7 +78,9 @@ constcw_key_size(caclient_t *cac) { 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; } @@ -151,8 +168,7 @@ constcw_service_start(caclient_t *cac, service_t *t) 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); } @@ -278,11 +294,77 @@ constcw_class_key_odd_get(void *o) 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, @@ -344,11 +426,11 @@ const idclass_t caclient_ccw_des_class = } }; -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, diff --git a/src/descrambler/cwc.c b/src/descrambler/cwc.c index 44a1d26e2..5b1fd9798 100644 --- a/src/descrambler/cwc.c +++ b/src/descrambler/cwc.c @@ -849,7 +849,7 @@ forbid: 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, diff --git a/src/descrambler/tvhcsa.c b/src/descrambler/tvhcsa.c index 99ff46a01..137823be4 100644 --- a/src/descrambler/tvhcsa.c +++ b/src/descrambler/tvhcsa.c @@ -43,7 +43,7 @@ tvhcsa_aes_descramble } static void -tvhcsa_des_flush +tvhcsa_csa_cbc_flush ( tvhcsa_t *csa, struct mpegts_service *s ) { #if ENABLE_DVBCSA @@ -90,7 +90,7 @@ tvhcsa_des_flush } 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; @@ -149,7 +149,7 @@ tvhcsa_des_descramble } while(0); if(csa->csa_fill == csa->csa_cluster_size) - tvhcsa_des_flush(csa, s); + tvhcsa_csa_cbc_flush(csa, s); } @@ -161,7 +161,7 @@ tvhcsa_des_descramble csa->csa_fill++; if(csa->csa_fill == csa->csa_cluster_size) - tvhcsa_des_flush(csa, s); + tvhcsa_csa_cbc_flush(csa, s); } @@ -176,12 +176,12 @@ tvhcsa_set_type( tvhcsa_t *csa, int type ) 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; @@ -197,14 +197,14 @@ tvhcsa_set_type( tvhcsa_t *csa, int type ) 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: @@ -216,14 +216,14 @@ void tvhcsa_set_key_odd( tvhcsa_t *csa, const uint8_t *odd ) { 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: