From c82a3d1bd0a5c42af7a5f09eaa2acd6fa44dac7b Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Tue, 30 May 2017 14:31:34 +0200 Subject: [PATCH] descrambler: fix the AES 64/128 mess --- Makefile | 1 + src/descrambler.h | 13 +++-- src/descrambler/algo/libaes128dec.c | 88 +++++++++++++++++++++++++++++ src/descrambler/algo/libaes128dec.h | 35 ++++++++++++ src/descrambler/algo/libaesdec.c | 17 +++--- src/descrambler/caclient.c | 1 + src/descrambler/caclient.h | 1 + src/descrambler/constcw.c | 76 +++++++++++++++++++++++-- src/descrambler/tsdebugcw.c | 2 +- src/descrambler/tvhcsa.c | 69 +++++++++++++++++----- src/descrambler/tvhcsa.h | 8 +-- 11 files changed, 271 insertions(+), 40 deletions(-) create mode 100644 src/descrambler/algo/libaes128dec.c create mode 100644 src/descrambler/algo/libaes128dec.h diff --git a/Makefile b/Makefile index 56aa69eae..ebe3fb3f1 100644 --- a/Makefile +++ b/Makefile @@ -547,6 +547,7 @@ endif # crypto algorithms SRCS-${CONFIG_SSL} += src/descrambler/algo/libaesdec.c +SRCS-${CONFIG_SSL} += src/descrambler/algo/libaes128dec.c SRCS-${CONFIG_SSL} += src/descrambler/algo/libdesdec.c # DBUS diff --git a/src/descrambler.h b/src/descrambler.h index bbbbdca55..85d08f8db 100644 --- a/src/descrambler.h +++ b/src/descrambler.h @@ -31,10 +31,15 @@ struct mpegts_table; struct mpegts_mux; struct th_descrambler_data; -#define DESCRAMBLER_NONE 0 -#define DESCRAMBLER_CSA_CBC 1 -#define DESCRAMBLER_DES_NCB 2 /* no block cipher mode! */ -#define DESCRAMBLER_AES_ECB 3 +#define DESCRAMBLER_NONE 0 +/* 64-bit keys */ +#define DESCRAMBLER_CSA_CBC 1 +#define DESCRAMBLER_DES_NCB 2 /* no block cipher mode! */ +#define DESCRAMBLER_AES_ECB 3 +/* 128-bit keys */ +#define DESCRAMBLER_AES128_ECB 16 + +#define DESCRAMBLER_KEY_SIZE(type) ((type >= DESCRAMBLER_AES128_ECB) ? 16 : 8) /** * Descrambler superclass diff --git a/src/descrambler/algo/libaes128dec.c b/src/descrambler/algo/libaes128dec.c new file mode 100644 index 000000000..5e5088d61 --- /dev/null +++ b/src/descrambler/algo/libaes128dec.c @@ -0,0 +1,88 @@ +/* + * libaesdec.c + * + * Created on: Jun 22, 2014 + * Author: spdfrk1 + */ + +#include +#include +#include +#include + +#include "openssl/aes.h" + +#include "libaes128dec.h" + +/* key structure */ +typedef struct aes128_priv { + AES_KEY keys[2]; /* 0 = even, 1 = odd */ +} aes128_priv_t; + +/* even cw represents one full 128-bit AES key */ +void aes128_set_even_control_word(void *keys, const uint8_t *pk) +{ + AES_set_decrypt_key(pk, 128, &((aes128_priv_t *) keys)->keys[0]); +} + +/* odd cw represents one full 128-bit AES key */ +void aes128_set_odd_control_word(void *keys, const uint8_t *pk) +{ + AES_set_decrypt_key(pk, 128, &((aes128_priv_t *) keys)->keys[1]); +} + +/* set control words */ +void aes128_set_control_words(void *keys, + const uint8_t *ev, + const uint8_t *od) +{ + AES_set_decrypt_key(ev, 128, &((aes128_priv_t *) keys)->keys[0]); + AES_set_decrypt_key(od, 128, &((aes128_priv_t *) keys)->keys[1]); +} + +/* allocate key structure */ +void * aes128_get_priv_struct(void) +{ + aes128_priv_t *keys; + + keys = (aes128_priv_t *) malloc(sizeof(aes128_priv_t)); + if (keys) { + static const uint8_t pk[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + aes128_set_control_words(keys, pk, pk); + } + return keys; +} + +/* free key structure */ +void aes128_free_priv_struct(void *keys) +{ + free(keys); +} + +/* decrypt */ +void aes128_decrypt_packet(void *keys, const uint8_t *pkt) +{ + uint_fast8_t ev_od = 0; + uint_fast8_t xc0, offset; + AES_KEY *k; + + // skip reserved and not encrypted pkt + if (((xc0 = pkt[3]) & 0x80) == 0) + return; + + ev_od = (xc0 & 0x40) >> 6; // 0 even, 1 odd + ((uint8_t *)pkt)[3] = xc0 & 0x3f; // consider it decrypted now + if (xc0 & 0x20) { // incomplete packet + offset = 4 + pkt[4] + 1; + if (offset + 16 > 188) { // decrypted==encrypted! + return; // this doesn't need more processing + } + } else { + offset = 4; + } + + k = &((aes128_priv_t *) keys)->keys[ev_od]; + for (; offset <= (188 - 16); offset += 16) { + AES_ecb_encrypt(pkt + offset, (uint8_t *)(pkt + offset), k, AES_DECRYPT); + } +} diff --git a/src/descrambler/algo/libaes128dec.h b/src/descrambler/algo/libaes128dec.h new file mode 100644 index 000000000..380008b7b --- /dev/null +++ b/src/descrambler/algo/libaes128dec.h @@ -0,0 +1,35 @@ +/* + * libaes128dec.h + * + * Created on: Jun 22, 2014 + * Author: spdfrk1 + */ + +#ifndef LIBAES128DEC_H_ +#define LIBAES128DEC_H_ + +#include +#include "build.h" + +#if ENABLE_SSL + +void *aes128_get_priv_struct(void); +void aes128_free_priv_struct(void *keys); +void aes128_set_control_words(void *keys, const uint8_t *even, const uint8_t *odd); +void aes128_set_even_control_word(void *keys, const uint8_t *even); +void aes128_set_odd_control_word(void *keys, const uint8_t *odd); +void aes128_decrypt_packet(void *keys, const uint8_t *pkt); + +#else + +// empty functions +static inline void *aes128_get_priv_struct(void) { return NULL; }; +static inline void aes128_free_priv_struct(void *keys) { return; }; +static inline void aes128_set_control_words(void *keys, const uint8_t *even, const uint8_t *odd) { return; }; +static inline void aes128_set_even_control_word(void *keys, const uint8_t *even) { return; }; +static inline void aes128_set_odd_control_word(void *keys, const uint8_t *odd) { return; }; +static inline void aes128_decrypt_packet(void *keys, const uint8_t *pkt) { return; }; + +#endif + +#endif /* LIBAES128DEC_H_ */ diff --git a/src/descrambler/algo/libaesdec.c b/src/descrambler/algo/libaesdec.c index 4aac4bc78..81374cb15 100644 --- a/src/descrambler/algo/libaesdec.c +++ b/src/descrambler/algo/libaesdec.c @@ -1,8 +1,7 @@ /* * libaesdec.c * - * Created on: Jun 22, 2014 - * Author: spdfrk1 + * Based on code from spdfrk1 */ #include @@ -19,16 +18,16 @@ typedef struct aes_priv { AES_KEY keys[2]; /* 0 = even, 1 = odd */ } aes_priv_t; -/* even cw represents one full 128-bit AES key */ +/* even cw represents one full 64-bit AES key */ void aes_set_even_control_word(void *keys, const uint8_t *pk) { - AES_set_decrypt_key(pk, 128, &((aes_priv_t *) keys)->keys[0]); + AES_set_decrypt_key(pk, 64, &((aes_priv_t *) keys)->keys[0]); } -/* odd cw represents one full 128-bit AES key */ +/* odd cw represents one full 64-bit AES key */ void aes_set_odd_control_word(void *keys, const uint8_t *pk) { - AES_set_decrypt_key(pk, 128, &((aes_priv_t *) keys)->keys[1]); + AES_set_decrypt_key(pk, 64, &((aes_priv_t *) keys)->keys[1]); } /* set control words */ @@ -36,8 +35,8 @@ void aes_set_control_words(void *keys, const uint8_t *ev, const uint8_t *od) { - AES_set_decrypt_key(ev, 128, &((aes_priv_t *) keys)->keys[0]); - AES_set_decrypt_key(od, 128, &((aes_priv_t *) keys)->keys[1]); + AES_set_decrypt_key(ev, 64, &((aes_priv_t *) keys)->keys[0]); + AES_set_decrypt_key(od, 64, &((aes_priv_t *) keys)->keys[1]); } /* allocate key structure */ @@ -82,7 +81,7 @@ void aes_decrypt_packet(void *keys, const uint8_t *pkt) } k = &((aes_priv_t *) keys)->keys[ev_od]; - for (; offset <= (188 - 16); offset += 16) { + for (; offset <= (188 - 8); offset += 8) { AES_ecb_encrypt(pkt + offset, (uint8_t *)(pkt + offset), k, AES_DECRYPT); } } diff --git a/src/descrambler/caclient.c b/src/descrambler/caclient.c index 8432804d9..79042b4a6 100644 --- a/src/descrambler/caclient.c +++ b/src/descrambler/caclient.c @@ -34,6 +34,7 @@ const idclass_t *caclient_classes[] = { &caclient_ccw_csa_cbc_class, &caclient_ccw_des_ncb_class, &caclient_ccw_aes_ecb_class, + &caclient_ccw_aes128_ecb_class, #endif NULL }; diff --git a/src/descrambler/caclient.h b/src/descrambler/caclient.h index b02c6349d..cb1c275c6 100644 --- a/src/descrambler/caclient.h +++ b/src/descrambler/caclient.h @@ -31,6 +31,7 @@ extern const idclass_t caclient_capmt_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; +extern const idclass_t caclient_ccw_aes128_ecb_class; TAILQ_HEAD(caclient_entry_queue, caclient); diff --git a/src/descrambler/constcw.c b/src/descrambler/constcw.c index e703a7133..12b593c7f 100644 --- a/src/descrambler/constcw.c +++ b/src/descrambler/constcw.c @@ -67,6 +67,8 @@ constcw_algo(caclient_t *cac) return DESCRAMBLER_DES_NCB; if (idnode_is_instance(&ccw->cac_id, &caclient_ccw_aes_ecb_class)) return DESCRAMBLER_AES_ECB; + if (idnode_is_instance(&ccw->cac_id, &caclient_ccw_aes128_ecb_class)) + return DESCRAMBLER_AES128_ECB; return DESCRAMBLER_CSA_CBC; } @@ -78,11 +80,9 @@ constcw_key_size(caclient_t *cac) { constcw_t *ccw = (constcw_t *)cac; - 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; + if (idnode_is_instance(&ccw->cac_id, &caclient_ccw_aes128_ecb_class)) + return 16; + return 8; } /* @@ -431,6 +431,72 @@ const idclass_t caclient_ccw_aes_ecb_class = .ic_super = &caclient_class, .ic_class = "caclient_ccw_aes_ecb", .ic_caption = N_("AES ECB 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_aes128_ecb_class = +{ + .ic_super = &caclient_class, + .ic_class = "caclient_ccw_aes128_ecb", + .ic_caption = N_("AES128 ECB Constant Code Word"), .ic_properties = (const property_t[]){ { .type = PT_U16, diff --git a/src/descrambler/tsdebugcw.c b/src/descrambler/tsdebugcw.c index b42449ac1..3bcc7c203 100644 --- a/src/descrambler/tsdebugcw.c +++ b/src/descrambler/tsdebugcw.c @@ -116,7 +116,7 @@ tsdebugcw_new_keys(service_t *t, int type, uint16_t pid, uint8_t *odd, uint8_t * th_descrambler_t *td; tsdebugcw_service_t *ct; tsdebugcw_request_t *ctr; - int keylen = type == DESCRAMBLER_AES_ECB ? 16 : 8; + int keylen = DESCRAMBLER_KEY_SIZE(type); LIST_FOREACH(td, &t->s_descramblers, td_service_link) if (td->td_stop == tsdebugcw_service_destroy) diff --git a/src/descrambler/tvhcsa.c b/src/descrambler/tvhcsa.c index af7b49231..3f909e746 100644 --- a/src/descrambler/tvhcsa.c +++ b/src/descrambler/tvhcsa.c @@ -20,6 +20,10 @@ #include "input.h" #include "input/mpegts/tsdemux.h" +#include "descrambler/algo/libaesdec.h" +#include "descrambler/algo/libaes128dec.h" +#include "descrambler/algo/libdesdec.h" + #include #include #include @@ -38,7 +42,18 @@ tvhcsa_aes_ecb_descramble const uint8_t *tsb2, *end2; for (tsb2 = tsb, end2 = tsb + len; tsb2 < end2; tsb2 += 188) - aes_decrypt_packet(csa->csa_aes_priv, tsb2); + aes_decrypt_packet(csa->csa_priv, tsb2); + ts_recv_packet2(s, tsb, len); +} + +static void +tvhcsa_aes128_ecb_descramble + ( tvhcsa_t *csa, struct mpegts_service *s, const uint8_t *tsb, int len ) +{ + const uint8_t *tsb2, *end2; + + for (tsb2 = tsb, end2 = tsb + len; tsb2 < end2; tsb2 += 188) + aes128_decrypt_packet(csa->csa_priv, tsb2); ts_recv_packet2(s, tsb, len); } @@ -49,7 +64,7 @@ tvhcsa_des_ncb_descramble const uint8_t *tsb2, *end2; for (tsb2 = tsb, end2 = tsb + len; tsb2 < end2; tsb2 += 188) - des_decrypt_packet(csa->csa_des_priv, tsb2); + des_decrypt_packet(csa->csa_priv, tsb2); ts_recv_packet2(s, tsb, len); } @@ -212,15 +227,21 @@ tvhcsa_set_type( tvhcsa_t *csa, int type ) #endif break; case DESCRAMBLER_DES_NCB: - csa->csa_des_priv = des_get_priv_struct(); + csa->csa_priv = des_get_priv_struct(); csa->csa_descramble = tvhcsa_des_ncb_descramble; csa->csa_flush = tvhcsa_empty_flush; csa->csa_keylen = 8; break; case DESCRAMBLER_AES_ECB: - csa->csa_aes_priv = aes_get_priv_struct(); + csa->csa_priv = aes_get_priv_struct(); csa->csa_descramble = tvhcsa_aes_ecb_descramble; csa->csa_flush = tvhcsa_empty_flush; + csa->csa_keylen = 8; + break; + case DESCRAMBLER_AES128_ECB: + csa->csa_priv = aes128_get_priv_struct(); + csa->csa_descramble = tvhcsa_aes128_ecb_descramble; + csa->csa_flush = tvhcsa_empty_flush; csa->csa_keylen = 16; break; default: @@ -242,10 +263,13 @@ void tvhcsa_set_key_even( tvhcsa_t *csa, const uint8_t *even ) #endif break; case DESCRAMBLER_DES_NCB: - des_set_even_control_word(csa->csa_des_priv, even); + des_set_even_control_word(csa->csa_priv, even); break; case DESCRAMBLER_AES_ECB: - aes_set_even_control_word(csa->csa_aes_priv, even); + aes_set_even_control_word(csa->csa_priv, even); + break; + case DESCRAMBLER_AES128_ECB: + aes128_set_even_control_word(csa->csa_priv, even); break; default: assert(0); @@ -264,10 +288,13 @@ void tvhcsa_set_key_odd( tvhcsa_t *csa, const uint8_t *odd ) #endif break; case DESCRAMBLER_DES_NCB: - des_set_odd_control_word(csa->csa_des_priv, odd); + des_set_odd_control_word(csa->csa_priv, odd); break; case DESCRAMBLER_AES_ECB: - aes_set_odd_control_word(csa->csa_aes_priv, odd); + aes_set_odd_control_word(csa->csa_priv, odd); + break; + case DESCRAMBLER_AES128_ECB: + aes128_set_odd_control_word(csa->csa_priv, odd); break; default: assert(0); @@ -311,12 +338,24 @@ tvhcsa_destroy ( tvhcsa_t *csa ) free(csa->csa_tsbcluster); csa->csa_tsbcluster = NULL; } - if (csa->csa_aes_priv) { - aes_free_priv_struct(csa->csa_aes_priv); - csa->csa_aes_priv = NULL; - } - if (csa->csa_des_priv) { - des_free_priv_struct(csa->csa_des_priv); - csa->csa_des_priv = NULL; + if (csa->csa_priv) { + switch (csa->csa_type) { + case DESCRAMBLER_CSA_CBC: + break; + case DESCRAMBLER_DES_NCB: + des_free_priv_struct(csa->csa_priv); + break; + case DESCRAMBLER_AES_ECB: + aes_free_priv_struct(csa->csa_priv); + break; + case DESCRAMBLER_AES128_ECB: + aes128_free_priv_struct(csa->csa_priv); + break; + default: + assert(0); + } + csa->csa_priv = NULL; } + csa->csa_type = 0; + csa->csa_keylen = 0; } diff --git a/src/descrambler/tvhcsa.h b/src/descrambler/tvhcsa.h index ef727b090..ec6f3ecd2 100644 --- a/src/descrambler/tvhcsa.h +++ b/src/descrambler/tvhcsa.h @@ -30,9 +30,6 @@ struct elementary_stream; #include "ffdecsa/FFdecsa.h" #endif -#include "algo/libaesdec.h" -#include "algo/libdesdec.h" - typedef struct tvhcsa { @@ -62,9 +59,8 @@ typedef struct tvhcsa #else void *csa_keys; #endif - void *csa_aes_priv; - void *csa_des_priv; - + void *csa_priv; + } tvhcsa_t; #if ENABLE_TVHCSA -- 2.47.3