From: Jaroslav Kysela Date: Wed, 24 May 2017 13:32:33 +0000 (+0200) Subject: descrambler: add libdesdec X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=1ee0611d90d475556cfc7e1247523941c7d67e37;p=thirdparty%2Ftvheadend.git descrambler: add libdesdec --- diff --git a/Makefile b/Makefile index cbeb70772..97f45513a 100644 --- a/Makefile +++ b/Makefile @@ -544,8 +544,9 @@ ${BUILDDIR}/src/descrambler/ffdecsa/ffdecsa_mmx.o : CFLAGS += -mmmx ${BUILDDIR}/src/descrambler/ffdecsa/ffdecsa_sse2.o : CFLAGS += -msse2 endif -# libaesdec +# crypto algorithms SRCS-${CONFIG_SSL} += src/descrambler/algo/libaesdec.c +SRCS-${CONFIG_SSL} += src/descrambler/algo/libdesdec.c # DBUS SRCS-${CONFIG_DBUS_1} += src/dbus.c diff --git a/src/descrambler/algo/libaesdec.c b/src/descrambler/algo/libaesdec.c index 3a41a827c..cab1d5f51 100644 --- a/src/descrambler/algo/libaesdec.c +++ b/src/descrambler/algo/libaesdec.c @@ -41,7 +41,7 @@ void aes_set_control_words(void *keys, } /* allocate key structure */ -void * aes_get_key_struct(void) +void * aes_get_priv_struct(void) { aes_priv_t *keys; @@ -54,13 +54,13 @@ void * aes_get_key_struct(void) } /* free key structure */ -void aes_free_key_struct(void *keys) +void aes_free_priv_struct(void *keys) { free(keys); } /* decrypt */ -void aes_decrypt_packet(void *keys, uint8_t *pkt) +void aes_decrypt_packet(void *keys, const uint8_t *pkt) { uint8_t ev_od = 0; uint_fast8_t xc0, offset, n; @@ -78,7 +78,7 @@ void aes_decrypt_packet(void *keys, uint8_t *pkt) if (xc0 == 0x80 || xc0 == 0xc0) { // encrypted ev_od = (xc0 & 0x40) >> 6; // 0 even, 1 odd - pkt[3] &= 0x3f; // consider it decrypted now + ((uint8_t *)pkt)[3] &= 0x3f; // consider it decrypted now if (pkt[3] & 0x20) { // incomplete packet offset = 4 + pkt[4] + 1; n = (188 - offset) >> 4; @@ -94,6 +94,6 @@ void aes_decrypt_packet(void *keys, uint8_t *pkt) k = &((aes_priv_t *) keys)->keys[ev_od]; for (; offset <= (188 - 16); offset += 16) { - AES_ecb_encrypt(pkt + offset, pkt + offset, k, AES_DECRYPT); + AES_ecb_encrypt(pkt + offset, (uint8_t *)(pkt + offset), k, AES_DECRYPT); } } diff --git a/src/descrambler/algo/libaesdec.h b/src/descrambler/algo/libaesdec.h index 1577ed298..a3198f327 100644 --- a/src/descrambler/algo/libaesdec.h +++ b/src/descrambler/algo/libaesdec.h @@ -13,22 +13,22 @@ #if ENABLE_SSL -void *aes_get_key_struct(void); -void aes_free_key_struct(void *keys); +void *aes_get_priv_struct(void); +void aes_free_priv_struct(void *keys); void aes_set_control_words(void *keys, const uint8_t *even, const uint8_t *odd); void aes_set_even_control_word(void *keys, const uint8_t *even); void aes_set_odd_control_word(void *keys, const uint8_t *odd); -void aes_decrypt_packet(void *keys, uint8_t *pkt); +void aes_decrypt_packet(void *keys, const uint8_t *pkt); #else // empty functions -static inline void *aes_get_key_struct(void) { return 0; }; -static inline void aes_free_key_struct(void *keys) { return; }; +static inline void *aes_get_priv_struct(void) { return NULL; }; +static inline void aes_free_priv_struct(void *keys) { return; }; static inline void aes_set_control_words(void *keys, const uint8_t *even, const uint8_t *odd) { return; }; static inline void aes_set_even_control_word(void *keys, const uint8_t *even) { return; }; static inline void aes_set_odd_control_word(void *keys, const uint8_t *odd) { return; }; -static inline void aes_decrypt_packet(void *keys, uint8_t *pkt) { return; }; +static inline void aes_decrypt_packet(void *keys, const uint8_t *pkt) { return; }; #endif diff --git a/src/descrambler/algo/libdesdec.c b/src/descrambler/algo/libdesdec.c new file mode 100644 index 000000000..8e6e00fda --- /dev/null +++ b/src/descrambler/algo/libdesdec.c @@ -0,0 +1,107 @@ +/* + * libaesdec.c + */ + +#include +#include +#include +#include + +#include "openssl/des.h" + +#include "libdesdec.h" + +/* key structure */ +typedef struct des_priv { + DES_key_schedule sched[2]; /* 0 = even, 1 = odd */ +} des_priv_t; + +/* even cw represents one 64-bit DES key */ +void des_set_even_control_word(void *priv, const uint8_t *pk) +{ + DES_set_key_unchecked((const_DES_cblock *)pk, &((des_priv_t *)priv)->sched[0]); +} + +/* odd cw represents one 64-bit DES key */ +void des_set_odd_control_word(void *priv, const uint8_t *pk) +{ + DES_set_key_unchecked((const_DES_cblock *)pk, &((des_priv_t *)priv)->sched[1]); +} + +/* set control words */ +void des_set_control_words(void *priv, + const uint8_t *ev, + const uint8_t *od) +{ + DES_set_key_unchecked((const_DES_cblock *)ev, &((des_priv_t *)priv)->sched[0]); + DES_set_key_unchecked((const_DES_cblock *)od, &((des_priv_t *)priv)->sched[1]); +} + +/* allocate key structure */ +void * des_get_priv_struct(void) +{ + des_priv_t *priv; + + priv = (des_priv_t *) malloc(sizeof(des_priv_t)); + if (priv) { + static const uint8_t pk[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + des_set_control_words(priv, pk, pk); + } + return priv; +} + +/* free key structure */ +void des_free_priv_struct(void *priv) +{ + free(priv); +} + +/* decrypt */ +void des_decrypt_packet(void *priv, const uint8_t *pkt) +{ + uint8_t ev_od = 0; + uint_fast8_t xc0, offset, offset2, n; + DES_key_schedule *sched; + uint8_t buf[188]; + + xc0 = pkt[3] & 0xc0; + + //skip clear pkt + if (xc0 == 0x00) + return; + + //skip reserved pkt + if (xc0 == 0x40) + return; + + if (xc0 == 0x80 || xc0 == 0xc0) { // encrypted + ev_od = (xc0 & 0x40) >> 6; // 0 even, 1 odd + ((uint8_t *)pkt)[3] &= 0x3f; // consider it decrypted now + if (pkt[3] & 0x20) { // incomplete packet + offset = 4 + pkt[4] + 1; + n = (188 - offset) >> 4; + if (n == 0) { // decrypted==encrypted! + return; // this doesn't need more processing + } + } else { + offset = 4; + } + } else { + return; + } + + sched = &((des_priv_t *)priv)->sched[ev_od]; + if (offset & 3) { + /* data must be aligned for DES_encrypt2() */ + offset2 = (offset + 3) & ~3; + memcpy(buf + offset2, pkt + offset, 188 - offset2); + for (; offset2 <= (188 - 8); offset2 += 8) { + DES_encrypt2((DES_LONG *)(buf + offset2), sched, 0); + } + memcpy((uint8_t *)(pkt + offset), buf + offset2, 188 - offset2); + } else { + for (; offset <= (188 - 8); offset += 8) { + DES_encrypt2((DES_LONG *)(pkt + offset), sched, 0); + } + } +} diff --git a/src/descrambler/algo/libdesdec.h b/src/descrambler/algo/libdesdec.h new file mode 100644 index 000000000..80bdbd122 --- /dev/null +++ b/src/descrambler/algo/libdesdec.h @@ -0,0 +1,32 @@ +/* + * libdesdec.h + */ + +#ifndef LIBDESDEC_H_ +#define LIBDESDEC_H_ + +#include +#include "build.h" + +#if ENABLE_SSL + +void *des_get_priv_struct(void); +void des_free_priv_struct(void *priv); +void des_set_control_words(void *priv, const uint8_t *even, const uint8_t *odd); +void des_set_even_control_word(void *priv, const uint8_t *even); +void des_set_odd_control_word(void *priv, const uint8_t *odd); +void des_decrypt_packet(void *priv, const uint8_t *pkt); + +#else + +// empty functions +static inline void *des_get_priv_struct(void) { return NULL; }; +static inline void des_free_priv_struct(void *priv) { return; }; +static inline void des_set_control_words(void *priv, const uint8_t *even, const uint8_t *odd) { return; }; +static inline void des_set_even_control_word(void *priv, const uint8_t *even) { return; }; +static inline void des_set_odd_control_word(void *priv, const uint8_t *odd) { return; }; +static inline void des_decrypt_packet(void *priv, const uint8_t *pkt) { return; }; + +#endif + +#endif /* LIBDESDEC_H_ */ diff --git a/src/descrambler/tvhcsa.c b/src/descrambler/tvhcsa.c index 137823be4..eccc1d4f4 100644 --- a/src/descrambler/tvhcsa.c +++ b/src/descrambler/tvhcsa.c @@ -25,20 +25,38 @@ #include static void -tvhcsa_aes_flush +tvhcsa_aes_ecb_flush ( tvhcsa_t *csa, struct mpegts_service *s ) { /* empty - no queue */ } static void -tvhcsa_aes_descramble +tvhcsa_aes_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) - aes_decrypt_packet(csa->csa_aes_keys, (unsigned char *)tsb2); + aes_decrypt_packet(csa->csa_aes_priv, tsb2); + ts_recv_packet2(s, tsb, len); +} + +static void +tvhcsa_des_ncb_flush + ( tvhcsa_t *csa, struct mpegts_service *s ) +{ + /* empty - no queue */ +} + +static void +tvhcsa_des_ncb_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) + des_decrypt_packet(csa->csa_des_priv, tsb2); ts_recv_packet2(s, tsb, len); } @@ -181,9 +199,14 @@ tvhcsa_set_type( tvhcsa_t *csa, int type ) csa->csa_flush = tvhcsa_csa_cbc_flush; csa->csa_keylen = 8; break; + case DESCRAMBLER_DES_NCB: + csa->csa_descramble = tvhcsa_des_ncb_descramble; + csa->csa_flush = tvhcsa_des_ncb_flush; + csa->csa_keylen = 8; + break; case DESCRAMBLER_AES_ECB: - csa->csa_descramble = tvhcsa_aes_descramble; - csa->csa_flush = tvhcsa_aes_flush; + csa->csa_descramble = tvhcsa_aes_ecb_descramble; + csa->csa_flush = tvhcsa_aes_ecb_flush; csa->csa_keylen = 16; break; default: @@ -204,8 +227,11 @@ void tvhcsa_set_key_even( tvhcsa_t *csa, const uint8_t *even ) set_even_control_word((csa)->csa_keys, even); #endif break; + case DESCRAMBLER_DES_NCB: + des_set_even_control_word(csa->csa_des_priv, even); + break; case DESCRAMBLER_AES_ECB: - aes_set_even_control_word(csa->csa_aes_keys, even); + aes_set_even_control_word(csa->csa_aes_priv, even); break; default: assert(0); @@ -223,8 +249,11 @@ void tvhcsa_set_key_odd( tvhcsa_t *csa, const uint8_t *odd ) set_odd_control_word((csa)->csa_keys, odd); #endif break; + case DESCRAMBLER_DES_NCB: + des_set_odd_control_word(csa->csa_des_priv, odd); + break; case DESCRAMBLER_AES_ECB: - aes_set_odd_control_word(csa->csa_aes_keys, odd); + aes_set_odd_control_word(csa->csa_aes_priv, odd); break; default: assert(0); @@ -255,7 +284,8 @@ tvhcsa_init ( tvhcsa_t *csa ) #else csa->csa_keys = get_key_struct(); #endif - csa->csa_aes_keys = aes_get_key_struct(); + csa->csa_aes_priv = aes_get_priv_struct(); + csa->csa_des_priv = des_get_priv_struct(); } void @@ -269,6 +299,7 @@ tvhcsa_destroy ( tvhcsa_t *csa ) #else free_key_struct(csa->csa_keys); #endif - aes_free_key_struct(csa->csa_aes_keys); + aes_free_priv_struct(csa->csa_aes_priv); + des_free_priv_struct(csa->csa_des_priv); free(csa->csa_tsbcluster); } diff --git a/src/descrambler/tvhcsa.h b/src/descrambler/tvhcsa.h index 06d1e167e..ef727b090 100644 --- a/src/descrambler/tvhcsa.h +++ b/src/descrambler/tvhcsa.h @@ -31,6 +31,7 @@ struct elementary_stream; #endif #include "algo/libaesdec.h" +#include "algo/libdesdec.h" typedef struct tvhcsa { @@ -61,7 +62,8 @@ typedef struct tvhcsa #else void *csa_keys; #endif - void *csa_aes_keys; + void *csa_aes_priv; + void *csa_des_priv; } tvhcsa_t;