📄 tps.c
字号:
memcpy(&tmp[4+16],&tkey[2],16); tkey+=18; if(memcmp(tkey,startse,sizeof(startse))) continue; memcpy(&tmp[4+32],&tkey[2],16); cTpsKey *k=new cTpsKey; if(k) { k->Set(tmp); nlist->Add(k); } } PRINTF(L_SYS_TPSAU,"got %d keys from AU data",nlist->Count()); bool res=nlist->Count()>0; Join(nlist); return res;}/*bool cTpsKeys::LoadBin(void){ static const unsigned char mark[] = { 'T','P','S',0 }; cFileMap *tpsbin=filemaps.GetFileMap(TPSBIN,FILEMAP_DOMAIN,false); if(!tpsbin) { PRINTF(L_SYS_TPS,"no filemap for "TPSBIN); return false; } else if(!tpsbin->Map()) { PRINTF(L_SYS_TPS,"mapping failed for "TPSBIN); return false; } else if(tpsbin->Size()<65536 || memcmp(mark,tpsbin->Addr()+32,sizeof(mark)) || memcmp(mark,tpsbin->Addr()+48,sizeof(mark))) { PRINTF(L_SYS_TPS,TPSBIN" format not recognised"); tpsbin->Unmap(); return false; } int size=tpsbin->Size()-56; cSimpleList<cTpsKey> *nlist=new cSimpleList<cTpsKey>; for(int i=68; i<size; i+=56) { const unsigned char *a=tpsbin->Addr()+i; if(*((const unsigned int *)a)==0x00000000L || *((const unsigned int *)a)==0xFFFFFFFFL) break; unsigned char tmp[56]; DecryptBin(a,tmp); cTpsKey *k=new cTpsKey; if(k) { k->Set(tmp); nlist->Add(k); } } tpsbin->Unmap(); PRINTF(L_SYS_TPSAU,"loaded %d keys from "TPSBIN" file",nlist->Count()); Join(nlist); return true;}void cTpsKeys::DecryptBin(const unsigned char *in, unsigned char *out){ unsigned int var2=*((unsigned int *)in); *((unsigned int *)out)=var2; for(int i=0; i<13; i++) { in+=4; out+=4; var2=(var2<<3) | (var2>>(32-3)); unsigned int var1=*((unsigned int *)in) ^ var2; *((unsigned int *)out)=(var1<<(i+2)) | (var1>>(32-(i+2))); }}*/bool cTpsKeys::ParseLine(const char *line, bool fromCache){ unsigned char tmp[60]; if(line[0]=='X') { if(line[1]=='S') { if(algomem) PRINTF(L_SYS_TPS,"multiple start extentions during cache load"); if(sscanf(&line[2],"%x %x %x %x",&algolen,&cb1off,&cb2off,&cb3off)==4) { free(algomem); if((algomem=MALLOC(unsigned char,algolen))) { algoread=0; return true; } else PRINTF(L_SYS_TPS,"no memory for algo"); } else PRINTF(L_SYS_TPS,"bad format in start extention"); } else if(line[1]=='C') { if(algomem) { int off, len; unsigned int crc; if(sscanf(&line[2],"%x %x %n",&off,&crc,&len)==2) { line+=len+2; unsigned char buff[210]; if((len=GetHex(line,buff,200,false))) { if(crc==crc32_le(0,buff,len) && off>=0 && off+len<=algolen) { memcpy(&algomem[off],buff,len); algoread+=len; if(algoread==algolen) { RegisterAlgo3(algomem,cb1off,cb2off,cb3off,algolen); free(algomem); algomem=0; } return true; } } } PRINTF(L_SYS_TPS,"bad format in code extention"); } else PRINTF(L_SYS_TPS,"unexpected code extention"); } else PRINTF(L_SYS_TPS,"unknown extention during cache load"); } else { if(GetHex(line,tmp,sizeof(tmp))) { unsigned int crc=crc32_le(0,&tmp[4],sizeof(tmp)-4); if(*((unsigned int *)tmp)==crc) { cTpsKey *k=new cTpsKey; if(k) { k->Set(&tmp[4]); list->Add(k); } return true; } else PRINTF(L_SYS_TPS,"CRC failed during cache load"); } } return false;}bool cTpsKeys::Save(FILE *f){ cMutexLock lock(this); bool res=true; char str[420]; for(cTpsKey *k=list->First(); k; k=list->Next(k)) { unsigned char tmp[60]; k->Put(&tmp[4]); *((unsigned int *)tmp)=crc32_le(0,&tmp[4],sizeof(tmp)-4); fprintf(f,"%s\n",HexStr(str,tmp,sizeof(tmp))); res=(ferror(f)==0 && res); } unsigned char *mem; int len=0, cb1=0, cb2=0, cb3=0; if((mem=DumpAlgo3(len,cb1,cb2,cb3))) { fprintf(f,"XS %04X %04X %04X %04X\n",len,cb1,cb2,cb3); res=(ferror(f)==0 && res); for(int i=0; i<len; i+=200) { int l=min(200,len-i); fprintf(f,"XC %04X %08X %s\n",i,crc32_le(0,&mem[i],l),HexStr(str,&mem[i],l)); res=(ferror(f)==0 && res); } free(mem); } Modified(!res); return res;}// -- cTpsAuHook ---------------------------------------------------------------#define AUSID 0x12C0cTpsAuHook::cTpsAuHook(void):cLogHook(HOOK_TPSAU,"tpsau"){ mod=0; pmtpid=aupid=-1; pids.AddPid(0x0000,0x00,0xff); // PAT}cTpsAuHook::~cTpsAuHook(){ delete mod;}void cTpsAuHook::Process(int pid, unsigned char *data){ if(data) { if(pid==0) { // PAT SI::PAT pat(data,false); if(pat.CheckCRCAndParse()) { SI::PAT::Association assoc; for(SI::Loop::Iterator it; pat.associationLoop.getNext(assoc,it);) { if(!assoc.isNITPid() && assoc.getServiceId()==AUSID) { pmtpid=assoc.getPid(); PRINTF(L_SYS_TPSAU,"got PMT pid %04x for SID %04x",pmtpid,AUSID); cPid *pid=pids.First(); if(pid && pid->filter) { pid->filter->Start(pmtpid,0x02,0xFF,0x00,false); pid->filter->Flush(); } else PRINTF(L_GEN_DEBUG,"internal: no pid/filter in cTpsAuHook/pat"); return; } } PRINTF(L_SYS_TPSAU,"no PMT pid found for SID %04x",AUSID); BailOut(); } } else if(pid==pmtpid) { // PMT SI::PMT pmt(data,false); if(pmt.CheckCRCAndParse() && pmt.getServiceId()==AUSID) { SI::PMT::Stream stream; for(SI::Loop::Iterator it; pmt.streamLoop.getNext(stream,it); ) { if(stream.getStreamType()==0x05) { aupid=stream.getPid(); PRINTF(L_SYS_TPSAU,"got AU pid %04x",aupid); cPid *pid=pids.First(); if(pid && pid->filter) { pid->filter->Start(aupid,0x87,0xFF,0x00,false); pid->filter->Flush(); } else PRINTF(L_GEN_DEBUG,"internal: no pid/filter in cTpsAuHook/pmt"); return; } } PRINTF(L_SYS_TPSAU,"could not locate AU pid in PMT %04x data",pmtpid); BailOut(); } } else if(pid==aupid) { if(cOpenTVModule::Id(data)==2) { if(!mod) mod=new cOpenTVModule(data); if(mod) { int r=mod->AddPart(data,SCT_LEN(data)); if(r>0) { PRINTF(L_SYS_TPSAU,"received complete OpenTV module ID 2"); if(tpskeys.ProcessAu(mod)) BailOut(); r=-1; } if(r<0) { delete mod; mod=0; } } } } }}// -- cTPSDecrypt --------------------------------------------------------------unsigned char *cTPSDecrypt::mem=0;int cTPSDecrypt::memLen=0;int cTPSDecrypt::cb1off=0;int cTPSDecrypt::cb2off=0;int cTPSDecrypt::cb3off=0;cMutex cTPSDecrypt::st20Mutex;cST20 cTPSDecrypt::st20;bool cTPSDecrypt::st20Inited=false;void cTPSDecrypt::TpsDecrypt(unsigned char *data, short mode, const unsigned char *key){ switch(mode) { case 0: break; case 1: cAES::SetKey(key); cAES::Decrypt(data,16); break; case 2: cRC6::SetKey(key,16); cRC6::Decrypt(data); break; case 3: if(mem) { if(!DecryptAlgo3(key,data)) PRINTF(L_SYS_TPS,"decrypt failed in algo 3"); } else PRINTF(L_SYS_TPS,"no callbacks for algo 3 registered"); break; default: PRINTF(L_SYS_TPS,"unknown TPS decryption algo %d",mode); break; }}bool cTPSDecrypt::RegisterAlgo3(const unsigned char *data, int cb1, int cb2, int cb3, int kd){ cMutexLock lock(&st20Mutex); free(mem); if(!(mem=MALLOC(unsigned char,kd))) return false; memcpy(mem,data,kd); memLen=kd; cb1off=cb1; cb2off=cb2; cb3off=cb3; st20Inited=false; PRINTF(L_SYS_TPSAU,"registered callbacks for algo 3"); return true;}unsigned char *cTPSDecrypt::DumpAlgo3(int &len, int &cb1, int &cb2, int &cb3){ cMutexLock lock(&st20Mutex); if(!mem) return 0; unsigned char *buff=MALLOC(unsigned char,memLen); if(!buff) return 0; memcpy(buff,mem,memLen); len=memLen; cb1=cb1off; cb2=cb2off; cb3=cb3off; return buff;}bool cTPSDecrypt::InitST20(void){ if(!mem) return false; if(!st20Inited) { st20.SetFlash(mem,memLen); st20.SetRam(NULL,0x10000); st20Inited=true; } return true;}bool cTPSDecrypt::Handle80008003(const unsigned char *src, int len, unsigned char *dest){ cMutexLock lock(&st20Mutex); if(cb1off && InitST20()) { for(int i=0; i<len; i++) st20.WriteByte(RAMS+0x400+i,src[i]); st20.WriteShort(RAMS+0x0,0x8000); st20.WriteShort(RAMS+0x2,0x8003); st20.WriteWord(RAMS+0x8,RAMS+0x400); st20.Init(FLASHS+cb1off,RAMS+0xF000); st20.SetCallFrame(0,RAMS,0,0); int err=st20.Decode(1000); if(err<0) { PRINTF(L_SYS_TPSAU,"ST20 processing failed in callback1 (%d)",err); return false; } for(int i=0; i<0x2D; i++) dest[i]=st20.ReadByte(RAMS+0x400+i); return true; } return false;}bool cTPSDecrypt::DecryptAlgo3(const unsigned char *key, unsigned char *data){ cMutexLock lock(&st20Mutex); if(cb2off && cb3off && InitST20()) { for(int i=0; i<16; i++) st20.WriteByte(RAMS+0x400+i,key[i]); st20.Init(FLASHS+cb2off,RAMS+0xF000); st20.SetCallFrame(0,RAMS+0x400,RAMS+0x800,0); int err=st20.Decode(20000); if(err<0) { PRINTF(L_SYS_TPS,"ST20 processing failed in callback2 (%d)",err); return false; } for(int i=0; i<16; i++) st20.WriteByte(RAMS+0x400+i,data[i]); st20.Init(FLASHS+cb3off,RAMS+0xF000); st20.SetCallFrame(0,RAMS+0x400,RAMS+0x1000,RAMS+0x800); err=st20.Decode(40000); if(err<0) { PRINTF(L_SYS_TPS,"ST20 processing failed in callback3 (%d)",err); return false; } for(int i=0; i<16; i++) data[i]=st20.ReadByte(RAMS+0x1000+i); return true; } return false;}// -- cTPS ---------------------------------------------------------------------cTPS::cTPS(void){ sattime=0;}cTPS::~cTPS(){ delete sattime;}int cTPS::Decrypt(int cardNum, int Source, int Transponder, unsigned char *data, int len){ if(!sattime) { sattime=new cSatTime(cardNum,Source,Transponder); if(!sattime) { PRINTF(L_SYS_TPS,"failed to create time class"); return -1; } } time_t now=sattime->Now(); tpskeys.Check(now,cardNum); if(now<0) return -1; const cTpsKey *k=tpskeys.GetKey(now); if(!k) { PRINTF(L_SYS_TPS,"no TPS key available for current time of day"); return -1; } doPost=0; int opmode=k->Opmode(), doTPS=0, doPre=0, hasDF=0, ret=0; if((opmode&4) && data[0]==0xD2 && data[1]==0x01 && data[2]==0x01) { data+=3; len-=3; ret=3; if(data[0]==0x90) PRINTF(L_SYS_TPS,"TPS v1 is no longer supported"); if(data[0]==0x40) data[0]=0x90; doTPS=1; } for(int i=0; i<len; i+=data[i+1]+2) switch(data[i]) { case 0xDF: if(!(opmode&4)) doTPS =(0x6996>>((data[i+2]&0xF)^(data[i+2]>>4)))&1; if(opmode&8) doPre =(0x6996>>((data[i+3]&0xF)^(data[i+3]>>4)))&1; if(opmode&16) doPost=(0x6996>>((data[i+4]&0xF)^(data[i+4]>>4)))&1; hasDF=1; break; case 0xEA: if(doPre) TpsDecrypt(&data[i+2],k->Mode(0),k->Key(0)); if(doTPS) TpsDecrypt(&data[i+2],(hasDF)?k->Mode(2):1,k->Key(2)); break; } postMode=k->Mode(1); memcpy(postKey,k->Key(1),sizeof(postKey)); return ret;}void cTPS::PostProc(unsigned char *cw){ if(doPost) TpsDecrypt(cw,postMode,postKey);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -