📄 nagra1.c
字号:
/* * 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 "system.h"#include "misc.h"#include "opts.h"#include "helper.h"#include "nagra.h"#include "cpu.h"#include "log-nagra.h"#define SYSTEM_NAME "Nagra"#define SYSTEM_PRI -10// -- cEmu ---------------------------------------------------------------------#define MAX_COUNT 200000class cEmu : public c6805 {protected: int romNr, id; char *romName, *romExtName, *eepromName; // int InitStart, InitEnd; int EmmStart, EmmEnd, EmmKey0, EmmKey1; int FindKeyStart, FindKeyEnd; int MapAddr; int Rc1H, Rc1L; int EnsIrdChk, Cmd83Chk; int SoftInt, StackHigh; // bool AddRom(unsigned short addr, unsigned short size, const char *name); bool AddEeprom(unsigned short addr, unsigned short size, unsigned short otpSize, const char *name); // virtual bool InitSetup(void) { return true; } virtual bool UpdateSetup(const unsigned char *emm) { return true; } virtual bool MathMapHandler(void);public: cEmu(void); virtual ~cEmu(); bool Init(int RomNr, int Id); bool GetOpKeys(const unsigned char *Emm, unsigned char *id, unsigned char *key0, unsigned char *key1); bool GetPkKeys(const unsigned char *select, unsigned char *pkset); bool Matches(int RomNr, int Id); };cEmu::cEmu(void){ romName=romExtName=eepromName=0;}cEmu::~cEmu(){ free(romName); free(romExtName); free(eepromName);}bool cEmu::AddRom(unsigned short addr, unsigned short size, const char *name){ cMap *map=new cMapRom(addr,name); return AddMapper(map,addr,size);}bool cEmu::AddEeprom(unsigned short addr, unsigned short size, unsigned short otpSize, const char *name){ cMap *map=new cMapEeprom(addr,name,otpSize); return AddMapper(map,addr,size);}bool cEmu::Matches(int RomNr, int Id){ return (romNr==RomNr && id==Id);}bool cEmu::Init(int RomNr, int Id){ romNr=RomNr; id=Id; asprintf(&romName,"ROM%d.bin",romNr); asprintf(&romExtName,"ROM%dext.bin",romNr); asprintf(&eepromName,"eep%i_%02x.bin",romNr,(id&0xff00)>>8); if(InitSetup()) { ForceSet(EnsIrdChk, 0x81,true); ForceSet(Cmd83Chk+0,0x98,true); ForceSet(Cmd83Chk+1,0x9d,true); if(SoftInt) { Set(0x1ffc,SoftInt>>8); Set(0x1ffd,SoftInt&0xff); } SetSp(StackHigh,0); SetPc(InitStart); ClearBreakpoints(); AddBreakpoint(InitEnd); if(!Run(MAX_COUNT)) return true; } return false;}bool cEmu::GetOpKeys(const unsigned char *Emm, unsigned char *id, unsigned char *key0, unsigned char *key1){ int keys=0; if(UpdateSetup(Emm)) { SetMem(0x0080,&Emm[0],64); SetMem(0x00F8,&Emm[1],2); SetPc(EmmStart); ClearBreakpoints(); AddBreakpoint(EmmEnd); AddBreakpoint(MapAddr); AddBreakpoint(EmmKey0); AddBreakpoint(EmmKey1); while(!Run(MAX_COUNT)) { unsigned short pc=GetPc(); if(pc==EmmKey0) { GetMem(0x82,key0,8); keys++; } if(pc==EmmKey1) { GetMem(0x82,key1,8); keys++; } if(pc==MapAddr) { if(!MathMapHandler()) break; PopPc(); // remove return address from stack } if(pc==EmmEnd) { GetMem(0x00F8,id,2); break; } } } return (keys==2);}bool cEmu::GetPkKeys(const unsigned char *select, unsigned char *pkset){ Set(0x0081,select[2]<<7); SetMem(0x00F8,select,3); SetPc(FindKeyStart); ClearBreakpoints(); AddBreakpoint(FindKeyEnd); while(!Run(MAX_COUNT)) { unsigned short pc=GetPc(); if(pc==FindKeyEnd) { if(!cc.c) { PRINTF(L_SYS_EMU,"Updating PK keys"); unsigned short loc=(Get(Rc1H)<<8)+Get(Rc1L); for(int i=0; i<45; i+=15) GetMem(loc+4+i,pkset+i,15); return true; } else { PRINTF(L_SYS_EMU,"Updating PK keys failed. Used a correct EEPROM image for provider %04x ?",((select[0]<<8)|select[1])); break; } } } return false;}bool cEmu::MathMapHandler(void){ PRINTF(L_SYS_EMU,"Unsupported math call $%02x in ROM %d, please report",a,romNr); return false;}// -- cEmuRom3Core -------------------------------------------------------------class cEmuRom3Core : public cEmu {protected: virtual void Stepper(void); bool CoreInitSetup(void); bool DoMaps(bool hasExt); };void cEmuRom3Core::Stepper(void){ int rnd=random(); unsigned char mem4=Get(0x04); if(!bitset(mem4,2)) { Set(0x06,(rnd&0xff00)>>8); Set(0x07,rnd&0xff); }}bool cEmuRom3Core::CoreInitSetup(void){ ForceSet(0x0001,1<<3,true); Set(0x0002,0x03); Set(0x004e,0x4B); return true;}bool cEmuRom3Core::DoMaps(bool hasExt){ // Eeprom & ROMext are non-fatal also they are required for some providers if(hasExt) AddRom(0x2000,0x2000,romExtName); AddEeprom(0xE000,0x1000,0x20,eepromName); return AddRom(0x4000,0x4000,romName);}// -- cEmuRom3 -----------------------------------------------------------------class cEmuRom3 : public cEmuRom3Core {protected: virtual bool InitSetup(void); virtual bool UpdateSetup(const unsigned char *emm);public: cEmuRom3(void); };cEmuRom3::cEmuRom3(void){ InitStart=0x4000; InitEnd =0x734b; EmmStart =0x5a82; EmmEnd =0x67db; EmmKey0 =0x617c; EmmKey1 =0x6184; FindKeyStart=0x6133; FindKeyEnd =0x6147; MapAddr =0x2800; Rc1H =0x0024; Rc1L =0x0025; EnsIrdChk=0x6437; Cmd83Chk =0x6431; SoftInt =0x0000; StackHigh=0x7f;}bool cEmuRom3::InitSetup(void){ return DoMaps(true) && CoreInitSetup();}bool cEmuRom3::UpdateSetup(const unsigned char *emm){ return CoreInitSetup();}// -- cEmuRom7 -----------------------------------------------------------------class cEmuRom7 : public cEmuRom3Core {protected: virtual bool InitSetup(void); virtual bool UpdateSetup(const unsigned char *emm);public: cEmuRom7(void); };cEmuRom7::cEmuRom7(void){ InitStart=0x4000; InitEnd =0x7b68; EmmStart =0x482b; EmmEnd =0x6146; EmmKey0 =0x4f2a; EmmKey1 =0x4f32; FindKeyStart=0x4ee4; FindKeyEnd =0x4ef5; MapAddr =0x200f; Rc1H =0x0028; Rc1L =0x0029; EnsIrdChk=0x51df; Cmd83Chk =0x51d9; SoftInt =0x4008; StackHigh=0x7f;}bool cEmuRom7::InitSetup(void){ return DoMaps(false) && CoreInitSetup();}bool cEmuRom7::UpdateSetup(const unsigned char *emm){ SetMem(0x01A2,&emm[1],2); return true;}// -- cEmuRom10Core ------------------------------------------------------------class cEmuRom10Core : public cEmu {protected: struct Map { unsigned char A[64], B[64], C[64], D[4], opSize; } map; // virtual void Stepper(void); bool DoMaps(bool hasExt, int romSize); bool CoreInitSetup(void); bool CoreUpdateSetup(const unsigned char *emm); };void cEmuRom10Core::Stepper(void){ int rnd=random(); unsigned char mem7=Get(0x07); if(cc.i) mem7&=0xFD; else mem7|=0x02; Set(0x07,mem7); if(bitset(mem7,1) && bitset(mem7,7)) { Set(0x05,(rnd&0xFF00)>>8); Set(0x06,rnd&0xFF); }}bool cEmuRom10Core::DoMaps(bool hasExt, int romSize){ // Eeprom & ROMext are non-fatal also they are required for some providers if(hasExt) AddRom(0x2000,0x2000,romExtName); AddEeprom(0xC000,0x2000,0x40,eepromName); return AddRom(0x4000,romSize,romName);}bool cEmuRom10Core::CoreInitSetup(void){ ForceSet(0x01,0x13,true); Set(0x02,0x3); Set(0x07,0xFF); return true;}bool cEmuRom10Core::CoreUpdateSetup(const unsigned char *emm){ SetMem(0x01A2,&emm[1],2); SetMem(0x0307,&emm[1],2); Set(0x0300,emm[5]); Set(0x0301,emm[2]); return true;}// -- cEmuRom10 ----------------------------------------------------------------class cEmuRom10 : public cEmuRom10Core {protected: virtual bool InitSetup(void); virtual bool UpdateSetup(const unsigned char *emm); virtual bool MathMapHandler(void);public: cEmuRom10(void); };cEmuRom10::cEmuRom10(void){ InitStart=0x4000; InitEnd =0x81ca; EmmStart =0x6a71; EmmEnd =0x81f7; EmmKey0 =0x7172; EmmKey1 =0x717a; FindKeyStart=0x712c; FindKeyEnd =0x713d; MapAddr =0x2020; Rc1H =0x004a; Rc1L =0x004b; EnsIrdChk=0x7427; Cmd83Chk =0x7421; SoftInt =0x4004; StackHigh=0x3ff;}bool cEmuRom10::InitSetup(void){ return DoMaps(false,0x5A00) && CoreInitSetup();}bool cEmuRom10::UpdateSetup(const unsigned char *emm){ Set(0x006e,0x4B); return CoreUpdateSetup(emm);}bool cEmuRom10::MathMapHandler(void){ PRINTF(L_SYS_EMU,"math call: $%02x",a); switch(a) { case 0x02: switch(Get(0x41)) { case 0: map.opSize=0x04; break; case 1: map.opSize=0x20; break; case 2: map.opSize=0x24; break; case 3: map.opSize=0x30; break; case 4: map.opSize=0x34; break; case 5: default: map.opSize=0x40; break; } return true; case 0x0e ... 0x10: { const unsigned short addr=(Get(0x4d)<<8)|Get(0x4e); unsigned char tmp[64]; GetMem(addr,tmp,map.opSize); unsigned char *reg; switch(a) { case 0x0e: reg=map.A; break; case 0x0f: reg=map.B; break; case 0x10: reg=map.C; break; default: return false; } SetMem(addr,reg,map.opSize); memcpy(reg,tmp,map.opSize); Set(0x41,map.opSize); return true; } case 0x29: Set(0x120,1); return true; } return cEmu::MathMapHandler();}// -- cEmuRom11 ----------------------------------------------------------------class cEmuRom11 : public cEmuRom10Core {protected: virtual bool InitSetup(void); virtual bool UpdateSetup(const unsigned char *emm);public: cEmuRom11(void); };cEmuRom11::cEmuRom11(void){ InitStart=0x4000; InitEnd =0x405b; EmmStart =0x5865; EmmEnd =0x9990; EmmKey0 =0x5f66; EmmKey1 =0x5f6e; FindKeyStart=0x5f20; FindKeyEnd =0x5f31; MapAddr =0x2020; Rc1H =0x004a; Rc1L =0x004b; EnsIrdChk=0x621b; Cmd83Chk =0x6215; SoftInt =0x4004; StackHigh=0x3ff;}bool cEmuRom11::InitSetup(void){ return DoMaps(false,0x8000) && CoreInitSetup();}bool cEmuRom11::UpdateSetup(const unsigned char *emm){ Set(0x0068,0x4B); return CoreUpdateSetup(emm);}// -- 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);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -