📄 sc-videoguard2.c
字号:
struct CmdTabEntry { unsigned char cla; unsigned char cmd; unsigned char len; unsigned char mode;};struct CmdTab { unsigned char index; unsigned char size; unsigned char Nentries; unsigned char dummy; CmdTabEntry e[1];};class CmdTable {private: struct CmdTab *tab;public: CmdTable(const unsigned char *mem, int size); ~CmdTable(); bool GetInfo(const unsigned char *cmd, unsigned char &rlen, unsigned char &rmode); };CmdTable::CmdTable(const unsigned char *mem, int size){ tab=(struct CmdTab *)new unsigned char[size]; memcpy(tab,mem,size);}CmdTable::~CmdTable(){ delete tab;}bool CmdTable::GetInfo(const unsigned char *cmd, unsigned char &rlen, unsigned char & rmode){ struct CmdTabEntry *pcte=tab->e; for(int i=0; i<tab->Nentries; i++,pcte++) if(cmd[1]==pcte->cmd) { rlen=pcte->len; rmode=pcte->mode; return true; } return false;}// -- cSmartCardVideoGuard2 -----------------------------------------------------------#define BASEYEAR 2000 // for date calculationclass cSmartCardVideoGuard2 : public cSmartCard, private cIdSet {private: unsigned char CW1[8], CW2[8]; unsigned char cardID[4], groupID[4], boxID[4]; unsigned int CAID; cCamCryptVG2 state; CmdTable *cmdList;public: void ReadTiers(void); void RevDateCalc(const unsigned char *Date, int &year, int &mon, int &day, int &hh, int &mm, int &ss); void Datecalc(int year, int mon, int day, int hh, int mm, int ss , unsigned char * Date); int DoCmd(const unsigned char *ins, const unsigned char *txbuff=0, unsigned char *rxbuff=0); int ReadCmdLen(const unsigned char *cmd);public: cSmartCardVideoGuard2(void); ~cSmartCardVideoGuard2(); virtual bool Init(void); virtual bool Decode(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw); virtual bool Update(int pid, int caid, const unsigned char *data); virtual bool CanHandle(unsigned short SysId); };static const struct StatusMsg msgs[] = { { { 0x90,0x00 }, "Instruction executed without errors, noupdate, nofilter, IRD# not set", true }, { { 0x90,0x01 }, "Instruction executed without errors, update, nofilter, IRD# not set", true }, { { 0x90,0x20 }, "Instruction executed without errors, noupdate, nofilter, IRD# set", true }, { { 0x90,0x21 }, "Instruction executed without errors, update, nofilter, IRD# set", true }, { { 0x90,0x80 }, "Instruction executed without errors, noupdate, filter, IRD# not set", true }, { { 0x90,0x81 }, "Instruction executed without errors, update, filter, IRD# not set", true }, { { 0x90,0xa0 }, "Instruction executed without errors, noupdate, filter, IRD# set", true }, { { 0x90,0xa1 }, "Instruction executed without errors, update, filter, IRD# set", true }, { { 0x91,0x00 }, "Instruction executed without errors, noupdate, nofilter, IRD# not set", true }, { { 0x91,0x01 }, "Instruction executed without errors, update, nofilter, IRD# not set", true }, { { 0x91,0x20 }, "Instruction executed without errors, noupdate, nofilter, IRD# set", true }, { { 0x91,0x21 }, "Instruction executed without errors, update, nofilter, IRD# set", true }, { { 0x91,0x80 }, "Instruction executed without errors, noupdate, filter, IRD# not set", true }, { { 0x91,0x81 }, "Instruction executed without errors, update, filter, IRD# not set", true }, { { 0x91,0xa0 }, "Instruction executed without errors, noupdate, filter, IRD# set", true }, { { 0x91,0xa1 }, "Instruction executed without errors, update, filter, IRD# set", true }, { { 0xFF,0xFF }, 0, false } };static const struct CardConfig cardCfg = { SM_8O2,2000,1400 };cSmartCardVideoGuard2::cSmartCardVideoGuard2(void):cSmartCard(&cardCfg,msgs){ cmdList=0;}cSmartCardVideoGuard2::~cSmartCardVideoGuard2(void){ delete cmdList;}bool cSmartCardVideoGuard2::CanHandle(unsigned short SysId){ return SysId==CAID;}bool cSmartCardVideoGuard2::Init(void){ static const unsigned char vg2Hist[] = { 'i',0xff,'J','P' }; if(atr->histLen<4 || memcmp(&atr->hist[3],vg2Hist,4)) { PRINTF(L_SC_INIT,"doesn't look like a VideoGuard2 card"); return false; } infoStr.Begin(); infoStr.Strcat("VideoGuard2 smartcard\n"); snprintf(idStr,sizeof(idStr),"%s (%c%c.%d)",SC_NAME,atr->hist[10],atr->hist[11],atr->hist[12]); ResetIdSet(); delete cmdList; cmdList=0; static unsigned char ins7401[] = { 0xD0,0x74,0x01,0x00,0x00 }; int l; if((l=ReadCmdLen(ins7401))<0) return false; ins7401[4]=l; unsigned char buff[256]; if(!IsoRead(ins7401,buff) || !Status()) { PRINTF(L_SC_ERROR,"failed to read cmd list"); return false; } cmdList=new CmdTable(buff,l); static const unsigned char ins7416[5] = { 0xD0,0x74,0x16,0x00,0x00 }; if(DoCmd(ins7416)<0 || !Status()) { PRINTF(L_SC_ERROR,"cmd 7416 failed"); return false; } static const unsigned char ins36[5] = { 0xD0,0x36,0x00,0x00,0x00 }; bool boxidOK=false; if((l=DoCmd(ins36,0,buff))>0 && Status()) for(int i=0; i<l ;i++) { if(buff[i]==0x00 && buff[i+1]==0xF3) { memcpy(&boxID,&buff[i+2],sizeof(boxID)); boxidOK=true; break; } } if(!boxidOK) { cSmartCardDataVideoGuard2 cd(dtBoxId); cSmartCardDataVideoGuard2 *entry=(cSmartCardDataVideoGuard2 *)smartcards.FindCardData(&cd); if(entry) { memcpy(&boxID,entry->boxid,sizeof(boxID)); boxidOK=true; } } if(!boxidOK) { PRINTF(L_SC_ERROR,"no boxID available"); return false; } static const unsigned char ins4C[5] = { 0xD0,0x4C,0x00,0x00,0x00 }; static unsigned char payload4C[9] = { 0,0,0,0, 3,0,0,2,4 }; memcpy(payload4C,boxID,4); if(DoCmd(ins4C,payload4C)<0 || !Status()) { PRINTF(L_SC_ERROR,"sending boxid failed"); return false; } static const unsigned char ins58[5] = { 0xD0,0x58,0x00,0x00,0x00 }; if(DoCmd(ins58,0,buff)<0 || !Status()) { PRINTF(L_SC_ERROR,"failed to read card details"); return false; } CAID=WORD(buff,0x1D,0xFFFF); memcpy(&cardID,&buff[8],4); memcpy(&groupID,&buff[8],4); groupID[3]=0; SetCard(new cCardNDS(cardID)); AddProv(new cProviderNDS(groupID)); char str[20], str2[20]; infoStr.Printf("Cardtype: %c%c.%d\n" "BoxID %s Caid %04x CardID %s\n", atr->hist[10],atr->hist[11],atr->hist[12],HexStr(str,boxID,4),CAID,HexStr(str2,cardID,4)); PRINTF(L_SC_INIT,"cardtype: %c%c.%d boxID %s caid %04x cardID %s",atr->hist[10],atr->hist[11],atr->hist[12],HexStr(str,boxID,4),CAID,HexStr(str2,cardID,4)); cSmartCardDataVideoGuard2 cd(dtSeed); cSmartCardDataVideoGuard2 *entry=(cSmartCardDataVideoGuard2 *)smartcards.FindCardData(&cd); if(!entry) { PRINTF(L_SC_ERROR,"no NDS seed available"); return false; } state.SetSeed(entry->seed0,entry->seed1); unsigned char tbuff[64]; state.GetCamKey(tbuff); static const unsigned char insB4[5] = { 0xD0,0xB4,0x00,0x00,0x00 }; if(DoCmd(insB4,tbuff)<0 || !Status()) { PRINTF(L_SC_ERROR,"cmd D0B4 failed"); return false; } static const unsigned char insBC[5] = { 0xD0,0xBC,0x00,0x00,0x00 }; if(DoCmd(insBC)<0 || !Status()) { PRINTF(L_SC_ERROR,"cmd D0BC failed"); return false; } static const unsigned char insBE[5] = { 0xD3,0xBE,0x00,0x00,0x00 }; if(DoCmd(insBE)<0 || !Status()) { PRINTF(L_SC_ERROR,"cmd D3BE failed"); return false; } static const unsigned char ins58a[5] = { 0xD1,0x58,0x00,0x00,0x00 }; if(DoCmd(ins58a)<0 || !Status()) { PRINTF(L_SC_ERROR,"cmd D158 failed"); return false; } static const unsigned char ins4Ca[5] = { 0xD1,0x4C,0x00,0x00,0x00 }; if(DoCmd(ins4Ca,payload4C)<0 || !Status()) { PRINTF(L_SC_ERROR,"cmd D14C failed"); return false; } ReadTiers(); return true;}bool cSmartCardVideoGuard2::Decode(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw){ static unsigned char ins40[5] = { 0xD1,0x40,0x40,0x80,0xFF }; static const unsigned char ins54[5] = { 0xD3,0x54,0x00,0x00,0x00 }; int posECMpart2=data[6]+7; int lenECMpart2=data[posECMpart2]+1; unsigned char tbuff[264]; tbuff[0]=0; memcpy(&tbuff[1],&data[posECMpart2+1],lenECMpart2); ins40[4]=lenECMpart2; if(DoCmd(ins40,tbuff)>0 && Status()) { if(DoCmd(ins54)>0 && Status()) { if(data[0]&1) memcpy(cw+8,CW1,8); else memcpy(cw+0,CW1,8); return true; } } return false;}bool cSmartCardVideoGuard2::Update(int pid, int caid, const unsigned char *data){ static unsigned char ins42[5] = { 0xD1,0x40,0x00,0x00,0xFF }; if(MatchEMM(data)) { const unsigned char *payloaddata=cParseNDS::PayloadStart(data); //points to 02 xx yy int lenEMM; switch(payloaddata[0]) { case 2: lenEMM=payloaddata[payloaddata[1]+2]; payloaddata+=3+payloaddata[1]; // skip len specifier break; default:// di(printf("scvg2: ***ERROR***: EMM: bad payload type byte %02x\n",payloaddata[0]));// DUMP3("VG2EMM",data,32); return false; }// di(printf("scvg2: EMM: pid %d (%x) caid %d (%x) len %d (%x)\n",pid,pid,caid,caid,lenEMM,lenEMM));// DUMP3("VG2EMM",data,32); if(lenEMM<=8 || lenEMM>188) {// di(printf("scvg2: ***ERROR***: EMM: len %d bad\n",lenEMM)); return false; } ins42[4]=lenEMM; if(DoCmd(ins42,payloaddata)>0 && Status()) return true; } return false;}/*bool cSmartCardVideoGuard2::ZKT(void){ static unsigned char payload4A[1] = { 0x01 }; static unsigned char ins4A[5] = { 0xD0,0x4A,0x15,0x01,0x01 }; DoCmd(ins4A,payload4A); static unsigned char ins5A1[5] = { 0xD0,0x5A,0x15,0x01,0x10 }; DoCmd(ins5A1); static unsigned char ins5A2[5] = { 0xD0,0x5A,0x11,0x02,0x40 }; DoCmd(ins5A2); DoCmd(ins4A,payload4A); DoCmd(ins5A1); static unsigned char ins5A3[5] = { 0xD0,0x5A,0x10,0x02,0x40 }; DoCmd(ins5A3); return true;}*/void cSmartCardVideoGuard2::ReadTiers(void){ static const unsigned char ins2a[5] = { 0xd0,0x2a,0x00,0x00,0x00 }; if(DoCmd(ins2a)<0 || !Status()) return; static unsigned char ins76[5] = { 0xd0,0x76,0x00,0x00,0x00 }; ins76[3]=0x7f; ins76[4]=2; unsigned char buff[270]; if(!IsoRead(ins76,buff) || !Status()) return; ins76[3]=0; ins76[4]=0; int num=buff[1]; if(num>0) { infoStr.Strcat("Tier\tExpiry Date\n"); infoStr.Strcat("----\t-----------\n"); } for(int i=0; i<num; i++) { ins76[2]=i; if(DoCmd(ins76,0,buff)<0 || !Status()) return; if(buff[5+2]==0 && buff[5+3]==0) break; int y,m,d,H,M,S; RevDateCalc(&buff[5+4],y,m,d,H,M,S); char str[100]; snprintf(str,sizeof(str),"%02x%02x\t%04d/%02d/%02d-%02d:%02d:%02d\n",buff[5+2],buff[5+3],y,m,d,H,M,S); infoStr.Strcat(str); PRINTF(L_SC_INIT,"Tier %02x%02x expires %04d/%02d/%02d-%02d:%02d:%02d",buff[5+2],buff[5+3],y,m,d,H,M,S); }}void cSmartCardVideoGuard2::RevDateCalc(const unsigned char *Date, int &year, int &mon, int &day, int &hh, int &mm, int &ss){ year=(Date[0]/12)+BASEYEAR; mon=(Date[0]%12)+1; day=Date[1]; hh=Date[2]/8; mm=(0x100*(Date[2]-hh*8)+Date[3])/32; ss=(Date[3]-mm*32)*2; }void cSmartCardVideoGuard2::Datecalc(int year, int mon, int day, int hh, int mm, int ss , unsigned char *Date){ Date[0]=((year-BASEYEAR)*12 + (mon-1)); Date[1]=day; Date[2]=hh*8+mm/8; Date[3]=ss/2+mm*32; } int cSmartCardVideoGuard2::DoCmd(const unsigned char *ins, const unsigned char *txbuff, unsigned char *rxbuff){ unsigned char ins2[5]; memcpy(ins2,ins,5); unsigned char len=0, mode=0; if(cmdList->GetInfo(ins2,len,mode)) { if(len==0xFF && mode==2) { if(ins2[4]==0) ins2[4]=len=ReadCmdLen(ins2); } else if(mode!=0) ins2[4]=len; } if(ins2[0]==0xd3) ins2[4]=len+16; len=ins2[4]; unsigned char b[256], tmp[264]; if(!rxbuff) rxbuff=tmp; if(mode>1) { if(!IsoRead(ins2,b) || !Status()) return -1; memcpy(rxbuff,ins2,5); memcpy(rxbuff+5,b,len); memcpy(rxbuff+5+len,sb,2); } else { if(!IsoWrite(ins2,txbuff) || !Status()) return -1; memcpy(rxbuff,ins2,5); memcpy(rxbuff+5,txbuff,len); memcpy(rxbuff+5+len,sb,2); } state.PostProcess_Decrypt(rxbuff,len,CW1,CW2); return len;}int cSmartCardVideoGuard2::ReadCmdLen(const unsigned char *cmd){ unsigned char cmd2[5], resp[16]; memcpy(cmd2,cmd,5); cmd2[3]=0x80; cmd2[4]=1; if(!IsoRead(cmd2,resp) || !Status()) { PRINTF(L_SC_ERROR,"failed to read %02x%02x cmd length",cmd[1],cmd[2]); return -1; } return resp[0]; }// -- cSmartCardLinkVG2 -------------------------------------------------------class cSmartCardLinkVG2 : public cSmartCardLink {public: cSmartCardLinkVG2(void):cSmartCardLink(SC_NAME,SC_ID) {} virtual cSmartCard *Create(void) { return new cSmartCardVideoGuard2; } virtual cSmartCardData *CreateData(void) { return new cSmartCardDataVideoGuard2; } };static cSmartCardLinkVG2 staticScInit;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -