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

📄 seca.c

📁 这是一个LINUX环境的 VDR 插件源代码,可支持Irdeto, Seca, Viaccess, Nagra, Conax & Cryptoworks等CA系统的读卡、共享等操作。
💻 C
📖 第 1 页 / 共 4 页
字号:
        }      HEXDUMP(L_SYS_VERBOSE,buff+2,msgLen-2,"ECM before SE decrypt :");      if(!sp->DecryptSE(buff+2,PK,msgLen-2,8,T1,T2)) {        PRINTF(L_SYS_VERBOSE,"SE decrypt failed");        continue;        }      HEXDUMP(L_SYS_VERBOSE,buff+2,msgLen-2,"ECM after SE decrypt :");      }    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;        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)) {             PRINTF(L_SYS_VERBOSE,"signature check failed after decrypt");            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)) {          LDUMP(L_SYS_VERBOSE,cCW,16,"crypted CW :");          Decrypt(&cCW[0],PK,T1,T2); Decrypt(&cCW[8],PK,T1,T2);          LDUMP(L_SYS_VERBOSE,cCW,16,"decrypted CW :");          if(SE) {            LDUMP(L_SYS_VERBOSE,cCW,16,"decrypted CW before modification :");            sp->PostCW(cCW);            LDUMP(L_SYS_VERBOSE,cCW,16,"decrypted CW after modification :");            }          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];  LDUMP(L_SYS_VERBOSE,hashDW,16,"0f: initial hashDW:");  LDUMP(L_SYS_VERBOSE,PK,16,"0f: PK:");  while(count--) {    unsigned char buffA[8];    swap8_4(hashDW);    memcpy(buffA,hashDW,8);    Decrypt(hashDW,PK,sp->T1(0),sp->T2(0));    LDUMP(L_SYS_VERBOSE,hashDW,16,"0f: hashDW:");    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);    LDUMP(L_SYS_VERBOSE,buffE,8,"0f: buffE:");    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);    LDUMP(L_SYS_VERBOSE,buffC,16,"0f: buffC:");    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;      }    PRINTF(L_SYS_VERBOSE,"0f: off=%04x",off);    memcpy(buffB,buffE,8);    Decrypt(buffB,buffC,&MT[off],&MT[off+256]);    LDUMP(L_SYS_VERBOSE,buffB,8,"0f: buffB after 1st decr:");    xxor(buffB,8,buffB,buffE);    LDUMP(L_SYS_VERBOSE,buffB,8,"0f: buffB after xor:");    Decrypt(buffB,PK,T1,T2);    LDUMP(L_SYS_VERBOSE,buffB,8,"0f: buffB after 2nd decr:");    xxor(hashDW,8,buffA,buffB);    }  for(int i=0; i<8; ++i) {    PK[i] = buffB[i];    PK[i+8] = ~sn8(buffB[i]);    }  LDUMP(L_SYS_VERBOSE,hashDW,16,"0f: hashDW:");  LDUMP(L_SYS_VERBOSE,PK,16,"0f: new PK:");  return true;}void cSystemSeca::Crypto51Nano(unsigned char *data, const unsigned char *key, const unsigned char crypto, const unsigned char mode){  switch(crypto) {    case 0: // Xor      PRINTF(L_SYS_VERBOSE,"51: XOR crypto selected");      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);      PRINTF(L_SYS_VERBOSE,"51: SECA crypto selected: %s",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)      PRINTF(L_SYS_VERBOSE,"51: DES crypto selected: %s",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      PRINTF(L_SYS_VERBOSE,"51: Additional crypto selected: %s",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) {    PRINTF(L_SYS_VERBOSE,"51: failed to get permutation table");    return false;    }  unsigned char buffF[8], buffG[8];  switch(pMode) {    case 0x00:    case 0x01:      {      // Permutation 1      Permute(buffF,PermData,PT->P1);      LDUMP(L_SYS_VERBOSE,buffF,8,"51: buffF:");      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);      LDUMP(L_SYS_VERBOSE,buffG,8,"51: buffG:");      // 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];      LDUMP(L_SYS_VERBOSE,buff1,20,"51: permuted hashDW:");      for(int i=0; i<20; i++)        buff1[i+24]=buff1[i+44]=buff1[i+68]=buff1[i+88]=buff1[i+108]=buff1[i];      LBSTARTF(L_SYS_VERBOSE);      LBPUT("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;        LBPUT(" %02x",t);        }      LBEND();      HEXDUMP(L_SYS_VERBOSE,buff1,128,"51: buff1:");      HEXDUMP(L_SYS_VERBOSE,buff2,64,"51: buff2:");      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;        }      HEXDUMP(L_SYS_VERBOSE,buff1,128,"51: buff1 rsa prepped:");      // RSA decrypt      {      cBN exp, mod;      cPlainKey *pk;      if(!(pk=keys.FindKey('S',provId,MBC3('E','9',N51_MAGIC),-1))) {        if(doLog) PRINTF(L_SYS_KEY,"missing %04x N51 E9 key",provId);        return false;        }      pk->Get(exp);      if(!(pk=keys.FindKey('S',provId,MBC3('M','9',N51_MAGIC),-1))) {        if(doLog) PRINTF(L_SYS_KEY,"missing %04x N51 M9 key",provId);        return false;        }      pk->Get(mod);      if(rsa.RSA(buff1,buff1,128,exp,mod)<9) return false;      HEXDUMP(L_SYS_VERBOSE,buff1,128,"51: buff1 rsa decrypted:");      }      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;                }      LDUMP(L_SYS_VERBOSE,buff1,9,"51: buff1 after sumalgo:");      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:      PRINTF(L_SYS_VERBOSE,"51: data incorrect or proccessing not needed");      return false;    }  LDUMP(L_SYS_VERBOSE,buffG,8,"51: cryptokey:");  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);  LDUMP(L_SYS_VERBOSE,hashDW,8,"51: cryptokey:");  Crypto51Nano(CW,hashDW,(PermData[1]>>4)&0x03,PermData[0]&0x40);  LDUMP(L_SYS_VERBOSE,CW,16,"51: new encrypted CW:");  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)      PRINTF(L_SYS_EMM,"length of EMM does not match (%02x <> 55/63)%s",msgLen,emmLenCnt==5 ? " ....":"");    return;    }  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;      }    }  for(cSecaCardInfo *ci=Scards.First(); ci; ci=Scards.Next(ci)) {    if(ci->MatchEMM(buffer) || (CheckNull(ci->sa,sizeof(ci->sa)) && ci->MatchID(buffer))) {      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[msgLen], 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],8)) 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;          }        }      char str[20],str2[20],str3[20];      if(sigOk) {        LBSTARTF(L_SYS_EMM);        LBPUT("ID %s SA %s",HexStr(str,SID(buffer),2),HexStr(str2,SA(buffer),3));        LBPUT(" - OK (CI ID %s SA %s KEY01 %s)",HexStr(str,ci->provId,2),HexStr(str2,ci->sa,3),HexStr(str3,ci->key,8));        for(unsigned int i=0 ; i<numKeys ; i++) {          Decrypt(key[i],MK,T1,T2);          LBPUT(" KEY %02x %s",keyN[i],HexStr(str,key[i],8));          FoundKey();          if(keys.NewKey('S',provId,keyN[i],key[i],8)) NewKey();         }        LBEND();        cLoaders::SaveCache();        break;        }      else if(!CheckNull(ci->sa,sizeof(ci->sa)))        PRINTF(L_SYS_EMM,"ID %s SA %s - FAIL",HexStr(str,SID(buffer),2),HexStr(str2,SA(buffer),3));      }    }  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 + -