nagra2-0101.c
来自「VDR softcam plugin 0.9.1」· C语言 代码 · 共 969 行 · 第 1/2 页
C
969 行
/* * 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 "nagra2.h"// -- cAuxSrv ------------------------------------------------------------------#ifdef HAS_AUXSRV#include "network.h"#define AUX_PROTOCOL_VERSION 2int auxEnabled=0;int auxPort=7777;char auxAddr[80]="localhost";char auxPassword[250]="auxserver";class cAuxSrv : public cMutex {private: cNetSocket so; // bool Login(void);public: cAuxSrv(void); int Map(int map, unsigned char *data, int len, int outlen); };cAuxSrv::cAuxSrv(void):so(DEFAULT_CONNECT_TIMEOUT,7,DEFAULT_IDLE_TIMEOUT){}bool cAuxSrv::Login(){ unsigned char buff[256]; PRINTF(L_SYS_MAP,"auxsrv: connecting to %s:%d",auxAddr,auxPort); if(so.Connect(auxAddr,auxPort)) { buff[0]=0xA7; buff[1]=0x7A; buff[2]=0; int l=strlen(auxPassword); buff[3]=l; memcpy(&buff[4],auxPassword,l); buff[4+l]=0xFF; if(so.Write(buff,l+5)==l+5 && so.Read(buff,sizeof(buff))>=9 && buff[0]==0x7A && buff[1]==0xA7 && buff[2]==0x00 && buff[3]==0x04 && buff[8]==0xff && ((buff[4]<<8)|buff[5])==AUX_PROTOCOL_VERSION) return true; PRINTF(L_SYS_MAP,"auxsrv: login write failed"); } so.Disconnect(); return false;}int cAuxSrv::Map(int map, unsigned char *data, int len, int outlen){ if(!auxEnabled) { PRINTF(L_SYS_MAP,"auxsrv: AUXserver is disabled!"); return -1; } if(len>500 || outlen>500) return -1; cMutexLock lock(this); if(!so.Connected() && !Login()) return false; PRINTF(L_SYS_MAP,"auxsrv: calling map%02x",map); unsigned char buff[512]; buff[0]=0xA7; buff[1]=0x7A; buff[2]=((len+1)>>8) & 0xff; buff[3]=(len+1)&0xff; buff[4]=map; memcpy(&buff[5],data,len); buff[len+5]=0xFF; if(so.Write(buff,len+6)==len+6) { if((len=so.Read(buff,sizeof(buff)))>0) { if(buff[0]==0x7A && buff[1]==0xA7) { if(buff[4]==0x00) { int cycles=(buff[5]<<16)|(buff[6]<<8)|buff[7]; int l=buff[2]*256+buff[3]; if(len>=l+5 && l==outlen+4) { if(buff[l+4]==0xFF) { memcpy(data,buff+8,outlen); return cycles; } else PRINTF(L_SYS_MAP,"auxsrv: bad footer in map%02x response",map); } else PRINTF(L_SYS_MAP,"auxsrv: bad length in map%02x response (got=%d,%d want=%d,%d)",map,l-4,len,outlen,l+8); } else PRINTF(L_SYS_MAP,"auxsrv: map%02x not successfull (unsupported?)",map); } else PRINTF(L_SYS_MAP,"auxsrv: bad response to map%02x",map); } else PRINTF(L_SYS_MAP,"auxsrv: map%02x read failed",map); } else PRINTF(L_SYS_MAP,"auxsrv: map%02x write failed",map); so.Disconnect(); return -1;}#endif //HAS_AUXSRV// -- cMap0101 ----------------------------------------------------------------class cMap0101 : public cMapCore {private: static const unsigned char primes[]; static const int tim3b[][17]; static const unsigned short msb3e[];#ifdef HAS_AUXSRV cAuxSrv aux;#endif // void MakePrime(BIGNUM *n, unsigned char *residues);protected: virtual bool Map(int f, unsigned char *data, int l); };const unsigned char cMap0101::primes[] = { 0x03,0x05,0x07,0x0B,0x0D,0x11,0x13,0x17,0x1D,0x1F,0x25,0x29,0x2B,0x2F,0x35,0x3B, 0x3D,0x43,0x47,0x49,0x4F,0x53,0x59,0x61,0x65,0x67,0x6B,0x6D,0x71,0x7F,0x83,0x89, 0x8B,0x95,0x97,0x9D,0xA3,0xA7,0xAD,0xB3,0xB5,0xBF,0xC1,0xC5,0xC7,0xD3,0xDF,0xE3, 0xE5,0xE9,0xEF,0xF1,0xFB };const int cMap0101::tim3b[][17] = { { 2666,2804,2957,3105,3258,3406,3554,3707,3855,4008,4156,4304,4457,4605,4758,4906,5054 }, { 3163,3316,3484,3652,3815,3983,4146,4314,4482,4645,4813,4976,5144,5312,5475,5643,5806 }, { 3715,3888,4071,4254,4432,4615,4798,4981,5164,5342,5525,5708,5891,6074,6252,6435,6618 }, { 4302,4490,4688,4886,5084,5282,5480,5678,5876,6074,6272,6470,6668,6866,7064,7262,7460 }, { 4899,5107,5320,5533,5751,5964,6177,6390,6603,6821,7034,7247,7460,7673,7891,8104,8317 }, { 5541,5759,5992,6220,6453,6681,6909,7142,7370,7603,7831,8059,8292,8520,8753,8981,9209 }, { 6198,6431,6679,6927,7170,7418,7661,7909,8157,8400,8648,8891,9139,9387,9630,9878,10121 }, { 6910,7163,7426,7689,7947,8210,8473,8736,8999,9257,9520,9783,10046,10309,10567,10830,11093 }, { 7637,7905,8183,8461,8739,9017,9295,9573,9851,10129,10407,10685,10963,11241,11519,11797,12075 }, { 8394,8682,8975,9268,9566,9859,10152,10445,10738,11036,11329,11622,11915,12208,12506,12799,13092 }, { 9196,9494,9807,10115,10428,10736,11044,11357,11665,11978,12286,12594,12907,13215,13528,13836,14144 }, { 10003,10346,10674,11002,11325,11653,11976,12304,12632,12955,13283,13606,13934,14262,14585,14913,15236 }, { 10885,11218,11561,11904,12242,12585,12928,13271,13614,13952,14295,14638,14981,15324,15662,16005,16348 }, { 11792,12145,12498,12856,13214,13572,13930,14288,14646,15004,15362,15720,16078,16436,16794,17152,17510 }, { 12709,13087,13465,13843,14226,14604,14982,15360,15738,16121,16499,16877,17255,17633,18016,18394,18772 }, { 13671,14069,14477,14880,15283,15686,16084,16492,16890,17298,17696,18099,18507,18905,19313,19711,20114 }, { 14668,15091,15519,15947,16370,16798,17221,17654,18082,18505,18933,19356,19784,20212,20640,21068,21491 }, };void cMap0101::MakePrime(BIGNUM *n, unsigned char *residues){ bool isPrime; cycles+=1290; do { cycles+=1465; BN_add_word(n,2); isPrime=true; for(int i=0; i<53; i++) { residues[i]+=2; unsigned char num=residues[i]; unsigned char denom=primes[i]; if(num>denom) { unsigned char r=0; while(denom>=r) { cycles+=1; r=(r<<1)|((num&0x80)>>7); num<<=1; } } residues[i]%=primes[i]; if(residues[i]==0) { cycles+=13; isPrime=false; } } } while(!isPrime);}bool cMap0101::Map(int f, unsigned char *data, int l){ int sl=l; l=GetOpSize(l); switch(f) { case 0x21: AddMapCycles(169-6); IMakeJ(); cycles=898; break; case 0x22: if(BN_is_zero(D)) { cycles=639-6; break; } l&=0x1fff; BN_one(B); BN_mod_lshift(B,B,l,D,ctx); if(l<64) cycles=927+(l&7)*9; else { div_t val=div(l-64,2046); int j=16*((val.rem+1)/2) + (val.rem>4?val.rem-7:val.rem-12)/4; cycles=1086 + j - ((j-2)%5) + 16923*val.quot - ((4*val.quot-2)%5); } break; case 0x23: AddMapCycles(169); IMonInit0(); break; case 0x25: AddMapCycles(254); MakeJ0(B,D,C,wordsize<<6); // valid for wordsize 1 and 2 AddMapCycles(795*wordsize-492); BN_zero(C); cycles=49+800*wordsize; break; case 0x29: { BN_add(B,B,C); bool b=BN_is_bit_set(B,wordsize<<6); if(data) data[0]=b; if(b) BN_mask_bits(B,wordsize<<6); cycles=501+(8*wordsize+3)/5*5-6; break; } case 0x2a: { bool b=ModSub(B,B,D); if(data) data[0]=b; BN_zero(C); break; } case 0x30: case 0x31: BN_sqr(D,B,ctx); BN_rshift(J,B,((wordsize+1)/2)*128-64); BN_mask_bits(J,64); if((f&1)) BN_add(D,D,C); BN_rshift(C,D,wordsize<<6); BN_mask_bits(C,wordsize<<6); BN_mask_bits(D,wordsize<<6); break; case 0x32: l=min(34,l); if(!BN_is_zero(D)) { A.GetLE(data,l<<3); BN_div(C,B,A,D,ctx); BN_rshift(A,C,17*64); BN_mask_bits(C,17*64); A.Commit(17); C.Commit(17); } BN_zero(J); break; case 0x36: case 0x38: AddMapCycles(230); MonMul0(B,f==0x36?A:B,B,C,D,J,wordsize); AddMapCycles(102); MonFin(B,D); break; case 0x3b: AddMapCycles(441); IMakeJ(); AddMapCycles(46); IMonInit0(wordsize*60+4*l); I.GetLE(data,l<<3); MonMul(B,I,B,l); cycles=tim3b[wordsize-1][l-1]-6; break; case 0x3c: case 0x3e: { if(sl==0) cycles+=4; if(l>wordsize) { l=wordsize; cycles+=l>17 ? 9:4; } cBN scalar; scalar.GetLE(data,l<<3); AddMapCycles(441); if(BN_is_zero(scalar) || BN_num_bits(D)<=1) { IMakeJ(); if(BN_num_bits(D)==1 || !BN_is_zero(scalar)) BN_zero(B); else BN_one(B); BN_one(A); } else { IMonInit(); MonMul0(B,A,B,C,D,J,0); if(f==0x3c) AddMapCycles(2200+(rand()%(wordsize*2000))); MonFin(B,D); MonExp(scalar); } BN_zero(C); int sbits=BN_num_bits(scalar); cycles+=3848+((sbits-1)/8)*650 - 11; int msb=data[(sbits-1)/8]; for(int i=7; i>=1; --i) if(msb&(1<<i)) { cycles+=i*75-15; break; } for(int i=0; i<sbits; ++i) if(BN_is_bit_set(scalar,i)) cycles+=88; break; } case 0x4d: if(-0x018000==l) BN_mask_bits(B,64); else { BN_set_bit(B,(wordsize<<6)-1); if(-0x028000==l) BN_set_bit(B,(wordsize<<6)-2); } BN_set_bit(B,0); for(int i=0; i<53; i++) data[i]=BN_mod_word(B,primes[i]); break; case 0x4e: MakePrime(B,data); break; case 0x57:#ifdef HAS_AUXSRV { int c=aux.Map(0x57,data,0x60,0x40); if(c>0) { cycles=c-6; break; } }#endif { cBN a, b, x, y, scalar; if(l<2 || l>4) l=4; WS_START(l); l<<=3; D.GetLE(data+0*l,l); x.GetLE(data+1*l,l); y.GetLE(data+2*l,l); b.GetLE(data+3*l,l); a.GetLE(data+4*l,l); scalar.GetLE(data+5*l,l); bool doz=false; int scalarbits=BN_num_bits(scalar); if(scalarbits>=2) { if(BN_is_zero(x) && (BN_is_zero(y) || (BN_is_zero(b) && BN_num_bits(y)==1))) { BN_zero(Px); BN_copy(Py,y); BN_zero(Qz); } else { CurveInit(a); ToProjective(0,x,y); BN_copy(Qx,Px); BN_copy(Qy,Py); for(int i=scalarbits-2; i>=0; i--) { DoubleP(0); if(BN_is_bit_set(scalar,i)) { BN_copy(A,Pz); if(BN_is_zero(Pz) || BN_is_zero(D)) { BN_copy(Px,Qx); BN_copy(Py,Qy); BN_copy(Pz,Qz); AddP(1); } else { doz=true; if(wordsize==4) { BN_rshift(Py,Py,32); BN_lshift(Py,Py,32); BN_rshift(b,Qz,224); BN_add(Py,Py,b); } BN_mask_bits(Px,32); BN_lshift(b,Qz,32); BN_add(Px,Px,b); BN_mask_bits(Px,128); AddP(0); } } } ToAffine(); } } else { BN_copy(Px,x); BN_copy(Py,y); BN_zero(Qz); } memset(data,0,0x40); Px.PutLE(&data[0x00],l); if(l<0x20 && doz) { unsigned char tmp[0x20]; Qz.PutLE(tmp,l); memcpy(&data[l],&tmp[l-4],4); } Py.PutLE(&data[0x20],l); BN_zero(A); BN_zero(B); BN_zero(C); WS_END(); break; } default: return false; } return true;}// -- cN2Prov0101 --------------------------------------------------------------class cN2Prov0101 : public cN2Prov, public cN2Emu, private cMap0101 {private: int desSize; DES_key_schedule desks1, desks2; unsigned char desblock[8]; IdeaKS ks; cMapMemHW *hwMapper; // Randomiser unsigned int rnd, rndtime; // void AddRomCallbacks(void); bool RomCallbacks(void); bool ProcessMap(int f); bool ProcessDESMap(int f);protected: int mecmAddr[2]; int mecmKeyId; // virtual bool Algo(int algo, const unsigned char *hd, unsigned char *hw); virtual void DynamicHD(unsigned char *hd, const unsigned char *ed); virtual bool RomInit(void); virtual void Stepper(void); virtual void ReadHandler(unsigned char seg, unsigned short ea, unsigned char &op); virtual void TimerHandler(unsigned int num); virtual void AddMapCycles(unsigned int num) { AddCycles(num); } virtual unsigned int CpuCycles(void) { return Cycles(); }public: cN2Prov0101(int Id, int Flags); virtual bool PostProcAU(int id, unsigned char *data); virtual int ProcessBx(unsigned char *data, int len, int pos); virtual int ProcessEx(unsigned char *data, int len, int pos); virtual int RunEmu(unsigned char *data, int len, unsigned short load, unsigned short run, unsigned short stop, unsigned short fetch, int fetch_len); virtual void PostDecrypt(bool ecm) { PostDecryptSetup(ecm); } };static cN2ProvLinkReg<cN2Prov0101,0x0101,(N2FLAG_MECM|N2FLAG_POSTAU|N2FLAG_Bx|N2FLAG_Ex)> staticPL0101;cN2Prov0101::cN2Prov0101(int Id, int Flags):cN2Prov(Id,Flags){ mecmAddr[0]=0x91d7; mecmAddr[1]=0x92d7; mecmKeyId=0x106; seedSize=10; desSize=16; hwMapper=0; SetMapIdent(Id); hasReadHandler=true;}void cN2Prov0101::DynamicHD(unsigned char *hd, const unsigned char *ed){ hd[5]=ed[5]; hd[6]=(ed[7]&0xEF) | ((ed[6]&0x40)>>2); hd[7]=ed[8]; hd[8]=(ed[9]&0x7F) | ((ed[6]&0x20)<<2); hd[9]=ed[6]&0x80;}bool cN2Prov0101::Algo(int algo, const unsigned char *hd, unsigned char *hw){ if(algo!=0x40 && algo!=0x60) { PRINTF(L_SYS_ECM,"%04X: unknown MECM algo %02x",id,algo); return false; } if(!Init(id,102)) { PRINTF(L_SYS_ECM,"%04X: failed to initialize ROM",id); return false; } unsigned char keyNr=(algo>>5)&0x01; unsigned char mecmCode[256]; GetMem(mecmAddr[keyNr],mecmCode,256,0x80); cPlainKey *pk; unsigned char ideaKey[16]; if(!(pk=keys.FindKey('N',mecmKeyId,keyNr,sizeof(ideaKey)))) { PRINTF(L_SYS_KEY,"missing %04x %02x MECM key",mecmKeyId,keyNr); return false; } pk->Get(ideaKey); idea.SetEncKey(ideaKey,&ks); for(int i=0x100-8; i>=8; i-=8) { idea.Encrypt(mecmCode+i,8,mecmCode+i,&ks,0); xxor(mecmCode+i,8,mecmCode+i,mecmCode+i-8); } idea.Encrypt(mecmCode,8,mecmCode,&ks,0); HEXDUMP(L_SYS_RAWECM,mecmCode,sizeof(mecmCode),"decrypted MECM code"); // check signature unsigned char data[256];
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?