⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 seca.cpp

📁 DVB-S的softcam源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
    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 + -