📄 seca.cpp
字号:
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)
ds(printf("seca-prov: no filemap for %s\n",name))
else if(!map->Map()) {
ds(printf("seca-prov: mapping failed for %s\n",name))
map=0;
}
else if(map->Size()<size) {
ds(printf("seca-prov: %s file %s has wrong size (has=%d wanted=%d)\n",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);
}
ds(printf("seca-prov: bad T1 table index %d\n",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;
}
ds(printf("seca-prov: bad T2 table index %d\n",index))
return 0;
}
const struct Perm *cSeca2Prov::P(int index) const
{
if(index>=0 && index<MAX_PERMS && perm) {
return &perm[index];
}
ds(printf("seca-prov: no perm table or bad index %d\n",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)
{
dyn(printf("seca2prov: registering Seca2 provider"))
for(int i=0; spl->ids[i]; i++) dyn(printf(" %.4x",spl->ids[i]))
dyn(printf("\n"))
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];
data[beforeSig+6]=buf[7];
data[beforeSig+7]=buf[2];
data[afterSig +0]=buf[3];
data[afterSig +1]=buf[1];
data[afterSig +2]=buf[0];
data[afterSig +3]=buf[6];
}
void cSeca2ProvFR::PostSSECore4(unsigned char *data, int pos)
{
data[afterSig+0]=data[beforeSig+3]^0x3e;
data[afterSig+1]=data[beforeSig+1]^0x5e;
data[afterSig+2]=data[beforeSig+5]^0x2f;
data[afterSig+3]=data[beforeSig+0]^0x77;
data[afterSig+4]=data[beforeSig+6]^-(0x4b);
data[afterSig+5]=data[beforeSig+2]^-(0x38);
data[afterSig+6]=data[beforeSig+7]^0x29;
data[afterSig+7]=data[beforeSig+4]^0x2b;
}
void cSeca2ProvFR::PostCW(unsigned char *data)
{
const unsigned char *T1=SSET1(), *T2=SSET2(), *T3=SSEPT2(), *T4=CWT1();
unsigned int idx;
unsigned char key[8];
idx=((data[0]<<8)|data[1]); key[0]=T3[idx & 0x3FF];
idx=(idx + key[0]); key[1]=T3[idx & 0x3FF];
idx=((data[2]<<8)|data[3]); key[2]=T4[idx & 0x1FF];
idx=idx + key[2]; key[3]=T4[idx & 0x1FF];
idx=((data[8+4]<<8)|data[8+5]); key[4]=T2[idx & 0x7FF];
idx=idx + key[4]; key[5]=T2[idx & 0x7FF];
idx=((data[8+6]<<8)|data[8+7]); key[6]=T1[idx & 0xBFF];
idx=idx + key[6]; key[7]=T1[idx & 0xBFF];
des.Des(data+4,key,SECA_DES_ENCR);
}
void cSeca2ProvFR::ChainTableXor(unsigned char *data, unsigned short index)
{
static const unsigned char tabIdx[] = { 0x00, 0x08, 0x03, 0x1F, 0x06, 0x32, 0x12, 0x0C };
static const unsigned char tabXor[] = { 0x77, 0x2B, 0xC8, 0xEE, 0x2F, 0xD3, 0x22, 0x29 };
static const unsigned char tabPos[] = { 0, 2, 1, 6, 4, 5, 7, 3 };
unsigned int idx1, idx2;
unsigned char xorVal=0;
const unsigned char *T1=MT(), *T2=SSET1();
idx1 = (index^0x17AC) & 0x3FFF;
idx2 = idx1 & 0xBFF;
for(int i=0; i<8; i++) {
idx1 = (idx1 + tabIdx[i]) & 0x3FFF;
idx2 = (idx2 + xorVal) & 0xBFF;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -