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

📄 seca.cpp

📁 DVB-S的softcam源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
        case 0x0e: extra=0x18; break;
        case 0x0f: extra=0x20; break;
        }
      switch(param) {
        case 0x0f:
          if(SE) nr0F++;
          break;
        case 0x51:
          if(SE) nano51Data=&buff[i];
          break;
        case 0xd1:
          cCW=&buff[i];
          if(SE) {
            sp->CalcSHASignature(buff,i,hashDW,false);
            memcpy(&hashDW[20],hashDW,8);
            Decrypt(&hashDW[20],PK,sp->T1(0),sp->T2(0));
            sp->CalcSHASignature(hashDW,28,hashDW,false);
            }
          break;
        case 0x82:
          if((!SE || sp->DoSigCheck()) && memcmp(&buff[i],signature,8)) { 
            dse(printf("system-seca: signature check failed after decrypt\n"))
            cCW=0; i=decrLen;
            }
          break;
        }
      i+=extra;
      }
    if(cCW) {
      if(!nr0F || Process0FNano(nr0F,hashDW,PK,T1,T2)) {
        if(SE) sp->PreCW(cCW);
        if(!nano51Data || Process51Nano(cCW,nano51Data,hashDW,T1,T2,ecmD->provId)) {
          dse(printf("system-seca: crypted CW :"); HexDump(cCW,16))
          Decrypt(&cCW[0],PK,T1,T2); Decrypt(&cCW[8],PK,T1,T2);
          dse(printf("system-seca: decrypted CW :"); HexDump(cCW,16))
          if(SE) {
            dse(printf("system-seca: decrypted CW before modification :"); HexDump(cCW,16))
            sp->PostCW(cCW);
            dse(printf("system-seca: decrypted CW after modification :"); HexDump(cCW,16))
            }
          memcpy(cw,cCW,16);
          ks.OK(pk);
          return true;
          }
        }
      }
    }
  return false;
}

bool cSystemSeca::Process0FNano(int count, unsigned char *hashDW, unsigned char *PK, const unsigned char *T1, const unsigned char *T2)
{
  const unsigned char *MT=sp->MT();
  unsigned char buffB[8];

  dse(printf("0f: initial hashDW:"); HexDump(hashDW,16))
  dse(printf("0f: PK:"); HexDump(PK,16))
  while(count--) {
    unsigned char buffA[8];
    swap8_4(hashDW);
    memcpy(buffA,hashDW,8);
    Decrypt(hashDW,PK,sp->T1(0),sp->T2(0));
    dse(printf("0f: hashDW:"); HexDump(hashDW,16))

    unsigned char buffE[8];
    int off=WORD(hashDW,0,0x3FFF);
    xxor(buffE,8,&MT[off],&MT[0x3FFF-off]);
    xxor(buffE,8,&MT[( ((buffE[0] ^ hashDW[6])<<8)
                     +  buffE[7] ^ hashDW[7]     )&0x3FFF],buffE);
    dse(printf("0f: buffE:"); HexDump(buffE,8))

    unsigned char buffC[16];
    off=WORD(hashDW,2,0x3FFF);
    xxor(buffC,16,&MT[off],&MT[0x3FFF-off]);
    xxor(buffC,16,&MT[( ((hashDW[6] ^ buffC[0])<<8)
                      + (hashDW[7] ^ buffC[15])   )&0x3FFF],buffC);
    dse(printf("0f: buffC:"); HexDump(buffC,16))

    off=WORD(hashDW,4,0x3FFF);
    for(int i=0; i<16; ++i) off=WORD(MT,off,0x3FFF);
    if(off+512 >= sp->MTSize()) {
      printf("BUG!!!: error: masking table overflow\n");
      return false;
      }
    dse(printf("0f: off=%04x\n",off))

    memcpy(buffB,buffE,8);
    Decrypt(buffB,buffC,&MT[off],&MT[off+256]);
    dse(printf("0f: buffB after 1st decr:"); HexDump(buffB,8))
    xxor(buffB,8,buffB,buffE);
    dse(printf("0f: buffB after xor:"); HexDump(buffB,8))
    Decrypt(buffB,PK,T1,T2);
    dse(printf("0f: buffB after 2nd decr:"); HexDump(buffB,8))
    xxor(hashDW,8,buffA,buffB);
    }

  for(int i=0; i<8; ++i) {
    PK[i] = buffB[i];
    PK[i+8] = ~sn8(buffB[i]);
    }
  dse(printf("0f: hashDW:"); HexDump(hashDW,16))
  dse(printf("0f: new PK:"); HexDump(PK,16))
  return true;
}

void cSystemSeca::Crypto51Nano(unsigned char *data, const unsigned char *key, const unsigned char crypto, const unsigned char mode)
{
  dse(printf("51: ")); 
  switch(crypto) {
    case 0: // Xor
      dse(printf("XOR crypto selected\n"))
      xxor(data+0,8,key,data+0); xxor(data+8,8,key,data+8);
      break;
    case 1: // Seca crypto, with 9x table, always!
      {
      unsigned char PK[16];
      const unsigned char *T1 = sp->T1(0);
      const unsigned char *T2 = sp->T2(0);
      memcpy(PK+0,key,8); memcpy(PK+8,key,8);
      dse(printf("SECA crypto selected: %s\n",mode?"decrypt":"encrypt"))
      if(mode) { Decrypt(data,PK,T1,T2); Decrypt(data+8,PK,T1,T2); }
      else     { Encrypt(data,PK,T1,T2); Encrypt(data+8,PK,T1,T2); }
      break;
      }
    case 2: // DES crypto (Modified PC1,PC2)
      dse(printf("DES crypto selected: %s\n",mode?"decrypt":"encrypt"))
      if(mode) { des.Des(data,key,SECA_DES_DECR); des.Des(data+8,key,SECA_DES_DECR); }
      else     { des.Des(data,key,SECA_DES_ENCR); des.Des(data+8,key,SECA_DES_ENCR); }
      break;
    case 3: // Additional Algo
      dse(printf("Additional crypto selected: %s\n",mode?"decrypt":"encrypt"))
      AdditionalAlgo(data,key,mode); AdditionalAlgo(data+8,key,mode);
      break;
    }
}

bool cSystemSeca::Process51Nano(unsigned char *CW, const unsigned char *PermData, const unsigned char *hashDW, const unsigned char *T1, const unsigned char *T2, int provId)
{
  const int pMode=(PermData[0]&0x3F)-1;
  const struct Perm *PT=sp->P(pMode);
  if(!PT) {
    dse(printf("51: failed to get permutation table\n"))
    return false;
    }
  unsigned char buffF[8], buffG[8];
  switch(pMode) {
    case 0x00:
    case 0x01:
      {
      // Permutation 1
      Permute(buffF,PermData,PT->P1);
      dse(printf("51: buffF:"); HexDump(buffF,8))
      xxor(buffG,8,buffF,hashDW);
      const int addAlgoMode=(PermData[0]&1)^1;
      for(int i=(PermData[1]&0x0f); i>0; i--) AdditionalAlgo(buffG,hashDW+8,addAlgoMode);
      // Permutation 2
      Permute(buffF,PermData,PT->P2);
      xxor(buffG,8,buffF,buffG);
      dse(printf("51: buffG:"); HexDump(buffG,8))
      // Permutation 3
      Permute(buffF,PermData,PT->P3);
      xxor(buffG,8,buffF,buffG);
      // Permutation 4
      Permute(buffF,PermData,PT->P4);
      xxor(buffG,8,buffF,buffG);
      break;
      }
    case 0x08:
      {
      unsigned char buff1[128], buff2[64], buff3[9];
      // prepare buffers for rsa data
      for(int i=0; i<20; i++)
        buff1[i]=buff2[i]=buff2[i+20]=buff2[i+40]=hashDW[i];
      memcpy(buff3,PermData+2,3);
      for(int i=0; i<8; i++) buff1[i] = buff3[PT->P1[i]-2] ^= buff1[i];
      dse(printf("51: permuted hashDW:"); HexDump(buff1,20))
      for(int i=0; i<20; i++)
        buff1[i+24]=buff1[i+44]=buff1[i+68]=buff1[i+88]=buff1[i+108]=buff1[i];
      dse(printf("51: nano51Data:"))
      for(int i=0; i<4; i++) {
        unsigned char t=PermData[PT->P3[i]];
        if(PT->P3[i]==1) t&=0x0F;
        buff1[i+20]=buff1[i+64]=buff2[i+60]=t;
        dse(printf(" %02x",t))
        }
      dse(printf("\n"))
      dse(printf("51: buff1:"); HexDump(buff1,128))
      dse(printf("51: buff2:"); HexDump(buff2,64))

      memcpy(buff3,buff1,9);
      for(int j=0; j<64; j++) { // XOR even with buff2, odd with 0xFF
        buff1[ j*2   ] ^= buff2[j];
        buff1[(j*2)+1] ^= 0xFF;
        }
      dse(printf("51: buff1 rsa prepped:"); HexDump(buff1,128))

      // RSA decrypt
      {
      cBN exp, mod;
      cPlainKey *pk;
      if(!(pk=keys.FindKey('S',provId,MBC3('E','9',N51_MAGIC),-1))) {
        if(doLog) d(printf("system-seca: missing %04x N51 E9 key\n",provId))
        return false;
        }
      pk->Get(exp);
      if(!(pk=keys.FindKey('S',provId,MBC3('M','9',N51_MAGIC),-1))) {
        if(doLog) d(printf("system-seca: missing %04x N51 M9 key\n",provId))
        return false;
        }
      pk->Get(mod);
      if(rsa.RSA(buff1,buff1,128,exp,mod)<9) return false;
      dse(printf("51: buff1 rsa decrypted:"); HexDump(buff1,128))
      }

      unsigned int sum=0;
      for(int j=0; j<9; j++) {
        unsigned int nextSum=(buff1[j]&0x80) ? 1:0;
        buff1[j]=(sum+2*buff1[j])^buff3[j];
        sum=nextSum;        
        }
      dse(printf("51: buff1 after sumalgo:"); HexDump(buff1,9))

      memcpy(buffG,buff1,8);
      memcpy(buff3,PermData+2,3);
      for(int i=0; i<8; i++) buffG[i] = buff3[PT->P2[i]-2] ^= buffG[i];
      break;
      }

    default:
      dse(printf("51: data incorrect or proccessing not needed\n"))
      return false;
    }
  dse(printf("51: cryptokey:"); HexDump(buffG,8))
  Crypto51Nano(CW,buffG,(PermData[1]>>6)&3,PermData[0]&0x80);
  // Final Permutation
  Permute(buffF,PermData,sp->FP());
  xxor(CW+0,8,CW+0,buffF); xxor(CW+8,8,CW+8,buffF);
  dse(printf("51: cryptokey:"); HexDump(hashDW,8))
  Crypto51Nano(CW,hashDW,(PermData[1]>>4)&0x03,PermData[0]&0x40);
  dse(printf("51: new encrypted CW:"); HexDump(CW,16))
  return true;
}

void cSystemSeca::Permute(unsigned char *data, const unsigned char *pdata, const unsigned char *P)
{
  for(int i=7; i>=0; i--) data[i] = P[i] ? pdata[P[i]] : 0;
}

void cSystemSeca::ProcessEMM(int pid, int caid, unsigned char *buffer)
{
  if(buffer[0]!=0x84) return; // we only support shared updates

  int msgLen=cParseSeca::CmdLen(buffer);
  if(msgLen!=0x55 && msgLen!=0x63) {
    if(++emmLenCnt<=5)
      dl(printf("system-seca: length of EMM does not match (%02x <> 55/63)%s\n",msgLen,emmLenCnt==5 ? " ....":""))
    return;
    }
  ds(emmLenCnt=0)
  unsigned char *emm;
  msgLen=cParseSeca::Payload(buffer,(const unsigned char **)&emm);
  int provId=cParseSeca::ProvId(buffer);
  bool SE=false;
  const unsigned char *T1=T1_S1, *T2=T2_S1;
  int decrLen=msgLen;
  if(emm[0]==0x10) { // de-SSE
    const int rsaKeynr = emm[1]+'0';
    cPlainKey *pk;
    cBN exp, mod;
    
    if(!(pk=keys.FindKey('S',provId,MBC3('E',rsaKeynr,EMM_MAGIC),-1))) return;
    pk->Get(exp);
    if(!(pk=keys.FindKey('S',provId,MBC3('M',rsaKeynr,EMM_MAGIC),-1))) return;
    pk->Get(mod);
 
    if(rsa.RSA(emm+2,emm+2,msgLen-2,exp,mod)!=msgLen-2) return;
    const int keyNr=cParseSeca::KeyNr(buffer);
    if(keyNr&0x80) {
      SE=true;
      decrLen-=emm[msgLen-1]; 
      if(!GetSeca2Prov(provId,spL) ||
         !(T1=spL->T1(KEY2INDEX(keyNr))) ||
         !(T2=spL->T2(KEY2INDEX(keyNr))) ||
         decrLen<8) return;
      }
    }

#ifdef DEBUG_LOG
  bool first=true;
#endif
  for(cSecaCardInfo *ci=Scards.First(); ci; ci=Scards.Next(ci)) {
    if(ci->MatchEMM(buffer) || (CheckNull(ci->sa,sizeof(ci->sa)) && ci->MatchID(buffer))) {
#ifdef DEBUG_LOG
      char str[20],str2[20],str3[20];
      if(first) {
        printf("\rID %s SA %s",HexStr(str,SID(buffer),2),HexStr(str2,SA(buffer),3));
        first=false;
        }
#endif
      unsigned char MK[16];
      if(cParseSeca::SysMode(buffer)&0x10) {
        if(ci->KeySize()!=16) continue; // don't bother
        memcpy(&MK[0],ci->key,16);
        }
      else {
        memcpy(&MK[0],ci->key,8);
        memcpy(&MK[8],ci->key,8);
        }

      unsigned char buff[256], signature[20];
      memcpy(buff,emm,sizeof(buff)); // if decoding fails we need the original de-sse'd data

      if(!SE) {
        for(int i=0 ; i<=64 && i<msgLen-8; i+=8) Decrypt(&buff[i],MK,T1,T2);
        CalcSignature(buff,decrLen-8,signature,MK,T1,T2);
        }
      else {
        spL->CalcSHASignature(buff,decrLen-8,signature);
        Encrypt(signature,MK,T1,T2);
        if(memcmp(signature,&buff[decrLen-8],8) ||
           !spL->DecryptSE(buff+2,MK,msgLen-2,0,T1,T2)) continue;
        }

      unsigned char keyN[4], *key[4];
      int pos, len;
      unsigned int numKeys=0;
      bool sigOk=false;
      for(pos=0 ; pos<decrLen ; pos+=len) {
        int cmd=buff[pos++];
        len=(cmd>>4)&0x0f;
        switch(len) {
          case 0x0b: len=0x0e; break;
          case 0x0d: len=0x10; break;
          case 0x0e: len=0x18; break;
          case 0x0f: len=0x20; break;
          }
        switch(cmd) {
          case 0x82: // signature
            if(!memcmp(signature,&buff[pos],sizeof(signature))) sigOk=true;
            pos=decrLen;
            break;
          case 0x90: // new primary key
            if(numKeys<sizeof(keyN)) {
              keyN[numKeys]=buff[pos] & 0x0f;
              key[numKeys]=&buff[pos+1];
              numKeys++;
              }
            break;
          }
        }
      if(sigOk) {
        dl(printf(" - OK (CI ID %s SA %s KEY01 %s)",HexStr(str,ci->provId,2),HexStr(str2,ci->sa,3),HexStr(str3,ci->key,8)))
#ifdef DEBUG_LOG_FILE
        FILE *f=LogStart();
        if(f) {
          char str[64],str2[20],str3[20];
          fprintf(f,"ID %s SA %s -  OK ",HexStr(str,SID(buffer),2),HexStr(str2,SA(buffer),3));
          fprintf(f," with CI ID %s SA %s KEY01 %s\n",HexStr(str,ci->provId,2),HexStr(str2,ci->sa,3),HexStr(str3,ci->key,8));
          fprintf(f,"     cmds:");
          for(pos=0 ; pos<decrLen ; pos+=len) {
            int cmd=buff[pos++];
            len=(cmd>>4)&0x0f;
            switch(len) {
              case 0x0b: len=0x0e; break;
              case 0x0d: len=0x10; break;
              case 0x0e: len=0x18; break;
              case 0x0f: len=0x20; break;
              }
            fprintf(f," 0x%02x/%d",cmd,len);
            }
          fprintf(f,"\n");
          for(int i=0 ; i<(decrLen+2) ; i+=16)
            fprintf(f,"     %02x %s\n",i,HexStr(str,&buff[i],i+16>decrLen?decrLen-i:16));
          LogEnd(f);
          }
#endif
        for(unsigned int i=0 ; i<numKeys ; i++) {
          Decrypt(key[i],MK,T1,T2);
          dl(printf(" KEY %02x %s",keyN[i],HexStr(str,key[i],8)))
          cSoftCAM::FoundKey();
          if(keys.NewKey('S',provId,keyN[i],key[i],8)) {
            cSoftCAM::NewKey();
#ifdef DEBUG_LOG_FILE
            FILE *f=LogStart();
            if(f) {
              char str[20];
              fprintf(f,"New key %02x %s\n",keyN[i],HexStr(str,key[i],8));
              LogEnd(f);
              }
#endif
            }
         }
        cSoftCAM::Save();

        dl(printf("\n"))
        break;
        }
      else if(!CheckNull(ci->sa,sizeof(ci->sa))) {
#ifdef DEBUG_LOG
        printf(" - FAIL\n");
        first=true;
#endif
#ifdef DEBUG_LOG_FILE
        FILE *f=LogStart();
        if(f) {
          char str[20],str2[20],str3[20];
          fprintf(f,"ID %s SA %s - FAIL",HexStr(str,SID(buffer),2),HexStr(str2,SA(buffer),3));
          fprintf(f," with CI ID %s SA %s KEY01 %s\n",HexStr(str,ci->provId,2),HexStr(str2,ci->sa,3),HexStr(str3,ci->key,8));
          LogEnd(f);
          }
#endif
        }
      dl(fflush(stdout))
      }
    }
  return;
}

// -- cSystemLinkSeca ----------------------------------------------------------

class cSystemLinkSeca : public cSystemLink {
public:
  cSystemLinkSeca(void);
  virtual bool CanHandle(unsigned short SysId);
  virtual cSystem *Create(void) { return new cSystemSeca; }
  virtual bool Init(const char *cfgdir);
  };

static cSystemLinkSeca staticInit;

cSystemLinkSeca::cSystemLinkSeca(void)
:cSystemLink(SYSTEM_NAME,SYSTEM_PRI)
{
  Feature.NeedsKeyFile();
}

bool cSystemLinkSeca::CanHandle(unsigned short SysId)
{
  SysId&=SYSTEM_MASK;
  return SYSTEM_CAN_HANDLE(SysId);
}

bool cSystemLinkSeca::Init(const char *cfgdir)
{
  Scards.Load(cfgdir,SYSTEM_NAME,"Seca.KID");
  return true;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -