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

📄 nagra2.cpp

📁 DVB-S的softcam源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
      SHA1_Init(&sctx);
      break;
    case 0x44: // add 64 bytes to SHA1 buffer
      RotateBytes(data,64);
      SHA1_Update(&sctx,data,64);
      BYTE4_LE(data   ,sctx.h4);
      BYTE4_LE(data+4 ,sctx.h3);
      BYTE4_LE(data+8 ,sctx.h2);
      BYTE4_LE(data+12,sctx.h1);
      BYTE4_LE(data+16,sctx.h0);
      break;
    case 0x45: // add wordsize bytes to SHA1 buffer and finalize SHA result
      if(wordsize) {
        if(wordsize>1) RotateBytes(data,wordsize);
        SHA1_Update(&sctx,data,wordsize);
        }
      memset(data,0,64);
      SHA1_Final(data+64,&sctx);
      break;
    default:
      return false;
    }
  return true;
}


#include "nagra2-prov.cpp"
//#include "nagra2-0101.cpp"

#ifndef TESTER

// -- cNagra2 ------------------------------------------------------------------

class cNagra2 : public cNagra {
private:
  bool Signature(const unsigned char *vkey, const unsigned char *sig, const unsigned char *msg, int len);
protected:
  cIDEA idea;
  //
  virtual void CreatePQ(const unsigned char *key, BIGNUM *p, BIGNUM *q);
  bool DecryptECM(const unsigned char *in, unsigned char *out, const unsigned char *key, int len, const unsigned char *vkey, BIGNUM *m);
  bool DecryptEMM(const unsigned char *in, unsigned char *out, const unsigned char *key, int len, const unsigned char *vkey, BIGNUM *m);
  };

void cNagra2::CreatePQ(const unsigned char *key, BIGNUM *p, BIGNUM *q)
{
  // Calculate P and Q from PK
  IdeaKS ks;
  idea.SetEncKey(key,&ks);
  // expand IDEA-G key
  unsigned char idata[96];
  for(int i=11; i>=0; i--) {
    const int off=i*8;
    memcpy(&idata[off],&key[13],8);
    idata[off]^=i;
    idea.Decrypt(&idata[off],8,&ks,0);
    for(int j=7; j>=0; j--) idata[off+j] ^= key[13+j];
    idata[off]^=i;
    }
  // 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);
    for(int j=7; j>=0; j--) buff[j+8]^=msg[i+j];
    }
  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) {
    d(printf("nagra2: first RSA failed (ECM)\n"))
    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) {
    //d(printf("nagra2: second RSA failed (ECM)\n"))
    return false;
    }
  if(vkey && !Signature(vkey,out,out+8,len-8)) {
    //d(printf("nagra2: signature failed (ECM)\n"))
    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) {
    dl(printf("nagra2: first RSA failed (EMM)\n"))
    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) {
    dl(printf("nagra2: second RSA failed (EMM)\n"))
    return false;
    }
  if(vkey && !Signature(vkey,out,out+8,len-8)) {
    dl(printf("nagra2: signature failed (EMM)\n"))
    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;

  int provider=id;
  if (id >= 0x0101 && id <= 0x010F) {
	provider = 0x0101;
  } else if (id >= 0x0901 && id <= 0x090F) {
	provider = 0x0901;
  } else {
	provider = id;
  }

  if(cmdLen<64 || SCT_LEN(data)<cmdLen+10) {
    if(doLog) d(printf("system-nagra2: bad ECM message msgLen=%d sctLen=%d\n",cmdLen,SCT_LEN(data)))
    return false;
    }

  int keyNr=(data[7]&0x10)>>4;
//  cKeySnoop ks(this,'N',id,keyNr);
  cKeySnoop ks(this,'N',provider,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(!(pk=keys.FindKey('N',provider,MBC('M','1'),-1,0)))  {
    if(doLog) d(printf("system-nagra2: missing %04x M1 key\n",id))
    return false;
    }
  pk->Get(m1);
//  if((pk=keys.FindKey('N',id,'V',sizeof(vKey)))) {
  if((pk=keys.FindKey('N',provider,'V',sizeof(vKey),0))) {
    pk->Get(vKey);
    hasVerifyKey=true;
    }
//  else if(doLog && id!=lastEcmId) d(printf("system-nagra2: missing %04x V key (non-fatal)\n",id))
  else if(doLog && provider!=lastEcmId) d(printf("system-nagra2: missing %04x V key (non-fatal)\n",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) d(printf("system-nagra2: decrypt of ECM failed (%04x)\n",id))
    return false;
    }

  if((!ecmP && id!=lastEcmId) || (ecmP && !ecmP->CanHandle(provider))) {
    delete ecmP;
    ecmP=cN2Providers::GetProv(provider,N2FLAG_NONE);
    if(ecmP) d(printf("\nsystem-nagra2: provider %04x capabilities%s%s%s\n",id,ecmP->HasFlags(N2FLAG_MECM)?" MECM":"",ecmP->HasFlags(N2FLAG_B1)  ?" B1":"",ecmP->HasFlags(N2FLAG_INV) ?" INVCW":""))
    }
  lastEcmId=id;
  lastEcmId=provider;

#ifdef DEBUG
  bool contFail=false;
#endif
  int l=0, mecmAlgo=0;
  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;
//		  if(provider==0x0501) s^=1; //PW
//		  if(provider==0x1101) s^=1; //KD 23,5 Kabel
//		  if(provider==0x1102) s^=1; //KD ISH
          mecmAlgo=buff[i+2]&0x60;
          memcpy(cw+(s<<3),&buff[i+3],8);
          i+=11; l|=(s+1);
          }
        else {
          d(printf("system-nagra2: bad length %d in CW nano %02x\n",buff[i+1],buff[i]))
          i++;
          }
        break;
      case 0x00:
        i+=2; break;
	  case 0x13: case 0x14: case 0x15: case 0x16:
        i+=4; break;
      case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36:
      case 0xB0:
        i+=buff[i+1]+2;
        break;
      default:
#ifdef DEBUG
        if(!contFail) printf("system-nagra2: unknown ECM nano");
        printf(" %02x",buff[i]);
        contFail=true;
#endif
        i++;
        continue;
      }
