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

📄 nagra2.cpp

📁 DVB-S的softcam源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*
 * Softcam plugin to VDR (C++)
 *
 * This code is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This code is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include <unistd.h>
#include <ctype.h>
#include "stdafx.h"
//#include <vdr/tools.h>

#include "common.h"
#include "sc.h"
#include "system.h"
#include "misc.h"
#include "opts.h"
#include "network.h"
#include "crypto.h"
//#include "md5crypt/md5crypt.h"
#include "helper.h"
/////////

#include "network.h"
#include "xnprintf.h"

#include <openssl/bn.h>
#include <openssl/des.h>
#include <openssl/sha.h>
#include "openssl-compat.h"

#include "debug.h"
#include "nagra.h"
#include "cpu.h"

//********************************************  Modification - 12/26/06  **
#include "main.h"
extern class DllClass m_DLLInstance;

extern bool g_BeepOnNewKey;
extern bool g_LogE3;

//#include "morph.h"
//extern class B1morph B1_morph;
//********************************************  Modification - 12/26/06  **

#define SYSTEM_NAME          "Nagra2"
#define SYSTEM_PRI           -10

// -- cN2Emu -------------------------------------------------------------------

class cN2Emu : protected c6805 {
private:
  bool initDone;
protected:
  bool Init(int id, int romv);
  virtual void Stepper(void) {}
public:
  cN2Emu(void);
  virtual ~cN2Emu() {}
  };

cN2Emu::cN2Emu(void)
{
  initDone=false;
}

bool cN2Emu::Init(int id, int romv)
{
  if(!initDone) {
    ResetMapper();
    char buff[256];
    _snprintf(buff,sizeof(buff),"ROM%d.bin",romv);
    // UROM  0x00:0x4000-0x7fff
    if(!AddMapper(new cMapRom(0x4000,buff,0x00000),0x4000,0x4000,0x00)) return false;
    // ROM00 0x00:0x8000-0xffff
    if(!AddMapper(new cMapRom(0x8000,buff,0x04000),0x8000,0x8000,0x00)) return false;
    // ROM01 0x01:0x8000-0xffff
    if(!AddMapper(new cMapRom(0x8000,buff,0x0C000),0x8000,0x8000,0x01)) return false;
    // ROM02 0x02:0x8000-0xbfff
    if(!AddMapper(new cMapRom(0x8000,buff,0x14000),0x8000,0x4000,0x02)) return false;

    _snprintf(buff,sizeof(buff),"EEP%02X_%d.bin",(id>>8)&0xFF,romv);
    // Eeprom00 0x00:0x3000-0x37ff OTP 0x80
    if(!AddMapper(new cMapRom(0x3000,buff,0x0000),0x3000,0x0800,0x00)) return false;
    //XXX if(!AddMapper(new cMapEeprom(0x3000,buff,128,0x0000),0x3000,0x0800,0x00)) return false;
    // Eeprom80 0x80:0x8000-0xbfff
    if(!AddMapper(new cMapRom(0x8000,buff,0x0800),0x8000,0x4000,0x80)) return false;
    //XXX if(!AddMapper(new cMapEeprom(0x8000,buff,  0,0x0800),0x8000,0x4000,0x80)) return false;
    initDone=true;
    }
  return true;
}

// -- cN2Prov ------------------------------------------------------------------

class cN2Prov {
private:
  unsigned seed[5], cwkey[8];
  bool keyValid;
  cIDEA idea;
protected:
  int id, flags;
  //
  virtual bool Algo(int algo, const unsigned char *hd, unsigned char *hw) { return false; }
  virtual bool NeedsCwSwap(void) { return false; }
  void ExpandInput(unsigned char *hw);
public:
  cN2Prov(int Id, int Flags);
  virtual ~cN2Prov() {}
  bool MECM(unsigned char in15, int algo, unsigned char *cws);
  void SwapCW(unsigned char *cw);
  virtual int ProcessB1(unsigned char *data, int len, int pos) { return -1; }
  bool CanHandle(int Id) { return ((Id^id)&~0x107)==0; }
  bool HasFlags(int Flags) { return (flags&Flags)==Flags; }
  };

cN2Prov::cN2Prov(int Id, int Flags)
{
  keyValid=false; id=Id; flags=Flags;
}

void cN2Prov::ExpandInput(unsigned char *hw)
{
  hw[0]^=(0xDE +(0xDE<<1)) & 0xFF;
  hw[1]^=(hw[0]+(0xDE<<1)) & 0xFF;
  for(int i=2; i<128; i++) hw[i]^=hw[i-2]+hw[i-1];
  IdeaKS ks;
  idea.SetEncKey((unsigned char *)"NagraVision S.A.",&ks);
  unsigned char buf[8];
  memset(buf,0,8);
  for(int i=0; i<128; i+=8) {
    xxor(buf,8,buf,&hw[i]);
    idea.Encrypt(buf,8,buf,&ks,0);
    xxor(buf,8,buf,&hw[i]);
    memcpy(&hw[i],buf,8);
    }
}

bool cN2Prov::MECM(unsigned char in15, int algo, unsigned char *cw)
{
  unsigned char hd[5], hw[128+64], buf[20];
  hd[0]=in15&0x7F;
  hd[1]=cw[14];
  hd[2]=cw[15];
  hd[3]=cw[6];
  hd[4]=cw[7];

  if(keyValid && !memcmp(seed,hd,5)) {	// key cached
    memcpy(buf,cwkey,8);
    }
  else {				// key not cached
    memset(hw,0,sizeof(hw));
    if (!Algo(algo,hd,hw)) return false;
    memcpy(&hw[128],hw,64);
    RotateBytes(&hw[64],128);
    SHA1(&hw[64],128,buf);
    RotateBytes(buf,20);

    memcpy(seed,hd,5);
    memcpy(cwkey,buf,8);
    keyValid=true;
    }  

  memcpy(&buf[8],buf,8);
  IdeaKS ks;
  idea.SetEncKey(buf,&ks);
  memcpy(&buf[0],&cw[8],6);
  memcpy(&buf[6],&cw[0],6);
  idea.Encrypt(&buf[4],8,&buf[4],&ks,0);
  idea.Encrypt(buf,8,buf,&ks,0);

  memcpy(&cw[ 0],&buf[6],3);
  memcpy(&cw[ 4],&buf[9],3);
  memcpy(&cw[ 8],&buf[0],3);
  memcpy(&cw[12],&buf[3],3);
  for(int i=0; i<16; i+=4) cw[i+3]=cw[i]+cw[i+1]+cw[i+2];
  return true;
}

void cN2Prov::SwapCW(unsigned char *cw)
{
  if(NeedsCwSwap()) {
    unsigned char tt[8];
    memcpy(&tt[0],&cw[0],8);
    memcpy(&cw[0],&cw[8],8);
    memcpy(&cw[8],&tt[0],8);
    }
}

// -- cN2ProvLink & cN2Providers -----------------------------------------------

#define N2FLAG_NONE 0
#define N2FLAG_MECM 1
#define N2FLAG_B1   2
#define N2FLAG_INV  128

class cN2Providers;

class cN2ProvLink {
friend class cN2Providers;
private:
  cN2ProvLink *next;
protected:
  int id, flags;
  //
  virtual cN2Prov *Create(void)=0;
  bool CanHandle(int Id) { return ((Id^id)&~0x107)==0; }
  bool HasFlags(int Flags) { return (flags&Flags)==Flags; }
public:
  cN2ProvLink(int Id, int Flags);
  virtual ~cN2ProvLink() {}
  };

class cN2Providers {
friend class cN2ProvLink;
private:
  static cN2ProvLink *first;
  //
  static void Register(cN2ProvLink *plink);
public:
  static cN2Prov *GetProv(int Id, int Flags);
  };

template<class PROV, int ID, int FLAGS> class cN2ProvLinkReg : public cN2ProvLink {
public:
  cN2ProvLinkReg(void):cN2ProvLink(ID,FLAGS) {}
  virtual cN2Prov *Create(void) { return new PROV(id,flags); }
  };

cN2ProvLink *cN2Providers::first=0;

void cN2Providers::Register(cN2ProvLink *plink)
{
  dyn(printf("n2providers: registering prov %04X with flags %d\n",plink->id,plink->flags))
  plink->next=first;
  first=plink;
}

cN2Prov *cN2Providers::GetProv(int Id, int Flags)
{
  cN2ProvLink *pl=first;
  while(pl) {
    if(pl->CanHandle(Id) && pl->HasFlags(Flags)) return pl->Create();
    pl=pl->next;
    }
  return 0;
}

cN2ProvLink::cN2ProvLink(int Id, int Flags)
{
  id=Id; flags=Flags;
  cN2Providers::Register(this);
}

class cMapCore {
private:
  cBN x, y, s, j;
  SHA_CTX sctx;
protected:
  cBN A, B, C, D, J;
  cBN H, R;
  cBNctx ctx;
  int wordsize;
  //
  void ImportReg(unsigned char reg, const unsigned char *data, int l=0);
  void ExportReg(unsigned char reg, unsigned char *data, int l=0, bool BE=false);
  void SetWordSize(int l) { wordsize=l; }
  void MakeJ(void);
  void MonMul(BIGNUM *o, BIGNUM *i1, BIGNUM *i2);
  bool DoMap(int f, unsigned char *data=0, int l=0);
public:
  cMapCore(void);
  };

cMapCore::cMapCore(void)
{
  wordsize=4;
}

void cMapCore::ImportReg(unsigned char reg, const unsigned char *in, int l)
{
  l=(l?l:wordsize)<<3;
  switch(reg) {
    case IMPORT_J: J.GetLE(in,8); break;
    case IMPORT_A: A.GetLE(in,l); break;
    case IMPORT_B: B.GetLE(in,l); break;
    case IMPORT_C: C.GetLE(in,l); break;
    case IMPORT_D: D.GetLE(in,l); break;
    default: d(printf("internal: nagramap import register not supported")); return;
    }
}

void cMapCore::ExportReg(unsigned char reg, unsigned char *out, int l, bool BE)
{
  l=(l?l:wordsize)<<3;
  cBN *ptr;
  switch(reg) {
    case EXPORT_A: ptr=&A; break;
    case EXPORT_B: ptr=&B; break;
    case EXPORT_C: ptr=&C; break;
    case EXPORT_D: ptr=&D; break;
    default: d(printf("internal: nagramap export register not supported")); return;
    }
  if(!BE) ptr->PutLE(out,l);
  else ptr->Put(out,l);
}

void cMapCore::MakeJ(void)
{
#if OPENSSL_VERSION_NUMBER < 0x0090700fL
#error BN_mod_inverse is probably buggy in your openssl version
#endif
  BN_zero(x);
  BN_sub(J,x,D);
  BN_set_bit(J,0);
  BN_set_bit(x,64);
  BN_mod_inverse(J,J,x,ctx);
}

void cMapCore::MonMul(BIGNUM *o, BIGNUM *i1, BIGNUM *i2)
{
  int words=(BN_num_bytes(i1)+7)>>3;
  BN_zero(s);
  for(int i=0; i<words; i++) {	
    BN_rshift(x,i1,i<<6);
    BN_mask_bits(x,64);
    BN_mul(x,x,i2,ctx);
    BN_add(s,s,x);

    BN_copy(x,s);
    BN_mask_bits(x,64);
    BN_mul(x,x,J,ctx);
    if(i==(words-1)) {
      BN_lshift(y,x,64);
      BN_add(y,y,x);
      // Low
      BN_rshift(C,y,2);
      BN_add(C,C,s);
      BN_rshift(C,C,52);
      BN_mask_bits(C,12);
      }

    BN_mask_bits(x,64);
    BN_mul(x,x,D,ctx);
    BN_add(s,s,x);
    if(i==(words-1)) {
      // High
      BN_lshift(y,s,12);
      BN_add(C,C,y);
      BN_mask_bits(C,wordsize<<6);
      }

    BN_rshift(s,s,64);
    if(BN_cmp(s,D)==1) {
      BN_copy(x,s);
      BN_sub(s,x,D);
      }
    }
  BN_copy(o,s);
}

bool cMapCore::DoMap(int f, unsigned char *data, int l)
{
  switch(f) {
    case 0x43: // init SHA1

⌨️ 快捷键说明

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