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

📄 nagra1.c

📁 VDR softcam plugin 0.9.1
💻 C
📖 第 1 页 / 共 2 页
字号:
// -- cNagraDES ----------------------------------------------------------------class cNagraDES {private:  cDes des;protected:  void Decrypt(const unsigned char *data, const unsigned char *key, unsigned char *out, bool desmod=false);  void Crypt(const unsigned char *data, const unsigned char *key, unsigned char *out);  bool SigCheck(const unsigned char *block, const unsigned char *sig, const unsigned char *vkey, const int rounds);};void cNagraDES::Decrypt(const unsigned char *data, const unsigned char *key, unsigned char *out, bool desmod){  unsigned char cardkey[8];  memcpy(cardkey,key,8);  RotateBytes(cardkey,8);  memcpy(out,data,8);  if(!desmod) RotateBytes(out,8);  des.Des(out,cardkey,NAGRA_DES_DECR);  if(!desmod) RotateBytes(out,8);}void cNagraDES::Crypt(const unsigned char *data, const unsigned char *key, unsigned char *out){  unsigned char cardkey[8];  memcpy(cardkey,key,8);  RotateBytes(cardkey,8);  memcpy(out,data,8);  RotateBytes(out,8);  des.Des(out,cardkey,NAGRA_DES_ENCR);  RotateBytes(out,8);}bool cNagraDES::SigCheck(const unsigned char *block, const unsigned char *sig, const unsigned char *vkey, const int rounds){  unsigned char hash[8];  memcpy(hash,vkey,8);  for(int j=0; j<rounds; j++) {    unsigned char cr[8];    Crypt(block+j*8,hash,cr);    xxor(hash,8,cr,&block[j*8]);    }  return (0==memcmp(hash,sig,8));}// -- cNagra1 ------------------------------------------------------------------class cNagra1 : public cNagra, public cNagraDES {protected:  virtual void CreatePQ(const unsigned char *key, BIGNUM *p, BIGNUM *q);  bool DecryptECM(const unsigned char *in, unsigned char *out, const unsigned char *vkey, int len, BIGNUM *e1, BIGNUM *n1, BIGNUM *n2);  bool DecryptEMM(const unsigned char *in, unsigned char *out, const unsigned char *vkey, int len, BIGNUM *e1, BIGNUM *n1, BIGNUM *n2);  };bool cNagra1::DecryptECM(const unsigned char *in, unsigned char *out, const unsigned char *vkey, int len, BIGNUM *e1, BIGNUM *n1, BIGNUM *n2){  cBN result;  if(rsa.RSA(result,&in[2],len,pubExp,n2)<=0) {    PRINTF(L_SYS_CRYPTO,"error decrypting ECM (round 1)");    return false;;    }  cBN mod;  BN_set_word(mod,in[0]>>4);  BN_lshift(mod,mod,508);  BN_add(result,result,mod);  if(rsa.RSA(out,64,result,e1,n1,false)!=64) {    PRINTF(L_SYS_CRYPTO,"error: result of ECM decryption is not 64 bytes");    return false;    }  if(vkey && !SigCheck(out,&out[56],vkey,7)) {    PRINTF(L_SYS_CRYPTO,"ECM decryption failed");    return false;    }  return true;}bool cNagra1::DecryptEMM(const unsigned char *in, unsigned char *out, const unsigned char *vkey, int len, BIGNUM *e1, BIGNUM *n1, BIGNUM *n2){  cBN result;  if(rsa.RSA(result,&in[9],len,pubExp,n2)<=0) {    PRINTF(L_SYS_CRYPTO,"error decrypting EMM (round 1)");    return false;;    }  cBN mod;  BN_set_word(mod,in[0]>>6);  BN_lshift(mod,mod,510);  BN_add(result,result,mod);  if(rsa.RSA(out,64,result,e1,n1,false)!=64) {    PRINTF(L_SYS_CRYPTO,"error: result of EMM decryption is not 64 bytes");    return false;    }  if(!vkey || SigCheck(out,&in[1],vkey,8))    return true;      // We need to use signature exchange method (7blocks emm,1 block signature)  PRINTF(L_SYS_CRYPTO,"warning: signature failed,trying signature exchange method");  unsigned char buf[8];  RotateBytes(buf,&in[1],sizeof(buf));  cBN newdata, newsig;  BN_bin2bn(buf,sizeof(buf),newdata);  BN_copy(newsig,result);  BN_mask_bits(newsig,64);  BN_bn2bin(newsig,buf);  RotateBytes(buf,sizeof(buf));  BN_rshift(result,result,64); // delete the lower 64 bits,we saved it  BN_lshift(result,result,64); // before as the new 64 bit signature  BN_add(result,result,newdata);    if(rsa.RSA(out,64,result,e1,n1)!=64) {    PRINTF(L_SYS_CRYPTO,"error: result of EMM decryption is not 64 bytes");    return false;    }  if(vkey && !SigCheck(out,buf,vkey,8)) {    PRINTF(L_SYS_CRYPTO,"fatal: signature failed in signature exchange method");    return false;    }  return true;}void cNagra1::CreatePQ(const unsigned char *key, BIGNUM *p, BIGNUM *q){  // Make des_key  unsigned char des_data[32];  unsigned char des_key[8], des_tmp[8];  memcpy(des_data,key,8);  RotateBytes(des_tmp,key,8);  des_tmp[7]=0x00;  Decrypt(des_data,des_tmp,des_key,true);  RotateBytes(des_key,8);  des_key[7]=0x00;  // Calculate P  for(int i=0; i<4; i++) {    const int off=i*8;    memcpy(&des_data[off],&key[4],8);    des_data[off]^=i;    Decrypt(&des_data[off],des_key,des_tmp,true);    memcpy(&des_data[off],des_tmp,8);    }  BN_bin2bn(des_data,32,p);  BN_add_word(p,(key[12]<<4)|((key[13]>>4)&0x0f));  BN_set_bit(p,(BN_num_bytes(p)*8)-1);  // Calculate Q  for(int i=0; i<4; i++) {    const int off=i*8;    memcpy(&des_data[off],&key[4],8);    des_data[off]^=(i+4);    Decrypt(&des_data[off],des_key,des_tmp,true);    memcpy(&des_data[off],des_tmp,8);    }  BN_bin2bn(des_data,32,q);  BN_add_word(q,((key[13]&0x0f)<<8)|key[14]);  BN_set_bit(q,(BN_num_bytes(q)*8)-1);}#ifndef TESTER// -- cSystemNagra -------------------------------------------------------------class cSystemNagra : public cSystem, public cNagra1 {private:  unsigned char mecmTable[256];  cEmu *emu;  //  void WriteTable(unsigned char *from, int off);public:  cSystemNagra(void);  virtual ~cSystemNagra();  virtual bool ProcessECM(const cEcmInfo *ecm, unsigned char *data);  virtual void ProcessEMM(int pid, int caid, unsigned char *buffer);  };cSystemNagra::cSystemNagra(void):cSystem(SYSTEM_NAME,SYSTEM_PRI){  emu=0;  memset(mecmTable,0,sizeof(mecmTable));  hasLogger=true;}cSystemNagra::~cSystemNagra(){  delete emu;}void cSystemNagra::WriteTable(unsigned char *from, int off){  off&=0xFF;  if(off+16<256) memcpy(mecmTable+off,from,16);  else {    int l=256-off;    memcpy(mecmTable+off,from,l);    memcpy(mecmTable,from+l,16-l);    }}bool cSystemNagra::ProcessECM(const cEcmInfo *ecm, unsigned char *data){  int cmdLen=data[4];  int id=(data[5]*256)+data[6];  cTimeMs minTime;  if(data[3]!=0x03) {    PRINTF(L_SYS_ECM,"invalid ECM");    return false;    }  data+=7;  if(data[0]!=0x10) {    PRINTF(L_SYS_ECM,"no ECM data available");    return false;    }  const int ecmLen=data[1];  const int verType=(data[2]>>3)&1;  const int keynr=(data[2]>>4)&1;  const int ecmParm=data[2]&7;  bool decrypt;  if(ecmParm==7) decrypt=false;  else if(ecmParm==5) decrypt=true;  else {    PRINTF(L_SYS_ECM,"unknown ecmParm, ignoring ECM");    return false;    }  cKeySnoop ks(this,'N',id,keynr);  unsigned char sessionKey[8], verifyKey[8];  bool hasVerifyKey=false;  cPlainKey *pk;  if((pk=keys.FindKey('N',id,ADDC3('V',KEYSET(0,0,verType)),sizeof(verifyKey)))) {    pk->Get(verifyKey);    hasVerifyKey=true;    }  else if(doLog) PRINTF(L_SYS_KEY,"missing %04X V TYP%d key (non-fatal)",id,verType);  if(!(pk=keys.FindKey('N',id,keynr,sizeof(sessionKey)))) return false;  pk->Get(sessionKey);  const int desLen=(ecmLen-9) & ~7; // datalen - signature - ks byte  unsigned char *decrypted=AUTOMEM(desLen);  for(int i=(desLen/8)-1; decrypt && i>=0; i--) {    const int off=i*8;    Decrypt(data+11+off,sessionKey,decrypted+off);    }  if(decrypt && hasVerifyKey && !SigCheck(decrypted,data+3,verifyKey,desLen/8)) {    PRINTF(L_SYS_ECM,"signature check failed in DES decrypt");    return false;    }  int cwEvenMecmIndex=-1, cwOddMecmIndex=-1;  switch(decrypted[0]) {    case 0x10:  // Whole CW      cwOddMecmIndex=decrypted[1];      memcpy(cw+8,&decrypted[2],8);      cwEvenMecmIndex=decrypted[10];      memcpy(cw,&decrypted[11],8);      break;    case 0x11: // Odd CW      cwOddMecmIndex=decrypted[1];      memcpy(cw+8, &decrypted[2],8);      break;    case 0x12: // Even CW      cwEvenMecmIndex=decrypted[1];      memcpy(cw,&decrypted[2],8);      break;    default: PRINTF(L_SYS_ECM,"failed to get CW"); return false;    }  const unsigned char * const mecmData=data+(ecmLen+2);  const int mecmRSALen=mecmData[1]-4;  if((cmdLen-(ecmLen+2))>64 && (*mecmData==0x20 || *mecmData==0x39)) {    if(mecmRSALen!=64) {      if(mecmRSALen>64 && doLog)        PRINTF(L_SYS_ECM,"ECM too big (len: %d)",mecmRSALen);      return false;      }    const int mecmProvId=mecmData[2]*256+mecmData[3];    const int keyType=(mecmData[4]>>3)&1;    const int pkey=mecmData[4]&3;    cBN e1, n1, n2;    cPlainKey *pk;    if(!(pk=keys.FindKey('N',mecmProvId,MBC3('E','1',KEYSET(0,pkey,keyType)),-1))) {      if(doLog) PRINTF(L_SYS_KEY,"missing %04x E1 PK%d TYP%d key",mecmProvId,pkey,keyType);      return false;      }    pk->Get(e1);    if(!(pk=keys.FindKey('N',mecmProvId,MBC3('N','1',KEYSET(0,pkey,keyType)),-1)))  {      if(doLog) PRINTF(L_SYS_KEY,"missing %04x N1 PK%d TYP%d key",mecmProvId,pkey,keyType);      return false;      }    pk->Get(n1);    if(!(pk=keys.FindKey('N',mecmProvId,MBC3('N','2',KEYSET(0,0,keyType)),-1)))  {      if(doLog) PRINTF(L_SYS_KEY,"missing %04x N2 TYP%d key",mecmProvId,keyType);      return false;      }    pk->Get(n2);    hasVerifyKey=false;    if((pk=keys.FindKey('N',mecmProvId,ADDC3('V',KEYSET(0,0,keyType)),sizeof(verifyKey))))  {      pk->Get(verifyKey);      hasVerifyKey=true;      }    else if(doLog) PRINTF(L_SYS_KEY,"missing %04x V TYP%d key (non-fatal)",mecmProvId,keyType);    unsigned char *decrMecmData=AUTOMEM(mecmRSALen);    if(!DecryptECM(&mecmData[4],decrMecmData,hasVerifyKey?verifyKey:0,mecmRSALen,e1,n1,n2))      return false;    if(*mecmData==0x39 || (*mecmData==0x20 && (mecmProvId&0xFE00)==0x4800)) {      unsigned char xor_table[64];      for(int i=sizeof(xor_table)-1; i>=0; i--) xor_table[i]=63-i;      CreateRSAPair(&decrMecmData[24],xor_table,e1,n1);      // new XOR table for MECM data      cBNctx ctx;      cBN x;      BN_mod_exp(x,e1,pubExp,n1,ctx);      int l=sizeof(xor_table)-BN_num_bytes(x);      memset(xor_table,0,l);      BN_bn2bin(x,xor_table+l);      RotateBytes(xor_table,sizeof(xor_table));      // And finally, new MECM table      for(int i=39; i<mecmRSALen; i++) decrMecmData[i]^=xor_table[i-39];      memcpy(&decrMecmData[3],&decrMecmData[39],mecmRSALen-39);      }    if(decrMecmData[0]==0x2F && decrMecmData[1]==mecmData[2] && decrMecmData[2]==mecmData[3])      WriteTable(decrMecmData+4,decrMecmData[3]*2);    }  if(cwOddMecmIndex>=0 && cwOddMecmIndex<0x80) {    const int d=cwOddMecmIndex*2;    for(int i=0 ; i<8 ; i++) cw[i+8]^=mecmTable[(d+i)&0xFF]; // odd    }  if(cwEvenMecmIndex>=0 && cwEvenMecmIndex<0x80) {    const int d=cwEvenMecmIndex*2;    for(int i=0 ; i<8 ; i++) cw[i]^=mecmTable[(d+i)&0xFF]; // even    }  ks.OK(pk);  int i=minEcmTime-minTime.Elapsed();  if(i>0) cCondWait::SleepMs(i);  return true;}  void cSystemNagra::ProcessEMM(int pid, int caid, unsigned char *buffer){  const int id=buffer[10]*256+buffer[11];  static const unsigned char tester[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x4B };  if(memcmp(&buffer[3],tester,sizeof(tester)) || SCT_LEN(buffer)<(12+9+64)) {    PRINTF(L_SYS_EMM,"%d: not a valid EMM structure",CardNum());    return;    }  const int pkey=(buffer[12]&3);  cPlainKey *pk;  cBN e1, n1, n2;  if(!(pk=keys.FindKey('N',id,MBC3('E','1',KEYSET(0,pkey,0)),-1))) return;  pk->Get(e1);  if(!(pk=keys.FindKey('N',id,MBC3('N','1',KEYSET(0,pkey,0)),-1))) return;  pk->Get(n1);  unsigned char v[8];  bool hasVerifyKey=false;  if((pk=keys.FindKey('N',id,ADDC3('V',KEYSET(0,0,0)),sizeof(v)))) {    pk->Get(v);    hasVerifyKey=true;    }  int mode=(buffer[12]&8) ? 0:2;  unsigned char emmdata[64];  bool r;  do {    switch(mode) {      case 0: // get the ROM10 specific management key        if(!(pk=keys.FindKey('N',id,MBC3('N','2',KEYSET(10,0,1)),-1))) return;        pk->Get(n2);        mode=1; break;      case 1: // get the ROM11 specific management keys        if(!(pk=keys.FindKey('N',id,MBC3('E','1',KEYSET(11,pkey,1)),-1))) return;        pk->Get(e1);        if(!(pk=keys.FindKey('N',id,MBC3('N','1',KEYSET(11,pkey,1)),-1))) return;        pk->Get(n1);        if(!(pk=keys.FindKey('N',id,MBC3('N','2',KEYSET(11,0,1)),-1))) return;        pk->Get(n2);        hasVerifyKey=false;        if((pk=keys.FindKey('N',id,ADDC3('V',KEYSET(11,0,1)),sizeof(v)))) {          pk->Get(v);          hasVerifyKey=true;          }        mode=-1; break;      case 2: // get the universal management key        if(!(pk=keys.FindKey('N',id,MBC3('N','2',KEYSET(0,0,0)),-1))) return;        pk->Get(n2);        mode=-1; break;      }    r=DecryptEMM(&buffer[12],emmdata,hasVerifyKey?v:0,64,e1,n1,n2);    } while(!r && mode>=0);  if(r) {    HEXDUMP(L_SYS_RAWEMM,emmdata,sizeof(emmdata),"Nagra1 RAWEMM");    unsigned int i=0;    bool gotKeys=false;    unsigned char key0[8], key1[8];    int keyId=(emmdata[i+1]<<8)+emmdata[i+2];    switch(emmdata[i]) { // Check filter type      case 0x00: // One card        i+=7; break;      case 0x01: case 0x02: case 0x03: case 0x04: // Group of cards      case 0x05: case 0x06: case 0x07: case 0x08:      case 0x09: case 0x0A: case 0x0B: case 0x0C:      case 0x0D: case 0x0E: case 0x0F: case 0x10:      case 0x11: case 0x12: case 0x13: case 0x14:      case 0x15: case 0x16: case 0x17: case 0x18:      case 0x19: case 0x1A: case 0x1B: case 0x1C:      case 0x1D: case 0x1E: case 0x1F: case 0x20:        i+=emmdata[i]+0x7; break;      case 0x3e:        i+=6; break;      case 0x3d: // All cards with same system ID      case 0x3f:        i+=3; break;      }    int nrKeys=0;    while(i<sizeof(emmdata)) {      if((emmdata[i]&0xF0)==0xF0) { // Update with CPU code        const int romNr=emmdata[i]&0x0F;        if(!emu || !emu->Matches(romNr,id)) {          delete emu; emu=0;          PRINTF(L_SYS_EMM,"%d: setting defaults for ROM %d",CardNum(),romNr);          switch(romNr) {            case 3:  emu=new cEmuRom3;  break;            case 7:  emu=new cEmuRom7;  break;            case 10: emu=new cEmuRom10; break;            case 11: emu=new cEmuRom11; break;            default: PRINTF(L_SYS_EMM,"%d: unsupported ROM",CardNum()); return;            }          if(!emu || !emu->Init(romNr,id)) {            delete emu; emu=0;            PRINTF(L_SYS_EMM,"%d: initialization failed for ROM %d",CardNum(),romNr);            return;            }          }        unsigned char ki[2];        if((gotKeys=emu->GetOpKeys(emmdata,ki,key0,key1))) {          keyId=(ki[0]<<8)+ki[1];          PRINTF(L_SYS_EMM,"%d: got keys for %04X (ROM %d)",CardNum(),keyId,romNr);          }        unsigned char select[3], pkset[3][15];        select[0]=(keyId>>8)|0x01; // always high id for ECM RSA keys        select[1]=keyId&0xFF;        select[2]=0; // type 0        if(emu->GetPkKeys(&select[0],&pkset[0][0])) {          int pkKeyId=((select[0]<<8)+select[1]);          PRINTF(L_SYS_EMM,"%d: got PK keys for %04X (ROM %d)",CardNum(),pkKeyId,romNr);          for(int i=0; i<3; i++) {            CreateRSAPair(pkset[i],0,e1,n1);            FoundKey();            if(keys.NewKey('N',pkKeyId,ADDC3(MBC('N','1'),KEYSET(0,i,0)),n1,64)) NewKey();            FoundKey();            if(keys.NewKey('N',pkKeyId,ADDC3(MBC('E','1'),KEYSET(0,i,0)),e1,64)) NewKey();            }          }        break; // don't process other nanos        }      else if(emmdata[i]==0x60) { // NULL nano        i+=2;        }      else if(emmdata[i]==0x00) {        i++;        }      else if(emmdata[i]==0x81) {        i++;        }      else if(emmdata[i]==0x83) {        keyId=(emmdata[i+1]<<8)+emmdata[i+2];        i+=3;        }      else if(emmdata[i]==0x42) { // plain Key        if(emmdata[i+1]==0x05) memcpy(key0,&emmdata[i+2],sizeof(key0));        else                   memcpy(key1,&emmdata[i+2],sizeof(key1));        i+=10;        if(++nrKeys==2) {          gotKeys=true;          PRINTF(L_SYS_EMM,"%d: got keys for %04X (plain)",CardNum(),keyId);          break;          }        }      else {        PRINTF(L_SYS_EMM,"%d: ignored nano %02x",CardNum(),emmdata[i]);        break;        }      }    if(gotKeys) {      FoundKey();      if(keys.NewKey('N',keyId,00,key0,8)) NewKey();      FoundKey();      if(keys.NewKey('N',keyId,01,key1,8)) NewKey();      }    }}// -- cSystemLinkNagra ---------------------------------------------------------class cSystemLinkNagra : public cSystemLink {public:  cSystemLinkNagra(void);  virtual bool CanHandle(unsigned short SysId);  virtual cSystem *Create(void) { return new cSystemNagra; }  };static cSystemLinkNagra staticInitN1;cSystemLinkNagra::cSystemLinkNagra(void):cSystemLink(SYSTEM_NAME,SYSTEM_PRI){  opts=new cOpts(SYSTEM_NAME,1);  opts->Add(new cOptInt("MinEcmTime",trNOOP("Nagra: min. ECM processing time"),&minEcmTime,0,5000));  Feature.NeedsKeyFile();}bool cSystemLinkNagra::CanHandle(unsigned short SysId){  return SysId==SYSTEM_NAGRA; // || SysId==SYSTEM_NAGRA_BEV;}#endif //TESTER

⌨️ 快捷键说明

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