#ifdef DEBUG
    if(contFail) { printf("\n"); contFail=false; }
#endif
    }
#ifdef DEBUG
  if(contFail) printf("\n");
#endif
  if(l!=3) return false;
  if(mecmAlgo>0) {
    if(ecmP && ecmP->HasFlags(N2FLAG_MECM)) {
      if(!ecmP->MECM(buff[15],mecmAlgo,cw)) return false;
      }
    else { d(printf("system-nagra2: MECM for provider %04x not supported\n",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];
	char txt[150];

	if(cmdLen<96 || SCT_LEN(buffer)<cmdLen+15) {
		sprintf(txt,"Bad EMM-G Packet (bad EMM message msgLen=%d sctLen=%d)\n",cmdLen,SCT_LEN(buffer));
		m_DLLInstance.PushMessage(MSG_EMM_DATA,txt);
		dl(printf("logger-nagra2: bad EMM message msgLen=%d sctLen=%d\n",cmdLen,SCT_LEN(buffer)))
		return;
    }

	int checkid = 0;
	int keyset=(buffer[12]&0x03);
	int sel=(buffer[12]&0x10)<<2;
	int sigsel=(buffer[13]&0x80)>>1;
	char time_str[20];
	_strtime(time_str);
	char text[100];
	char filename[_MAX_PATH];
	char EMM_filename[_MAX_PATH];
	int CamID = 0;
	int LogType = 0;

	int provider=id;
	if (id >= 0x0101 && id <= 0x010F) {
		provider = 0x0101;
	} else if (id >= 0x0901 && id <= 0x090F) {
		provider = 0x0901;
	} else {
		provider = id;
	}

	int keyPTR = N2_MAGIC;
	if (buffer[0] == 0x83) {
  		keyPTR = 0;
		for (int it=5; it>2; it--) {
			CamID = MBC(CamID,buffer[it]);
		}
  		keyPTR=CID(N2_EMM_S,buffer[5],buffer[4],buffer[3]);

	  LogType = m_DLLInstance.m_log_emm_by;
		switch(LogType) {
			case 0:			//0=no logging
				sprintf(EMM_filename,"");
				break;
			case 1:			//1=single file
				sprintf(EMM_filename,"EMM-S.log");
				break;
			case 2:			//2= two files (group / cam spec.)
				if (buffer[6] == 0x00) {
					sprintf(EMM_filename,"EMM-S_By_Group.log");
				} else {
					sprintf(EMM_filename,"EMM-S_By_Target.log");
				}
				break;
			case 3:			//3=by camid
			default:
				sprintf(EMM_filename,"CamID_%02X%02X%02X%02X.log",buffer[5],buffer[4],buffer[3],buffer[6]);
				break;
		}
	}

	cPlainKey *pk;
	cBN n;
	unsigned char ideaKey[24], vKey[16];
	bool hasVerifyKey=false;
	if(!(pk=keys.FindKey('N',provider,MBC(keyPTR,keyset+0x10+sel),96,0)))  {
		if (buffer[0] == 0x83) {
			sprintf(text,"[%s] EMM-S {%06X%02X} Missing: %04x S %.06X %.02X  RSA key",time_str,CamID,buffer[6],id,CamID,keyset+0x10+sel);
			m_DLLInstance.PushMessage(MSG_MESSAGE,text);
			sprintf(txt,"Your missing: %04x S %.06X %.02X  RSA key (96 bytes)",id,CamID,keyset+0x10+sel);
		} else {
			sprintf(txt,"Your missing: %04x NN %.02X  RSA key (96 bytes)",id,keyset+0x10+sel);
		}
		m_DLLInstance.PushMessage(MSG_EMM_DATA,txt);
		dl(printf("logger-nagra2: missing %04x NN %.02X RSA key (96 bytes)\n",id,keyset+0x10+sel))
		return;
    }
	pk->Get(n);

	if (buffer[0] != 0x83) {
	    if((pk=keys.FindKey('N',provider,MBC(keyPTR,0x03+sigsel),sizeof(vKey)))) {

⌨️ 快捷键说明

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