From 1463b25b36e9eca27e34594f6eaa3aad4bac05b4 Mon Sep 17 00:00:00 2001 From: anon Date: Thu, 28 Aug 2008 21:49:08 +0800 Subject: [PATCH] irdeto: add support for Irdeto2 --- systems/irdeto/irdeto.c | 2 +- systems/irdeto/irdeto.h | 1 + systems/irdeto/irdeto.mk | 2 +- systems/irdeto/irdeto1.c | 5 +- systems/irdeto/irdeto2.c | 282 ++++++++++++++++++++++++++++++++++++ systems/irdeto/log-irdeto.h | 4 +- 6 files changed, 289 insertions(+), 7 deletions(-) create mode 100644 systems/irdeto/irdeto2.c diff --git a/systems/irdeto/irdeto.c b/systems/irdeto/irdeto.c index e72d501..02b166e 100644 --- a/systems/irdeto/irdeto.c +++ b/systems/irdeto/irdeto.c @@ -30,7 +30,7 @@ static const struct LogModule lm_sys = { (LMOD_ENABLE|L_SYS_ALL)&LOPT_MASK, (LMOD_ENABLE|L_SYS_DEFDEF)&LOPT_MASK, "irdeto", - { L_SYS_DEFNAMES } + { L_SYS_DEFNAMES,"rawemm","rawecm" } }; ADD_MODULE(L_SYS,lm_sys) diff --git a/systems/irdeto/irdeto.h b/systems/irdeto/irdeto.h index 6c5709e..cd95caa 100644 --- a/systems/irdeto/irdeto.h +++ b/systems/irdeto/irdeto.h @@ -24,6 +24,7 @@ #define SYSTEM_BETA 0x1700 #define SYSTEM_NAME "Irdeto" +#define SYSTEM_NAME2 "Irdeto2" #define SYSTEM_PRI -10 #define TYPE_I1 0 diff --git a/systems/irdeto/irdeto.mk b/systems/irdeto/irdeto.mk index cfde90e..dd16106 100644 --- a/systems/irdeto/irdeto.mk +++ b/systems/irdeto/irdeto.mk @@ -2,4 +2,4 @@ # Irdeto # TARGET = irdeto -OBJS = irdeto.o irdeto1.o +OBJS = irdeto.o irdeto1.o irdeto2.o diff --git a/systems/irdeto/irdeto1.c b/systems/irdeto/irdeto1.c index c829316..b3285fd 100644 --- a/systems/irdeto/irdeto1.c +++ b/systems/irdeto/irdeto1.c @@ -28,8 +28,6 @@ #include "irdeto.h" #include "log-irdeto.h" -#define SYSTEM_CAN_HANDLE(x) ((x)==SYSTEM_IRDETO || (x)==SYSTEM_BETA) - // -- cIrdCardInfo ------------------------------------------------------------- class cIrdCardInfo : public cStructItem, public cProviderIrdeto, public cCardIrdeto { @@ -464,6 +462,5 @@ cSystemLinkIrd::cSystemLinkIrd(void) bool cSystemLinkIrd::CanHandle(unsigned short SysId) { - SysId&=SYSTEM_MASK; - return SYSTEM_CAN_HANDLE(SysId); + return SysId==SYSTEM_IRDETO || (SysId&SYSTEM_MASK)==SYSTEM_BETA; } diff --git a/systems/irdeto/irdeto2.c b/systems/irdeto/irdeto2.c new file mode 100644 index 0000000..da8ac92 --- /dev/null +++ b/systems/irdeto/irdeto2.c @@ -0,0 +1,282 @@ +/* + * Softcam plugin to VDR (C++) + * + * This code is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include + +#include "system-common.h" +#include "data.h" +#include "parse.h" +#include "helper.h" +#include "misc.h" + +#include +#include "openssl-compat.h" + +#include "irdeto.h" +#include "log-irdeto.h" + +// -- cIrdeto2 ----------------------------------------------------------------- + +class cIrdeto2 { +private: + DES_key_schedule ks1, ks2; + // + void ScheduleKey(const unsigned char *key); + void DES3(unsigned char *data, int mode); +protected: + void Encrypt(unsigned char *data, const unsigned char *seed, const unsigned char *key, int len); + void Decrypt(unsigned char *data, const unsigned char *seed, const unsigned char *key, int len); + bool CalculateHash(const unsigned char *Key, const unsigned char *IV_PAD, const unsigned char *Data2Sign, int DataLen); + }; + +void cIrdeto2::ScheduleKey(const unsigned char *key) +{ + DES_key_sched((DES_cblock *)key,&ks1); + DES_key_sched((DES_cblock *)(key+8),&ks2); +} + +void cIrdeto2::DES3(unsigned char *data, int mode) +{ + int m1, m2; + if(mode) { m1=DES_DECRYPT; m2=DES_ENCRYPT; } + else { m1=DES_ENCRYPT; m2=DES_DECRYPT; } + DES_ecb_encrypt(DES_CAST(data),DES_CAST(data),&ks1,m1); + DES_ecb_encrypt(DES_CAST(data),DES_CAST(data),&ks2,m2); + DES_ecb_encrypt(DES_CAST(data),DES_CAST(data),&ks1,m1); +} + +void cIrdeto2::Encrypt(unsigned char *data, const unsigned char *seed, const unsigned char *key, int len) +{ + ScheduleKey(key); + len&=~7; + const unsigned char *tmp=seed; + for(int i=0; icaId,KEYSET(prov,TYPE_IV,0),16))) { + if(doLog) PRINTF(L_SYS_KEY,"missing %04x %02x IV key",ecm->caId,prov); + return false; + } + pk->Get(ECM_IV); + + unsigned char ECM_Seed[16]; + if(!(pk=keys.FindKey('I',ecm->caId,KEYSET(prov,TYPE_SEED,0),16))) { + if(doLog) PRINTF(L_SYS_KEY,"missing %04x %02x ECM key",ecm->caId,prov); + return false; + } + pk->Get(ECM_Seed); + + cKeySnoop ks(this,'I',ecm->caId,KEYSET(prov,TYPE_OP,data[9])); + unsigned char key[16]; + if(!(pk=keys.FindKey('I',ecm->caId,KEYSET(prov,TYPE_OP,data[9]),16))) return false; + pk->Get(key); + PrepareSeed(ECM_Seed,key); + + data+=12; + Decrypt(data,ECM_IV,ECM_Seed,len); + int i=(data[0]&7)+1; + NanoDecrypt(data,i,len-8,key,ECM_IV); + if(CalculateHash(ECM_Seed,ECM_IV,data-6,len+6)) { + HEXDUMP(L_SYS_RAWECM,data-12,len+12,"Irdeto2 RAWECM"); + while(iGet(EMM_IV); + + for(int keyno=0; keyno<2; keyno++) { + if(!(pk=keys.FindKey('I',caid,KEYSET(prov,TYPE_PMK,keyno),16))) { + PRINTF(L_SYS_EMM,"missing %04x %02x MK%d key",caid,prov,keyno); + continue; + } + unsigned char PMK[16]; + pk->Get(PMK); + + if(!(pk=keys.FindKey('I',caid,KEYSET(prov,TYPE_SEED,1),16))) { + PRINTF(L_SYS_EMM,"missing %04x %02x EMM key",caid,prov); + return; + } + unsigned char EMM_Seed[16]; + pk->Get(EMM_Seed); + PrepareSeed(EMM_Seed,PMK); + + memcpy(emm,data,len); + Decrypt(&emm[10],EMM_IV,EMM_Seed,len-10); + NanoDecrypt(emm,16,len-8,PMK,EMM_IV); + memcpy(emm+6,emm+7,len-7); // removing padding byte + if(CalculateHash(EMM_Seed,EMM_IV,emm+3,len-4)) { + HEXDUMP(L_SYS_RAWEMM,emm,len,"Irdeto2 RAWEMM"); + for(int i=15; i>2),&emm[i+3],16)) NewKey(); + } + break; + } + i+=l; + } + break; + } + else + PRINTF(L_SYS_EMM,"hash failed MK%d",keyno); + } +} + +// -- cSystemLinkIrd ----------------------------------------------------------- + +class cSystemLinkIrd2 : public cSystemLink { +public: + cSystemLinkIrd2(void); + virtual bool CanHandle(unsigned short SysId); + virtual cSystem *Create(void) { return new cSystemIrd2; } + }; + +static cSystemLinkIrd2 staticInit2; + +cSystemLinkIrd2::cSystemLinkIrd2(void) +:cSystemLink(SYSTEM_NAME2,SYSTEM_PRI) +{ + Feature.NeedsKeyFile(); +} + +bool cSystemLinkIrd2::CanHandle(unsigned short SysId) +{ + return SysId!=SYSTEM_IRDETO && (SysId&SYSTEM_MASK)==SYSTEM_IRDETO; +} diff --git a/systems/irdeto/log-irdeto.h b/systems/irdeto/log-irdeto.h index 6d09216..2dbac62 100644 --- a/systems/irdeto/log-irdeto.h +++ b/systems/irdeto/log-irdeto.h @@ -23,6 +23,8 @@ #include "log-sys.h" #define L_SYS 5 -#define L_SYS_ALL LALL(L_SYS_LASTDEF) +#define L_SYS_RAWEMM LCLASS(L_SYS,L_SYS_LASTDEF<<1) +#define L_SYS_RAWECM LCLASS(L_SYS,L_SYS_LASTDEF<<2) +#define L_SYS_ALL LALL(L_SYS_RAWECM) #endif -- 2.39.5