📄 seca.c
字号:
virtual void PreSSE(unsigned char *data, int pos) {} virtual void PostSSE(unsigned char *data, int pos) {} virtual void SignatureMod(unsigned char *MD, const unsigned char *PK) {} virtual void PreCW(unsigned char *data) {} virtual void PostCW(unsigned char *data) {} virtual void ChainTableXor(unsigned char *data, unsigned short index)=0; virtual bool DoSigCheck(void) { return true; } // virtual bool Init(void); void CalcSHASignature(const unsigned char *data, int n, unsigned char *signature, bool PadMode=true); bool DecryptSE(unsigned char *data, const unsigned char *key, int n, int start, const unsigned char *T1, const unsigned char *T2); bool Matches(unsigned short Id) const { return Id==id; } // const unsigned char *T1(int index) const; const unsigned char *T2(int index) const; const struct Perm *P(int index) const; inline const unsigned char *MT(void) const { return mask->Addr(); } inline int MTSize(void) const { return pData->MTSize; } inline const unsigned char *FP(void) const { return pData->FP; } };cSeca2Prov::cSeca2Prov(unsigned short Id){ id=Id; pData=0; perm=0; hash=0; mask=0;}cSeca2Prov::~cSeca2Prov(){ if(hash) hash->Unmap(); if(mask) mask->Unmap();}bool cSeca2Prov::Init(void){ hash=GetMap("hash",1536,false); mask=GetMap("mt",pData->MTLoadSize,false); if(!hash || !mask) return false; return true;}cFileMap *cSeca2Prov::GetMap(const char *type, int size, bool generic) const{ char name[32]; snprintf(name,sizeof(name),generic ? "s2_%s.bin" : "s2_%s_%04x.bin",type,pData->LoadId); cFileMap *map=filemaps.GetFileMap(name,FILEMAP_DOMAIN,false); if(!map) PRINTF(L_SYS_CRYPTO,"no filemap for %s",name); else if(!map->Map()) { PRINTF(L_SYS_CRYPTO,"mapping failed for %s",name); map=0; } else if(map->Size()<size) { PRINTF(L_SYS_CRYPTO,"%s file %s has wrong size (has=%d wanted=%d)",type,name,map->Size(),size); map->Unmap(); map=0; } return map;}// Hash file layout is (Yankse style):// Table T1 for 9x, // Table T1 for Bx,// Table T1 for FX,// Table T2 for 9x, // Table T2 for Bx,// Table T2 for FX (total: 1536 bytes)const unsigned char *cSeca2Prov::T1(int index) const{ static int idxTrans[] = { 0,1,2,2 }; if(index>=0 && index<=3) { return hash->Addr()+(idxTrans[index]*256); } PRINTF(L_SYS_CRYPTO,"bad T1 table index %d",index); return 0;}const unsigned char *cSeca2Prov::T2(int index) const{ static int idxTrans[] = { 0,1,2,2 }; if(index>=0 && index<=3) { return hash->Addr()+(idxTrans[index]*256)+768; } PRINTF(L_SYS_CRYPTO,"bad T2 table index %d",index); return 0;}const struct Perm *cSeca2Prov::P(int index) const{ if(index>=0 && index<MAX_PERMS && perm) { return &perm[index]; } PRINTF(L_SYS_CRYPTO,"no perm table or bad index %d",index); return 0;}unsigned short cSeca2Prov::Sum(const unsigned char *data, int n) const{ unsigned int sum=0; for(int i=1; i<n; i+=2) sum+=((data[i-1]<<8)+data[i]); if(n&1) sum+=(data[n-1]<<4); return sum&0x3FFF;}bool cSeca2Prov::DecryptSE(unsigned char *data, const unsigned char *key, int n, int start, const unsigned char *T1, const unsigned char *T2){ const int sigStart=n-data[n-1]-9; // 82 <8 bytes> P5(sigStart) const int encrLen=sigStart-16;#ifdef DEBUG_SECA_EXTRA if(encrLen>=n || encrLen<0) printf("encrLen error in SE\n"); if(sigStart<16) printf("sigStart error in SE\n");#endif if(encrLen>=n || encrLen<0 || sigStart<16) return false; Decrypt(data+sigStart-8,key,T1,T2); ChainTableXor(data+sigStart-8,Sum(data+start,sigStart-8-start)); int i; for(i=start; i<encrLen; i+=8) { Decrypt(data+i,key,T1,T2); ChainTableXor(data+i,Sum(&data[i+8],8)); } int restBytes=sigStart&0x07; if(!restBytes) restBytes=8; // Last Block unsigned char lastBlock[8]; memset(lastBlock,0,sizeof(lastBlock)); memcpy(lastBlock,data+sigStart-restBytes,restBytes); Decrypt(lastBlock,key,T1,T2); Decrypt(data+i,key,T1,T2); ChainTableXor(data+i,Sum(lastBlock,sizeof(lastBlock))); return true;}void cSeca2Prov::CalcSHASignature(const unsigned char *data, int n, unsigned char *signature, bool PadMode){ SHA_CTX ctx; SHA1_Init(&ctx); SHA1_Update(&ctx,data,n); unsigned char Pad=0; if(PadMode) { unsigned char End=pData->SHA1End; SHA1_Update(&ctx,&End,1); int l=(n&63)+1; Pad=pData->SHA1Pad; if(l>62) { for(; l<64; l++) SHA1_Update(&ctx,&Pad,1); l=0; } for(; l<62; l++) SHA1_Update(&ctx,&Pad,1); unsigned short s=bswap_16(n); SHA1_Update(&ctx,&s,2); } else for(; n&63; n++) SHA1_Update(&ctx,&Pad,1); *((unsigned int *)(signature ))=bswap_32(ctx.h0); *((unsigned int *)(signature+ 4))=bswap_32(ctx.h1); *((unsigned int *)(signature+ 8))=bswap_32(ctx.h2); *((unsigned int *)(signature+12))=bswap_32(ctx.h3); *((unsigned int *)(signature+16))=bswap_32(ctx.h4);}// -- cSecaProviders & cSecaProviderLink ---------------------------------------class cSeca2ProvLink {friend class cSeca2Providers;private: cSeca2ProvLink *next; const unsigned short *ids;public: cSeca2ProvLink(const unsigned short *Ids); bool CanHandle(unsigned short Id); virtual cSeca2Prov *Create(unsigned short Id)=0; virtual ~cSeca2ProvLink() {}; };template<class CC> class cSeca2ProvLinkReg : public cSeca2ProvLink {public: cSeca2ProvLinkReg(const unsigned short *Ids):cSeca2ProvLink(Ids) {} virtual cSeca2Prov *Create(unsigned short Id) { return new CC(Id); } };class cSeca2Providers {friend class cSeca2ProvLink;private: static cSeca2ProvLink *first; // static void Register(cSeca2ProvLink *spl);public: static cSeca2Prov *GetProv(unsigned short id); };cSeca2ProvLink *cSeca2Providers::first=0;void cSeca2Providers::Register(cSeca2ProvLink *spl){ LBSTART(L_CORE_DYN); LBPUT("seca2prov: registering Seca2 provider"); for(int i=0; spl->ids[i]; i++) LBPUT(" %.4x",spl->ids[i]); LBEND(); spl->next=first; first=spl;}cSeca2Prov *cSeca2Providers::GetProv(unsigned short id){ cSeca2ProvLink *spl=first; while(spl) { if(spl->CanHandle(id)) { cSeca2Prov *sp=spl->Create(id); if(sp && sp->Init()) return sp; delete sp; } spl=spl->next; } return 0;}cSeca2ProvLink::cSeca2ProvLink(const unsigned short *Ids){ ids=Ids; cSeca2Providers::Register(this);}bool cSeca2ProvLink::CanHandle(unsigned short Id){ for(int i=0; ids[i]; i++) if(ids[i]==Id) return true; return false;}// -- cSeca2ProvSSE ------------------------------------------------------------#define beforeSig (pos-8)#define afterSig (pos+1)class cSeca2ProvSSE : public cSeca2Prov {private: virtual void PreSSECore(unsigned char *buf, const unsigned char *data, int i)=0; virtual void PostSSECore1(unsigned char *data, int pos)=0; virtual void PostSSECore2(unsigned char *buf, const unsigned char *data, int pos)=0; virtual void PostSSECore3(unsigned char *data, const unsigned char *buf, int pos)=0; virtual void PostSSECore4(unsigned char *data, int pos)=0;protected: cDes des; cFileMap *sse, *sseP, *cw; // virtual bool InitSSE(void)=0; virtual void PreSSE(unsigned char *data, int pos); virtual void PostSSE(unsigned char *data, int pos); // inline const unsigned char *SSET1(void) const { return sse->Addr(); } inline const unsigned char *SSET2(void) const { return sse->Addr()+3072; } inline const unsigned char *SSEPT1(void) const { return sseP->Addr(); } inline const unsigned char *SSEPT2(void) const { return sseP->Addr()+80; } inline const unsigned char *CWT1(void) const { return cw->Addr(); }public: cSeca2ProvSSE(unsigned short Id); virtual ~cSeca2ProvSSE(); virtual bool Init(void); };cSeca2ProvSSE::cSeca2ProvSSE(unsigned short Id):cSeca2Prov(Id),des(secaPC1,secaPC2){ sse=0; sseP=0; cw=0;}cSeca2ProvSSE::~cSeca2ProvSSE(){ if(sse) sse->Unmap(); if(sseP) sseP->Unmap(); if(cw) cw->Unmap();}bool cSeca2ProvSSE::Init(void){ return InitSSE() && cSeca2Prov::Init();}void cSeca2ProvSSE::PreSSE(unsigned char *data, int pos){ const unsigned char *T1=SSEPT1(); unsigned char tmpBuf[80]; data+=pos+5; // Start at offset 5 for(int i=4; i>=0; i--) { int j=i*16; PreSSECore(&tmpBuf[j],&data[j],i); } for(int i=79; i>=0; i--) data[i]=tmpBuf[i]^T1[i];}void cSeca2ProvSSE::PostSSE(unsigned char *data, int pos){ PostSSECore1(data,pos); // create the SHA hash buffer unsigned char tmpBuf[64]; memcpy(tmpBuf+0,&data[beforeSig+0],4); memcpy(tmpBuf+4,&data[afterSig +4],4); PostSSECore2(tmpBuf+8,data,pos); // Calc Signature of the generated buffer here unsigned char MD[20]; CalcSHASignature(tmpBuf,sizeof(tmpBuf),MD,false); // Prepare DES data memcpy(tmpBuf+0,&data[beforeSig+4],4); memcpy(tmpBuf+4,&data[afterSig +0],4); // DES Enrypt des.Des(tmpBuf,MD,SECA_DES_ENCR); // modify data with encrypted DES data PostSSECore3(data,tmpBuf,pos); // save the signature memcpy(tmpBuf,data+afterSig,8); PostSSECore4(data,pos); // put the signature in the data memcpy(data+beforeSig,tmpBuf,8);}// -- France -------------------------------------------------------------------class cSeca2ProvFR : public cSeca2ProvSSE {private: virtual void PreSSECore(unsigned char *buf, const unsigned char *data, int i); virtual void PostSSECore1(unsigned char *data, int pos); virtual void PostSSECore2(unsigned char *buf, const unsigned char *data, int pos); virtual void PostSSECore3(unsigned char *data, const unsigned char *buf, int pos); virtual void PostSSECore4(unsigned char *data, int pos);protected: virtual bool InitSSE(void); virtual void PostCW(unsigned char *data); virtual void ChainTableXor(unsigned char *data, unsigned short index); virtual void SignatureMod(unsigned char *MD, const unsigned char *PK);public: cSeca2ProvFR(unsigned short Id); };static const unsigned short IdsFR[] = { 0x80,0x81,0 };static cSeca2ProvLinkReg<cSeca2ProvFR> staticLinkFR(IdsFR);static const struct ProvData provDataFR = { 0x80,16895,16895,0x7F,0xF7, { 3, 0, 0, 0, 2, 4, 3, 0 } };cSeca2ProvFR::cSeca2ProvFR(unsigned short Id):cSeca2ProvSSE(Id){ pData=&provDataFR;}bool cSeca2ProvFR::InitSSE(void){ sse=GetMap("sse",5120,true); sseP=GetMap("sse",1104,false); cw=GetMap("cw",512,false); return sse && sseP && cw;}void cSeca2ProvFR::PreSSECore(unsigned char *buf, const unsigned char *data, int i){ const unsigned char *T1=SSET1(), *T2=SSET2(); buf[ 0]=data[0x06]^T2[i+0x0a]; buf[ 1]=data[0x01]^T2[i+0x00]; buf[ 2]=data[0x02]^T1[i+0x00]; buf[ 3]=data[0x03]^T2[i+0x04]; buf[ 4]=~data[0x04]; buf[ 5]=data[0x05]^T1[i+0x01]; buf[ 6]=data[0x00]^T2[i+0x0f]; buf[ 7]=data[0x07]^T1[i+0x02]; buf[ 8]=data[0x08]^T1[i+0x00]; buf[ 9]=data[0x0d]^T2[i+0x14]; buf[10]=data[0x0f]^T2[i+0x07]; buf[11]=~data[0x0b]; buf[12]=data[0x0c]^T1[i+0x00]; buf[13]=data[0x09]^T2[i+0x19]; buf[14]=data[0x0e]^T2[i+0x1e]; buf[15]=data[0x0a]^T1[i+0x01];}void cSeca2ProvFR::PostSSECore1(unsigned char *data, int pos){ data[beforeSig+0]^=-(0x2d); data[beforeSig+1]-=0x22; data[beforeSig+2]^=0x1d; data[beforeSig+3]^=-(0x68); data[beforeSig+4] =~data[beforeSig + 4]; data[beforeSig+5]^=0x26; data[beforeSig+6]^=0x09; data[beforeSig+7]-=0x3e; data[afterSig +0]^=-(0x5d); data[afterSig +1]-=0x74; data[afterSig +2]^=0x2d; data[afterSig +3]^=-(0x2a); data[afterSig +4]+=0x0d; data[afterSig +5]^=-(0x6c); data[afterSig +6]^=-(0x76); data[afterSig +7]+=0x31;}void cSeca2ProvFR::PostSSECore2(unsigned char *buf, const unsigned char *data, int pos){ const unsigned char *T1=SSEPT2(); memcpy(buf, &T1[data[afterSig+4]+0x48], 56);}void cSeca2ProvFR::PostSSECore3(unsigned char *data, const unsigned char *buf, int pos){ data[beforeSig+4]=buf[5]; data[beforeSig+5]=buf[4];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -