📄 seca.cpp
字号:
xorVal ^= T1[idx1] ^ tabXor[i];
data[tabPos[i]] ^= xorVal ^ T2[idx2];
}
}
void cSeca2ProvFR::SignatureMod(unsigned char *MD, const unsigned char *PK)
{
const unsigned char *T1=SSEPT2();
unsigned int idx;
idx = ((MD[18] << 8) | MD[19]) & 0x3FF;
MD[10] = T1[idx];
MD[13] ^= PK[6];
idx = ((MD[15] << 8) | MD[13]) & 0x3FF;
MD[16] = T1[idx];
des.Des(MD,MD+10,SECA_DES_ENCR);
}
// -- Netherlands --------------------------------------------------------------
class cSeca2ProvNL : public cSeca2ProvSSE {
private:
virtual void PreSSECore(unsigned char *buf, const unsigned char *data, int i);
virtual void PostSSECore1(unsigned char *data, int pos);
virtual void PostSSECore2(unsigned char *buf, const unsigned char *data, int pos);
virtual void PostSSECore3(unsigned char *data, const unsigned char *buf, int pos);
virtual void PostSSECore4(unsigned char *data, int pos);
protected:
virtual bool InitSSE(void);
virtual void PostCW(unsigned char *data);
virtual void ChainTableXor(unsigned char *data, unsigned short index);
virtual bool DoSigCheck(void) { return false; }
public:
cSeca2ProvNL(unsigned short Id);
};
static const unsigned short IdsNL[] = { 0x6a,0 };
static cSeca2ProvLinkReg<cSeca2ProvNL> staticLinkNL(IdsNL);
static const struct ProvData provDataNL = {
0x6a,16895,16895,0xa3,0x3a, { 3, 0, 0, 0, 2, 4, 3, 0 }
};
cSeca2ProvNL::cSeca2ProvNL(unsigned short Id)
:cSeca2ProvSSE(Id)
{
pData=&provDataNL;
}
bool cSeca2ProvNL::InitSSE(void)
{
sse=GetMap("sse",5120,true);
sseP=GetMap("sse",336,false);
cw=GetMap("cw",512,false);
return sse && sseP && cw;
}
void cSeca2ProvNL::PreSSECore(unsigned char *buf, const unsigned char *data, int i)
{
const unsigned char *T1=SSET1(), *T2=SSET2();
buf[0] =data[7] ^T1[i+0x17];
buf[1] =data[1] ^T2[i+0x07];
buf[2] =data[2] ^T1[i+0x03];
buf[3] =data[3] ^T2[i+0x0C];
buf[4] =~data[4];
buf[5] =data[5] ^T1[i+0x1E];
buf[6] =data[6] ^T1[i+0x11];
buf[7] =data[0] ^T2[i+0x0F];
buf[8] =data[9] ^T1[i+0x15];
buf[9] =data[8] ^T2[i+0x04];
buf[10]=data[12]^T2[i+0x07];
buf[11]=data[11]^T1[i+0x16];
buf[12]=data[10]^T1[i+0x01];
buf[13]=data[13]^T1[i+0x0F];
buf[14]=~data[14];
buf[15]=data[15]^T2[i+0x0B];
}
void cSeca2ProvNL::PostSSECore1(unsigned char *data, int pos)
{
// modify 8 bytes before signature byte (0x82)
data[beforeSig+0] ^= 0xd6; data[beforeSig+1] ^= 0x96;
data[beforeSig+2] -= 0x51; data[beforeSig+3] ^= 0x3a;
data[beforeSig+4] -= 0x8d; data[beforeSig+5] ^= 0xf1;
data[beforeSig+6] -= 0xc2; data[beforeSig+7] ^= 0xb1;
data[afterSig+0] ^= 0x84; data[afterSig+1] ^= 0xf8;
data[afterSig+2] -= 0x7d; data[afterSig+3] = ~(data[afterSig+3]);
data[afterSig+4] ^= 0xfd; data[afterSig+5] ^= 0xd0;
data[afterSig+6] ^= 0x77; data[afterSig+7] ^= 0x25;
}
void cSeca2ProvNL::PostSSECore2(unsigned char *buf, const unsigned char *data, int pos)
{
const unsigned char *T1=SSEPT2();
memcpy(buf,&T1[(data[afterSig+6]+0x19)&0x7F],56);
}
void cSeca2ProvNL::PostSSECore3(unsigned char *data, const unsigned char *buf, int pos)
{
data[beforeSig+4]=buf[7];
data[beforeSig+5]=buf[0];
data[beforeSig+6]=buf[3];
data[beforeSig+7]=buf[5];
data[afterSig+0]=buf[6];
data[afterSig+1]=buf[2];
data[afterSig+2]=buf[1];
data[afterSig+3]=buf[4];
}
void cSeca2ProvNL::PostSSECore4(unsigned char *data, int pos)
{
data[afterSig+0]=data[beforeSig+1] ^ 0x65; data[afterSig+1]=data[beforeSig+0] ^ 0x75;
data[afterSig+2]=data[beforeSig+5] ^ 0x35; data[afterSig+3]=data[beforeSig+3] ^ 0xd9;
data[afterSig+4]=data[beforeSig+6] ^ 0xb7; data[afterSig+5]=data[beforeSig+7] ^ 0x9a;
data[afterSig+6]=data[beforeSig+4] ^ 0xc7; data[afterSig+7]=data[beforeSig+2] ^ 0x1f;
}
void cSeca2ProvNL::PostCW(unsigned char *data)
{
const unsigned char *T1=SSET1(), *T2=SSET2(), *T3=CWT1(), *T4=SSEPT2();
unsigned char key[8];
unsigned int off2;
off2=data[2]^data[8+6];
key[2]=T4[off2]; key[5]=T4[(off2+key[2])&0xff];
off2=(data[3]<<8)|data[8+4]; key[0]=T3[off2&0x1ff];
off2+=key[2]; key[4]=T3[off2&0x1ff];
off2=(data[0]<<8)|data[8+7]; key[7]=T2[off2&0x7ff];
off2+=key[0]; key[1]=T2[off2&0x7ff];
off2=(data[1]<<8)|data[8+5]; key[3]=T1[off2&0xbff];
off2+=key[4]; key[6]=T1[off2&0xbff];
des.Des(data+4,key,SECA_DES_ENCR);
}
void cSeca2ProvNL::ChainTableXor(unsigned char *data, unsigned short index)
{
static const unsigned short tabIdx[] = { 0x000, 0x4C3, 0x5D8, 0x63A, 0x471, 0x639, 0x417, 0x6CD };
static const unsigned char tabXor[] = { 0x84, 0xD6, 0x3A, 0x1F, 0x25, 0xB1, 0x7D, 0xF7 };
static const unsigned char tabPos1[] = { 2, 4, 3, 4, 5, 7, 6, 7 };
static const unsigned char tabPos2[] = { 3, 1, 5, 6, 0, 1, 0, 2 };
unsigned int idx1, idx2;
unsigned char xorVal=0;
const unsigned char *T1=MT(), *T2=SSET1();
idx1=(index^0x2B36) & 0x3FFF;
idx2=idx1 & 0xBFF;
for(int i=0; i<8; i++) {
idx1=(idx1 + tabIdx[i]) & 0x3FFF;
idx2=(idx2 + xorVal) & 0xBFF;
xorVal ^= T1[idx1] ^ tabXor[i];
data[tabPos1[i]]^=xorVal;
data[tabPos2[i]]^=T2[idx2];
}
}
#undef beforeSig
#undef afterSig
// -- Poland -------------------------------------------------------------------
class cSeca2ProvPL : public cSeca2Prov {
protected:
virtual void PreCW(unsigned char *data);
virtual void ChainTableXor(unsigned char *data, unsigned short index);
public:
cSeca2ProvPL(unsigned short Id);
};
static const unsigned short IdsPL[] = { 0x65,0 };
static cSeca2ProvLinkReg<cSeca2ProvPL> staticLinkPL(IdsPL);
static const struct ProvData provDataPL = {
0x65,16895,16895,0x96,0x69, { 3, 0, 0, 0, 2, 4, 3, 0 }
};
static const struct Perm ptPL[MAX_PERMS] = {
{ // 1
{ 2, 4, 4, 3, 2, 2, 4, 4 },
{ 3, 2, 4, 3, 4, 4, 2, 3 },
{ 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0 }
},{ // 2
{ 4, 4, 3, 2, 2, 3, 3, 4 },
{ 4, 2, 3, 4, 3, 2, 4, 2 },
{ 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0 }
},{ // 3
},{ // 4
},{ // 5
},{ // 6
},{ // 7
},{ // 8
},{ // 9
{ 4, 4, 3, 2, 3, 4, 3, 2 },
{ 2, 4, 3, 2, 2, 4, 4, 3 },
{ 2, 3, 4, 1, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0 },
},{ // 10
} };
cSeca2ProvPL::cSeca2ProvPL(unsigned short Id)
:cSeca2Prov(Id)
{
pData=&provDataPL; perm=ptPL;
}
void cSeca2ProvPL::PreCW(unsigned char *data)
{
static const unsigned char XT[]={ 0xA0,0x12,0x23,0x35,0x46,0xB0,0xDF,0xCA, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
static const unsigned char PT[]={ 0x05,0x04,0x06,0x07,0x03,0x00,0x01,0x02, 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F };
unsigned char temp[16];
xxor(temp,16,data,XT);
for(int i=15; i>=0; i--) data[i]=temp[PT[i]];
}
void cSeca2ProvPL::ChainTableXor(unsigned char *data, unsigned short index)
{
const unsigned char *T1=MT();
for(int i=0; i<8; i++) data[i]^=T1[index++];
}
// -- Spain ---------------------------------------------------------------------
class cSeca2ProvSPA : public cSeca2Prov {
protected:
virtual void CreateHashDW(unsigned char *buff, int i, unsigned char *PK, unsigned char *hashDW);
virtual void ChainTableXor(unsigned char *data, unsigned short index);
public:
cSeca2ProvSPA(unsigned short Id);
};
static const unsigned short IdsSPA[] = { 0x64,0x66,0x67,0 };
static cSeca2ProvLinkReg<cSeca2ProvSPA> staticLinkSPA(IdsSPA);
static const struct ProvData provDataSPA = {
0x64,16895,16895,0x96,0x69, { 2, 2, 2, 2, 2, 2, 2, 2 }
};
static const struct Perm ptSPA[MAX_PERMS] = {
{ // 1
{ 3, 2, 4, 3, 3, 4, 4, 2 },
{ 4, 4, 3, 3, 2, 2, 4, 4 },
{ 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0 }
},{ // 2
{ 2, 3, 4, 3, 2, 4, 3, 2 },
{ 4, 3, 2, 3, 4, 2, 4, 3 },
{ 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0 }
},{ // 3
},{ // 4
},{ // 5
},{ // 6
},{ // 7
},{ // 8
},{ // 9
{ 3, 3, 4, 4, 3, 3, 2, 2 },
{ 3, 3, 2, 2, 3, 3, 2, 2 },
{ 2, 3, 4, 1, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0 }
},{ // 10
} };
cSeca2ProvSPA::cSeca2ProvSPA(unsigned short Id)
:cSeca2Prov(Id)
{
pData=&provDataSPA; perm=ptSPA;
}
void cSeca2ProvSPA::CreateHashDW(unsigned char *buff, int i, unsigned char *PK, unsigned char *hashDW)
{
CalcSHASignature(buff,i,hashDW,false);
memcpy(&hashDW[20],hashDW,8);
Decrypt(&hashDW[20],PK,T1(0),T2(0));
CalcSHASignature(hashDW,28,hashDW,false);
}
void cSeca2ProvSPA::ChainTableXor(unsigned char *data, unsigned short index)
{
const unsigned char *T1=MT();
for(int i=0; i<8; i++) data[i]^=T1[index++];
}
// -- cSystemSeca ---------------------------------------------------------------
class cSystemSeca : public cSystem, private cSeca {
private:
cSeca2Prov *sp, *spL;
int emmLenCnt;
cDes des;
cRSA rsa;
//
bool GetSeca2Prov(int provId, cSeca2Prov * &sp);
bool Process0FNano(int count, unsigned char *hashDW, unsigned char *PK, const unsigned char *T1, const unsigned char *T2);
bool Process51Nano(unsigned char *CW, const unsigned char *PermData, const unsigned char *hashDW, const unsigned char *T1, const unsigned char *T2, int provId);
void Crypto51Nano(unsigned char *data, const unsigned char *key, const unsigned char crypto, const unsigned char mode);
void Permute(unsigned char *data, const unsigned char *pdata, const unsigned char *P);
public:
cSystemSeca(void);
virtual ~cSystemSeca();
virtual bool ProcessECM(const cEcmInfo *ecm, unsigned char *data);
virtual void ProcessEMM(int pid, int caid, unsigned char *buffer);
};
cSystemSeca::cSystemSeca(void)
:cSystem(SYSTEM_NAME,SYSTEM_PRI),
des(secaPC1,secaPC2)
{
sp=spL=0; emmLenCnt=0;
hasLogger=true;
}
cSystemSeca::~cSystemSeca()
{
delete sp;
delete spL;
}
bool cSystemSeca::GetSeca2Prov(int provId, cSeca2Prov * &sp)
{
if(!sp || !sp->Matches(provId)) {
delete sp;
sp=cSeca2Providers::GetProv(provId);
}
return sp!=0;
}
bool cSystemSeca::ProcessECM(const cEcmInfo *ecmD, unsigned char *data)
{
bool SE=false;
unsigned char *ecm;
const int msgLen=cParseSeca::Payload(data,(const unsigned char **)&ecm);
const int keyNr=cParseSeca::KeyNr(data);
if(keyNr&0x80) {
dse(printf("system-seca: Super Encryption enabled\n"))
SE=true;
if(!GetSeca2Prov(ecmD->provId,sp)) {
if(doLog) d(printf("system-seca: Seca2 provider %04x not supported\n",ecmD->provId))
return false;
}
}
dse(printf("system-seca: ECM:"); HexDump(data,SCT_LEN(data)))
if(ecm[0]==0x10) {
if(msgLen<0x5c) {
if(doLog) ds(printf("system-seca: ECM length too small (%d)\n",msgLen))
return false;
}
if(SE) {
dse(printf("system-seca: ECM before SSE data modification :"); HexDump(ecm+(msgLen-0x5a),0x5a))
sp->PreSSE(ecm,msgLen-0x5a);
dse(printf("system-seca: ECM after SSE data modification :"); HexDump(ecm+(msgLen-0x5a),0x5a))
}
const int rsaKeynr=(ecm[1]&0x0F)+'0';
cBN exp, mod;
cPlainKey *rsaKey;
if(!(rsaKey=keys.FindKey('S',ecmD->provId,MBC('E',rsaKeynr),-1))) {
if(doLog) d(printf("system-seca: missing %04x E%c key\n",ecmD->provId,rsaKeynr))
return false;
}
rsaKey->Get(exp);
if(!(rsaKey=keys.FindKey('S',ecmD->provId,MBC('M',rsaKeynr),-1))) {
if(doLog) d(printf("system-seca: missing %04x M%c key\n",ecmD->provId,rsaKeynr))
return false;
}
rsaKey->Get(mod);
dse(printf("system-seca: ECM before RSA decrypt :"); HexDump(ecm+(msgLen-0x5a),0x5a))
if(rsa.RSA(ecm+(msgLen-0x5a),ecm+(msgLen-0x5a),0x5a,exp,mod)!=0x5a) {
ds(printf("system-seca: RSA decrypt failed\n"))
return false;
}
dse(printf("system-seca: ECM after RSA decrypt :"); HexDump(ecm+(msgLen-0x5a),0x5a))
if(SE) { // PostSSE needed
const int hashPtr=msgLen-ecm[msgLen-1]-9;
if(hashPtr>=msgLen-9 || ecm[hashPtr]!=0x82) {
ds(printf("system-seca: RSA decrypt failed, signature pointer not found\n"))
return false;
}
dse(printf("system-seca: ECM before SSE result modification :"); HexDump(ecm+(msgLen-0x5a),0x5a))
sp->PostSSE(ecm,hashPtr);
dse(printf("system-seca: ECM after SSE result modification :"); HexDump(ecm+(msgLen-0x5a),0x5a))
}
}
const unsigned char *T1=T1_S1, *T2=T2_S1;
int decrLen=msgLen;
if(SE) {
if(!(T1=sp->T1(KEY2INDEX(keyNr))) ||
!(T2=sp->T2(KEY2INDEX(keyNr)))) return false;
decrLen-=ecm[msgLen-1]; if(decrLen<8) return false;
}
bool key8=!(cParseSeca::SysMode(data)&0x10);
cPlainKey *pk=0;
cKeySnoop ks(this,'S',ecmD->provId,keyNr&0x0F);
while((pk=keys.FindKey('S',ecmD->provId,keyNr&0x0F,key8?8:16,pk))) {
unsigned char buff[256];
memcpy(buff,ecm,sizeof(buff)); // if decoding fails we need the original data
unsigned char PK[16], signature[20];
pk->Get(PK);
if(key8) memcpy(&PK[8],&PK[0],8); // duplicate key
if(SE) {
sp->CalcSHASignature(buff,decrLen-8,signature);
dse(printf("system-seca: signature before encrypt :"); HexDump(signature,8))
sp->SignatureMod(signature,PK);
Encrypt(signature,PK,T1,T2);
dse(printf("system-seca: signature after encrypt :"); HexDump(signature,8))
if(sp->DoSigCheck() && memcmp(signature,&buff[decrLen-8],8)) {
dse(printf("system-seca: signature check failed before SE decrypt\n"))
continue;
}
dse(printf("system-seca: ECM before SE decrypt :"); HexDump(buff+2,msgLen-2))
if(!sp->DecryptSE(buff+2,PK,msgLen-2,8,T1,T2)) {
dse(printf("system-seca: SE decrypt failed\n"))
continue;
}
dse(printf("system-seca: ECM after SE decrypt :"); HexDump(buff+2,msgLen-2))
}
else {
CalcSignature(buff,decrLen-8,signature,PK,T1,T2);
}
unsigned char hashDW[28]; // actually 16 bytes used for processing, but SHA needs more
unsigned char *cCW=0;
const unsigned char *nano51Data=0;
int nr0F=0;
for(int i=0 ; i<decrLen; ) {
int param=buff[i++];
int extra=(param >> 4) & 0x0f;
switch(extra) {
case 0x0d: extra=0x10; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -