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

📄 nagra2.c

📁 这是一个LINUX环境的 VDR 插件源代码,可支持Irdeto, Seca, Viaccess, Nagra, Conax & Cryptoworks等CA系统的读卡、共享等操作。
💻 C
📖 第 1 页 / 共 2 页
字号:
  // Calculate P  idata[0] |= 0x80;  idata[47] |= 1;  BN_bin2bn(idata,48,p);  BN_add_word(p,(key[21] << 5 ) | ((key[22] & 0xf0) >> 3));  // Calculate Q  idata[48] |= 0x80;  idata[95] |= 1;  BN_bin2bn(idata+48,48,q);  BN_add_word(q,(key[22] &0xf << 9 ) | (key[23]<<1));}bool cNagra2::Signature(const unsigned char *vkey, const unsigned char *sig, const unsigned char *msg, int len){  unsigned char buff[16];  memcpy(buff,vkey,sizeof(buff));  for(int i=0; i<len; i+=8) {    IdeaKS ks;    idea.SetEncKey(buff,&ks);    memcpy(buff,buff+8,8);    idea.Encrypt(msg+i,8,buff+8,&ks,0);    xxor(&buff[8],8,&buff[8],msg+i);    }  buff[8]&=0x7F;  return (memcmp(sig,buff+8,8)==0);}bool cNagra2::DecryptECM(const unsigned char *in, unsigned char *out, const unsigned char *key, int len, const unsigned char *vkey, BIGNUM *m){  int sign=in[0] & 0x80;  if(rsa.RSA(out,in+1,64,pubExp,m)<=0) {    PRINTF(L_SYS_CRYPTO,"first RSA failed (ECM)");    return false;    }  out[63]|=sign; // sign adjustment  if(len>64) memcpy(out+64,in+65,len-64);  if(in[0]&0x04) {    unsigned char tmp[8];    DES_key_schedule ks1, ks2;     RotateBytes(tmp,&key[0],8);    DES_key_sched((DES_cblock *)tmp,&ks1);    RotateBytes(tmp,&key[8],8);    DES_key_sched((DES_cblock *)tmp,&ks2);    memset(tmp,0,sizeof(tmp));    for(int i=7; i>=0; i--) RotateBytes(out+8*i,8);    DES_ede2_cbc_encrypt(out,out,len,&ks1,&ks2,(DES_cblock *)tmp,DES_DECRYPT);    for(int i=7; i>=0; i--) RotateBytes(out+8*i,8);    }   else idea.Decrypt(out,len,key,0);   RotateBytes(out,64);  if(rsa.RSA(out,out,64,pubExp,m,false)<=0) {    PRINTF(L_SYS_CRYPTO,"second RSA failed (ECM)");    return false;    }  if(vkey && !Signature(vkey,out,out+8,len-8)) {    PRINTF(L_SYS_CRYPTO,"signature failed (ECM)");    return false;    }  return true;}bool cNagra2::DecryptEMM(const unsigned char *in, unsigned char *out, const unsigned char *key, int len, const unsigned char *vkey, BIGNUM *m){  int sign=in[0]&0x80;  if(rsa.RSA(out,in+1,96,pubExp,m)<=0) {    PRINTF(L_SYS_CRYPTO,"first RSA failed (EMM)");    return false;    }  out[95]|=sign; // sign adjustment  cBN exp;  if(in[0]&0x08) {    // standard IDEA decrypt    if(len>96) memcpy(out+96,in+97,len-96);    idea.Decrypt(out,len,key,0);    BN_set_word(exp,3);    }  else {    // private RSA key expansion    CreateRSAPair(key,0,exp,m);    }  RotateBytes(out,96);  if(rsa.RSA(out,out,96,exp,m,false)<=0) {    PRINTF(L_SYS_CRYPTO,"second RSA failed (EMM)");    return false;    }  if(vkey && !Signature(vkey,out,out+8,len-8)) {    PRINTF(L_SYS_CRYPTO,"signature failed (EMM)");    return false;    }  return true;}// -- cSystemNagra2 ------------------------------------------------------------class cSystemNagra2 : public cSystem, protected cNagra2 {private:  int lastEcmId, lastEmmId;  cN2Prov *ecmP, *emmP;public:  cSystemNagra2(void);  ~cSystemNagra2();  virtual bool ProcessECM(const cEcmInfo *ecm, unsigned char *data);  virtual void ProcessEMM(int pid, int caid, unsigned char *buffer);  };cSystemNagra2::cSystemNagra2(void):cSystem(SYSTEM_NAME,SYSTEM_PRI){  hasLogger=true;  lastEcmId=lastEmmId=0; ecmP=emmP=0;}cSystemNagra2::~cSystemNagra2(){  delete ecmP;  delete emmP;}bool cSystemNagra2::ProcessECM(const cEcmInfo *ecm, unsigned char *data){  int cmdLen=data[4]-5;  int id=(data[5]*256)+data[6];  cTimeMs minTime;  if(id==0x4101) StartLog(ecm,0x1881); // D+ AU      if(cmdLen<64 || SCT_LEN(data)<cmdLen+10) {    if(doLog) PRINTF(L_SYS_ECM,"bad ECM message msgLen=%d sctLen=%d",cmdLen,SCT_LEN(data));    return false;    }  int keyNr=(data[7]&0x10)>>4;  cKeySnoop ks(this,'N',id,keyNr);  cPlainKey *pk;  cBN m1;  unsigned char ideaKey[16], vKey[16];  bool hasVerifyKey=false;  if(!(pk=keys.FindKey('N',id,MBC('M','1'),-1)))  {    if(doLog) PRINTF(L_SYS_KEY,"missing %04x M1 key",id);    return false;    }  pk->Get(m1);  if((pk=keys.FindKey('N',id,'V',sizeof(vKey)))) {    pk->Get(vKey);    hasVerifyKey=true;    }  else if(doLog && id!=lastEcmId) PRINTF(L_SYS_KEY,"missing %04x V key (non-fatal)",id);  if(!(pk=keys.FindKey('N',id,keyNr,sizeof(ideaKey)))) return false;  pk->Get(ideaKey);  unsigned char buff[256];  if(!DecryptECM(data+9,buff,ideaKey,cmdLen,hasVerifyKey?vKey:0,m1)) {    if(doLog) PRINTF(L_SYS_ECM,"decrypt of ECM failed (%04x)",id);    return false;    }  if((!ecmP && id!=lastEcmId) || (ecmP && !ecmP->CanHandle(id))) {    delete ecmP;    ecmP=cN2Providers::GetProv(id,N2FLAG_NONE);    if(ecmP) PRINTF(L_SYS_ECM,"provider %04x capabilities%s%s%s%s",id,                      ecmP->HasFlags(N2FLAG_MECM)    ?" MECM":"",                      ecmP->HasFlags(N2FLAG_Bx)      ?" Bx":"",                      ecmP->HasFlags(N2FLAG_POSTAU)  ?" POSTPROCAU":"",                      ecmP->HasFlags(N2FLAG_INV)     ?" INVCW":"");    }  lastEcmId=id;  int l=0, mecmAlgo=0;  LBSTARTF(L_SYS_ECM);  bool contFail=false;  for(int i=16; i<cmdLen-10 && l!=3; ) {    switch(buff[i]) {      case 0x10:      case 0x11:        if(buff[i+1]==0x09) {          int s=(~buff[i])&1;          mecmAlgo=buff[i+2]&0x60;          memcpy(cw+(s<<3),&buff[i+3],8);          i+=11; l|=(s+1);          }        else {          PRINTF(L_SYS_ECM,"bad length %d in CW nano %02x",buff[i+1],buff[i]);          i++;          }        break;      case 0x00:        i+=2; break;      case 0x13 ... 0x17:        i+=4; break;      case 0x30 ... 0x36:      case 0xB0:        i+=buff[i+1]+2;        break;      default:        if(!contFail) LBPUT("unknown ECM nano");        LBPUT(" %02x",buff[i]);        contFail=true;        i++;        continue;      }    LBFLUSH(); contFail=false;    }  LBEND();  if(l!=3) return false;  if(mecmAlgo>0) {    if(ecmP && ecmP->HasFlags(N2FLAG_MECM)) {      if(!ecmP->MECM(buff[15],mecmAlgo,cw)) return false;      }    else { PRINTF(L_SYS_ECM,"MECM for provider %04x not supported",id); return false; }    }  if(ecmP) ecmP->SwapCW(cw);  ks.OK(pk);  int i=minEcmTime-minTime.Elapsed();  if(i>0) cCondWait::SleepMs(i);  return true;}void cSystemNagra2::ProcessEMM(int pid, int caid, unsigned char *buffer){  int cmdLen=buffer[9]-5;  int id=buffer[10]*256+buffer[11];  if(cmdLen<96 || SCT_LEN(buffer)<cmdLen+15) {    PRINTF(L_SYS_EMM,"bad EMM message msgLen=%d sctLen=%d",cmdLen,SCT_LEN(buffer));    return;    }  int keyset=(buffer[12]&0x03);  int sel=(buffer[12]&0x10)<<2;  int rsasel=(id==0x4101 || id==0x4001) ? 0:sel; // D+ hack  int sigsel=(buffer[13]&0x80)>>1;  cPlainKey *pk;  cBN n;  unsigned char ideaKey[24], vKey[16];  bool hasVerifyKey=false;  if(!(pk=keys.FindKey('N',id,MBC(N2_MAGIC,keyset+0x10+rsasel),96)))  {    PRINTF(L_SYS_EMM,"missing %04x NN %.02X RSA key (96 bytes)",id,keyset+0x10+rsasel);    return;    }  pk->Get(n);  if((pk=keys.FindKey('N',id,MBC(N2_MAGIC,0x03+sigsel),sizeof(vKey)))) {    pk->Get(vKey);    hasVerifyKey=true;    }  else if(id!=lastEmmId) PRINTF(L_SYS_EMM,"missing %04x NN %.02X signature key (non-fatal)",id,0x03+sigsel);  if(!(pk=keys.FindKey('N',id,MBC(N2_MAGIC,keyset),24))) {    if(!(pk=keys.FindKey('N',id,MBC(N2_MAGIC,keyset+sel),16))) {      PRINTF(L_SYS_EMM,"missing %04x NN %.02x IDEA key (24 or 16 bytes)",id,keyset+sel);      return;      }    memset(ideaKey+16,0,8);    }  pk->Get(ideaKey);  unsigned char emmdata[256];  if(!DecryptEMM(buffer+14,emmdata,ideaKey,cmdLen,hasVerifyKey?vKey:0,n)) {    PRINTF(L_SYS_EMM,"decrypt of EMM failed (%04x)",id);    return;    }  if((!emmP && id!=lastEmmId) || (emmP && !emmP->CanHandle(id))) {    delete emmP;    emmP=cN2Providers::GetProv(id,N2FLAG_NONE);    if(emmP) PRINTF(L_SYS_EMM,"provider %04x capabilities%s%s%s%s",id,                      emmP->HasFlags(N2FLAG_MECM)    ?" MECM":"",                      emmP->HasFlags(N2FLAG_Bx)      ?" Bx":"",                      emmP->HasFlags(N2FLAG_POSTAU)  ?" POSTPROCAU":"",                      emmP->HasFlags(N2FLAG_INV)     ?" INVCW":"");    }  lastEmmId=id;  HEXDUMP(L_SYS_RAWEMM,emmdata,cmdLen,"Nagra2 RAWEMM");  id=(emmdata[8]<<8)+emmdata[9];  LBSTARTF(L_SYS_EMM);  bool contFail=false;  for(int i=8+2+4+4; i<cmdLen-22; ) {    switch(emmdata[i]) {      case 0x42: // plain Key update        if(emmdata[i+2]==0x10 && (emmdata[i+3]&0xBF)==0x06 &&           (emmdata[i+4]&0xF8)==0x08 && emmdata[i+5]==0x00 && emmdata[i+6]==0x10) {          if(!emmP || emmP->PostProcAU(id,&emmdata[i])) {            FoundKey();            if(keys.NewKey('N',id,(emmdata[i+3]&0x40)>>6,&emmdata[i+7],16)) NewKey();            cLoaders::SaveCache();            }          }        i+=23;        break;      case 0xE0: // DN key update        if(emmdata[i+1]==0x25) {          FoundKey();          if(keys.NewKey('N',id,(emmdata[i+16]&0x40)>>6,&emmdata[i+23],16)) NewKey();          cLoaders::SaveCache();          }        i+=39;        break;      case 0x83: // change data prov. id        id=(emmdata[i+1]<<8)|emmdata[i+2];        i+=3;        break;      case 0xA4: // conditional (always no match assumed for now)        i+=emmdata[i+1]+2+4;        break;      case 0xA6:        i+=15;        break;      case 0xAE:        i+=11;        break;      case 0x13 ... 0x17: // Date        i+=4;        break;      case 0xB0 ... 0xBF: // Update with ROM CPU code        {        int bx=emmdata[i]&15;        if(!emmP || !emmP->HasFlags(N2FLAG_Bx)) {          PRINTF(L_SYS_EMM,"B%X for provider %04x not supported",bx,id);          i=cmdLen;          break;          }        int r;        if((r=emmP->ProcessBx(emmdata,cmdLen,i+1))>0)          i+=r;        else {          PRINTF(L_SYS_EMM,"B%X executing failed for %04x",bx,id);          i=cmdLen;          }        break;        }      case 0xE3: // Eeprom update        i+=emmdata[i+4]+4;        break;      case 0xE1:      case 0xE2:      case 0x00: // end of processing        i=cmdLen;        break;      default:        if(!contFail) LBPUT("unknown EMM nano");        LBPUT(" %02x",emmdata[i]);        contFail=true;        i++;        continue;      }    LBFLUSH(); contFail=false;    }  LBEND();}// -- cSystemLinkNagra2 --------------------------------------------------------static const tI18nPhrase Phrases2[] = {  { "Nagra2: AUXserver hostname",    "Nagra2: AUXserver Hostname",    "",    "",    "",    "",    "",    "",    "Nagra2: AUX-palvelimen osoite",    "",    "",    "",    "",  },  { "Nagra2: AUXserver port",    "Nagra2: AUXserver Port",    "",    "",    "",    "",    "",    "",    "Nagra2: AUX-palvelimen portti",    "",    "",    "",    "",  },  { "Nagra2: AUXserver password",    "Nagra2: AUXserver Passwort",    "",    "",    "",    "",    "",    "",    "Nagra2: AUX-palvelimen salasana",    "",    "",    "",    "",  },  { NULL }  };class cSystemLinkNagra2 : public cSystemLink {public:  cSystemLinkNagra2(void);  virtual bool CanHandle(unsigned short SysId);  virtual cSystem *Create(void) { return new cSystemNagra2; }  };static cSystemLinkNagra2 staticInitN2;cSystemLinkNagra2::cSystemLinkNagra2(void):cSystemLink(SYSTEM_NAME,SYSTEM_PRI){#ifdef HAS_AUXSRV  static const char allowed_chars[] = "0123456789abcdefghijklmnopqrstuvwxyz-.";  opts=new cOpts(SYSTEM_NAME,3);  opts->Add(new cOptStr("AuxServerAddr","Nagra2: AUXserver hostname",auxAddr,sizeof(auxAddr),allowed_chars));  opts->Add(new cOptInt("AuxServerPort","Nagra2: AUXserver port",&auxPort,0,65535));  opts->Add(new cOptStr("AuxServerPass","Nagra2: AUXserver password",auxPassword,sizeof(auxPassword),allowed_chars));  Feature.AddPhrases(Phrases2);#endif  Feature.NeedsKeyFile();}bool cSystemLinkNagra2::CanHandle(unsigned short SysId){  return ((SysId&SYSTEM_MASK)==SYSTEM_NAGRA && (SysId&0xFF)>0) ||          SysId==SYSTEM_NAGRA_BEV;}#endif //TESTER

⌨️ 快捷键说明

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