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

📄 nagra1.cpp

📁 DVB-S的softcam源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
  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);
    for(int i=0; i<8; i++) hash[i]=cr[i]^block[j*8+i];
    }
  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) {
    dn(printf("nagra: error decrypting ECM (round 1)\n"))
    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) {
    dn(printf("nagra: error: result of ECM decryption is not 64 bytes\n"))
    return false;
    }
  if(vkey && !SigCheck(out,&out[56],vkey,7)) {
    dn(printf("nagra: ECM decryption failed\n"))
    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) {
    dn(printf("nagra: error decrypting EMM (round 1)\n"))
    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) {
    dn(printf("nagra: error: result of EMM decryption is not 64 bytes\n"))
    return false;
    }
  if(!vkey || SigCheck(out,&in[1],vkey,8))
    return true;
    
  // We need to use signature exchange method (7blocks emm,1 block signature)
  dn(printf("nagra: warning: signature failed,trying signature exchange method\n"))
  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) {
    dn(printf("nagra: error: result of EMM decryption is not 64 bytes\n"))
    return false;
    }
  if(vkey && !SigCheck(out,buf,vkey,8)) {
    dn(printf("nagra: fatal: signature failed in signature exchange method\n"))
    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);
}

// -- 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) {
    dn(printf("system-nagra: invalid ECM\n"))
    return false;
    }
  data+=7;
  if(data[0]!=0x10) {
    dn(printf("system-nagra: no ECM data available\n"))
    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 {
    dn(printf("system-nagra: unknown ecmParm, ignoring ECM\n"))
    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) d(printf("system-nagra: missing %04X V TYP%d key (non-fatal)\n",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[desLen];
  unsigned char decrypted[16000];
  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)) {
    dn(printf("system-nagra: signature check failed in DES decrypt\n"))
    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: dn(printf("system-nagra: failed to get CW\n")) 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)
        d(printf("system-nagra: ECM too big (len: %d)\n",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) d(printf("system-nagra: missing %04x E1 PK%d TYP%d key\n",mecmProvId,pkey,keyType))
      return false;
      }
    pk->Get(e1);
    if(!(pk=keys.FindKey('N',mecmProvId,MBC3('N','1',KEYSET(0,pkey,keyType)),-1)))  {
      if(doLog) d(printf("system-nagra: missing %04x N1 PK%d TYP%d key\n",mecmProvId,pkey,keyType))
      return false;
      }
    pk->Get(n1);
    if(!(pk=keys.FindKey('N',mecmProvId,MBC3('N','2',KEYSET(0,0,keyType)),-1)))  {
      if(doLog) d(printf("system-nagra: missing %04x N2 TYP%d key\n",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) d(printf("system-nagra: missing %04x V TYP%d key (non-fatal)\n",mecmProvId,keyType))
//    unsigned char decrMecmData[mecmRSALen];
	unsigned char decrMecmData[16000];
    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)) {
    dl(printf("logger-nagra %d: not a valid EMM structure\n",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) {
    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: 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 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: // Group of cards
        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;
          dl(printf("logger-nagra %d: setting defaults for ROM %d\n",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: dl(printf("logger-nagra %d: unsupported ROM\n",CardNum())) return;
            }
          if(!emu || !emu->Init(romNr,id)) {
            delete emu; emu=0;
            dl(printf("logger-nagra %d: initialization failed for ROM %d\n",CardNum(),romNr))
            return;
            }
          }
        unsigned char ki[2];
        if((gotKeys=emu->GetOpKeys(emmdata,ki,key0,key1))) {
          keyId=(ki[0]<<8)+ki[1];
          dl(printf("logger-nagra %d: got keys for %04X (ROM %d)\n",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]);
          dl(printf("logger-nagra %d: got PK keys for %04X (ROM %d)\n",CardNum(),pkKeyId,romNr))
          for(int i=0; i<3; i++) {
            CreateRSAPair(pkset[i],0,e1,n1);
            cSoftCAM::FoundKey();
            if(keys.NewKey('N',pkKeyId,ADDC3(MBC('N','1'),KEYSET(0,i,0)),(void *)n1,64)) cSoftCAM::NewKey();
            cSoftCAM::FoundKey();
            if(keys.NewKey('N',pkKeyId,ADDC3(MBC('E','1'),KEYSET(0,i,0)),(void *)e1,64)) cSoftCAM::NewKey();
            }
          cSoftCAM::Save();
          }
        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;
          dl(printf("logger-nagra %d: got keys for %04X (plain)\n",CardNum(),keyId))
          break;
          }
        }
      else {
        dl(printf("logger-nagra %d: ignored nano %02x\n",CardNum(),emmdata[i]))
        break;
        }
      }
    if(gotKeys) {
      cSoftCAM::FoundKey();
      if(keys.NewKey('N',keyId,00,key0,8)) cSoftCAM::NewKey();
      cSoftCAM::FoundKey();
      if(keys.NewKey('N',keyId,01,key1,8)) cSoftCAM::NewKey();
      cSoftCAM::Save();
      }
    }
}

// -- cSystemLinkNagra ---------------------------------------------------------

/*
static const tI18nPhrase Phrases[] = {
  { "Nagra: min. ECM processing time",
    "Nagra: min. ECM Bearbeitungszeit",
    "",
    "",
    "Nagra: min. ECM bewerkingstijd",
    "",
    "Nagra: min. dur閑 du processus ECM",
    "",
    "Nagra: min. ECM:n prosessointiaika",
    "Nagra: min. czas przetwarzania ECM",
    "",
    "",
    "",
  },
  { NULL }
  };
*/

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","Nagra: min. ECM processing time",&minEcmTime,0,5000));
  Feature.NeedsKeyFile();
//  Feature.AddPhrases(Phrases);
}

bool cSystemLinkNagra::CanHandle(unsigned short SysId)
{
  //Bev Fix 12/26/06, NooneImportant
  //return SysId==SYSTEM_NAGRA || SysId==SYSTEM_NAGRA_BEV;
	return SysId==SYSTEM_NAGRA;
}

#endif //TESTER

⌨️ 快捷键说明

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