📄 sc-cryptoworks.cpp
字号:
/* * 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 <string.h>#include "system.h"#include "system-common.h"#include "smartcard.h"#include "parse.h"#include "opts.h"#define SYSTEM_NAME "SC-Cryptoworks"#define SYSTEM_PRI -5#define SC_NAME "Cryptoworks"#define SC_ID MAKE_SC_ID('C','r','W','o')static int disableParental=0;// -- cSystemScCryptoworks ---------------------------------------------------------------class cSystemScCryptoworks : public cSystemScCore {public: cSystemScCryptoworks(void);};cSystemScCryptoworks::cSystemScCryptoworks(void):cSystemScCore(SYSTEM_NAME,SYSTEM_PRI,SC_ID,"SC Cryptoworks"){ hasLogger=true;}// -- cSystemLinkScCryptoworks --------------------------------------------------------class cSystemLinkScCryptoworks : public cSystemLink {public: cSystemLinkScCryptoworks(void); virtual bool CanHandle(unsigned short SysId); virtual cSystem *Create(void) { return new cSystemScCryptoworks; }};static cSystemLinkScCryptoworks staticInit;cSystemLinkScCryptoworks::cSystemLinkScCryptoworks(void):cSystemLink(SYSTEM_NAME,SYSTEM_PRI){ static const char *rat[] = { "don't touch", "disable" }; opts=new cOpts(SYSTEM_NAME,1); opts->Add(new cOptSel("DisableParental","SC-Cryptoworks: Parental rating",&disableParental,sizeof(rat)/sizeof(char *),rat)); Feature.NeedsSmartCard();}bool cSystemLinkScCryptoworks::CanHandle(unsigned short SysId){ bool res=false; cSmartCard *card=smartcards.LockCard(SC_ID); if(card) { res=card->CanHandle(SysId); smartcards.ReleaseCard(card); } return res;}// -- cSmartCardCryptoworks -----------------------------------------------------------class cSmartCardCryptoworks : public cSmartCard, public cIdSet {private: int caid; // int GetLen(void); bool EndOfData(void); bool SelectFile(int file); int ReadRecord(unsigned char *buff, int num);public: cSmartCardCryptoworks(void); virtual bool Init(void); virtual bool Decode(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw); virtual bool CanHandle(unsigned short CaId);};static const struct StatusMsg msgs[] = { { { 0x90,0x00 }, "Instruction executed without errors", true }, { { 0x92,0x40 }, "Memory problem", false }, { { 0x94,0x02 }, "Out of range", false }, { { 0x94,0x04 }, "File not found", false }, { { 0x98,0x04 }, "Verification failed (wrong PIN)", false }, { { 0x98,0x05 }, "Wrong signature", false }, { { 0x98,0x40 }, "Verification failed, card blocked (deblocking by uplink required)", false }, { { 0x9F,0xFF }, "Instruction accepted, data to be read", true }, { { 0xFF,0xFF }, 0, false }};static const struct CardConfig cardCfg = { SM_8E2,1000,100};struct chid_dat { unsigned int chid, version; unsigned char id, status; char from[16], to[16], name[16];};cSmartCardCryptoworks::cSmartCardCryptoworks(void):cSmartCard(&cardCfg,msgs){}int cSmartCardCryptoworks::GetLen(void){ return (sb[0]==0x9F) ? sb[1] : -1;}bool cSmartCardCryptoworks::EndOfData(void){ return sb[0]==0x94 && sb[1]==0x02;}bool cSmartCardCryptoworks::SelectFile(int file){ static unsigned char insa4[] = { 0xA4,0xA4,0x00,0x00,0x02,0x00,0x00 }; insa4[5]=file>>8; insa4[6]=file&0xFF; return IsoWrite(insa4,&insa4[5]) && Status();}int cSmartCardCryptoworks::ReadRecord(unsigned char *buff, int num){ static unsigned char insa2[] = { 0xA4,0xA2,0x00,0x00,0x01,0x00 }; static unsigned char insb2[] = { 0xA4,0xB2,0x00,0x00,0x00 }; insa2[5]=num; if(IsoWrite(insa2,&insa2[5]) && Status() && (num=GetLen())>0) { insb2[4]=num; if(IsoRead(insb2,buff) && Status()) return num; } return -1;}bool cSmartCardCryptoworks::Init(void){ if(atr->histLen<6 || atr->hist[1]!=0xC4 || atr->hist[4]!=0x8F || atr->hist[5]!=0xF1) { di(printf("smartcardcryptoworks: doesn't look like a Cryptoworks card\n")) return false; } infoStr.Begin(); infoStr.Strcat("Cryptoworks smartcard\n"); unsigned char buff[MAX_LEN]; if(!SelectFile(0x2F01) || ReadRecord(buff,0xD1)<4) { di(printf("smartcardcryptoworks: reading record 2f01/d1 failed\n")) return false; } caid=buff[2]*256+buff[3]; if(ReadRecord(buff,0x80)<7) { di(printf("smartcardcryptoworks: reading record 2f01/80 failed\n")) return false; } SetCard(new cCardCryptoworks(&buff[2])); _snprintf(idStr,sizeof(idStr),"%s (V.%d)",SC_NAME,atr->hist[2]); char str[20]; infoStr.Printf( "Card v.%d (PINcount=%d)\n" "Caid %04x Serial %s\n", atr->hist[2],atr->hist[3],caid,HexStr(str,&buff[2],5)); di(printf("smartcardcryptoworks: card v.%d (pindown=%d) caid %04x serial %s\n",atr->hist[2],atr->hist[3],caid,HexStr(str,&buff[2],5))) if(ReadRecord(buff,0x9F)>=3) { char *n="(unknown)"; if(ReadRecord(buff+10,0xC0)>=18) n=(char *)buff+10+2; infoStr.Printf("Issuer: 0x%02x (%.16s)\n",buff[2],n); di(printf("smartcardcryptoworks: card issuer: 0x%02x %.16s\n",buff[2],n)) } // read entitlements static unsigned char insb8[] = { 0xA4,0xB8,0x00,0x00,0x0C }; unsigned char provId[16]; unsigned int count=0; insb8[2]=insb8[3]=0x00; while(IsoRead(insb8,buff) && !EndOfData() && Status()) { if(buff[0]==0xDF && buff[1]==0x0A) { int fileno=(buff[4]&0x3F)*256+buff[5]; if((fileno&0xFF00)==0x1F00) { provId[count++]=fileno&0xFF; if(count>=sizeof(provId)) break; } } insb8[2]=insb8[3]=0xFF; } for(unsigned int i=0; i<count ; i++) { if(SelectFile(0x1F00+provId[i])) { char *n="(unknown)"; if(SelectFile(0x0E11) && ReadRecord(buff,0xD6)>=18) n=(char *)buff+2; infoStr.Printf("Provider %d: 0x%02x (%.16s)\n",i,provId[i],n); di(printf("smartcardcryptoworks: provider %d: 0x%02x %.16s\n",i,provId[i],n)) static unsigned char insa2_0[] = { 0xA4,0xA2,0x01,0x00,0x03,0x83,0x01,0x00 }; static unsigned char insa2_1[] = { 0xA4,0xA2,0x01,0x00,0x05,0x8C,0x00,0x00,0x00,0x00 }; static unsigned char insb2[] = { 0xA4,0xB2,0x00,0x00,0x00 }; static const unsigned int fn[] = { 0x0f00,0x0f20,0x0f40,0x0f60,0 }; static const char *fnName[] = { "Download","Subscriptions","PPV Events","PPV Events",0 }; bool first=true; for(int j=0; fn[j]; j++) { if(SelectFile(fn[j])) { insa2_0[7]=provId[i]; unsigned char *ins=(j==1) ? insa2_1 : insa2_0; int l; if(IsoWrite(ins,&ins[5]) && Status() && (l=GetLen())>0) { if(first) { infoStr.Printf("id|chid|st|date |name\n"); di(printf("smartcardcryptoworks: | id | chid | stat | date | version | name \n")) first=false; } infoStr.Printf( "--+----+--+-----------------+------\n" "%s\n", fnName[j]); di(printf( "smartcardcryptoworks: +----+------+------+-------------------+----------+-------------\n" "smartcardcryptoworks: | %s\n", fnName[j])) insb2[3]=0x00; insb2[4]=l; while(IsoRead(insb2,buff) && !EndOfData() && Status()) { struct chid_dat chid; memset(&chid,0,sizeof(chid)); for(int k=0; k<l; k+=buff[k+1]+2) { switch(buff[k]) { case 0x83: chid.id=buff[k+2]; break; case 0x8c: chid.status=buff[k+2]; chid.chid=buff[k+3]*256+buff[k+4]; break; case 0x8D: _snprintf(chid.from,sizeof(chid.from),"%02d.%02d.%02d",buff[k+3]&0x1F,((buff[k+2]&1)<<3)+(buff[k+3]>>5),(1990+(buff[k+2]>>1))%100); _snprintf(chid.to ,sizeof(chid.to) ,"%02d.%02d.%02d",buff[k+5]&0x1F,((buff[k+4]&1)<<3)+(buff[k+5]>>5),(1990+(buff[k+4]>>1))%100); break; case 0xD5: _snprintf(chid.name,sizeof(chid.name),"%.12s",&buff[k+2]); chid.version=Bin2Int(&buff[k+14],4); break; } } infoStr.Printf("%02x|%04x|%02x|%s-%s|%.12s\n", chid.id,chid.chid,chid.status,chid.from,chid.to,chid.name); di(printf("smartcardcryptoworks: | %02x | %04x | %02x | %s-%s | %08x | %.12s\n", chid.id,chid.chid,chid.status,chid.from,chid.to,chid.version,chid.name)) insb2[3]=0x01; } } } } } } // disable parental rating if(disableParental) { static unsigned char ins24[] = { 0xA4,0x24,0x00,0x01,0x05,0x00,0x00,0x00,0x00,0x00 }; if(SelectFile(0x2F11) && ReadRecord(buff,atr->hist[3])>=7) { di(printf("smartcardcryptoworks: your card PIN is %.4s\n",&buff[2])) memcpy(&ins24[5],&buff[2],4); // parental rating // 0x00 - undefined // 0x01-0x0f - minimum age=rating+3 years // 0x10-0xff - reserved for provider usage ins24[9]=0; if(IsoWrite(ins24,&ins24[5]) && Status()) di(printf("smartcardcryptoworks: parental rating set to %02x\n",ins24[9])) else di(printf("smartcardcryptoworks: failed to set parental rating.\n")) } else di(printf("smartcardcryptoworks: failed to read card PIN.\n")) } infoStr.Finish(); return true;}bool cSmartCardCryptoworks::CanHandle(unsigned short CaId){ return CaId==caid;}bool cSmartCardCryptoworks::Decode(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw){ static unsigned char ins4c[] = { 0xA4,0x4C,0x00,0x00,0x00 }; static unsigned char insc0[] = { 0xA4,0xC0,0x00,0x00,0x00 }; int l=CheckSctLen(data,-5); if(l>5) { unsigned char buff[MAX_LEN]; ins4c[4]=l-5; if(IsoWrite(ins4c,&data[5]) && Status() && (l=GetLen())>0) { insc0[4]=l; if(IsoRead(insc0,buff) && Status()) { int r=0; for(int i=0; i<l; ) { int n=buff[i+1]; switch(buff[i]) { case 0xDB: // CW if(n==0x10) { memcpy(cw,&buff[i+2],16); r|=1; } break; case 0xDF: // signature if(n==0x08 && (buff[i+2]&0x50)==0x50 && !(buff[i+3]&0x01) && (buff[i+5]&0x80)) r|=2; break; } i+=n+2; } return r==3; } } } return false;}// -- cSmartCardLinkCryptoworks -------------------------------------------------------class cSmartCardLinkCryptoworks : public cSmartCardLink {public: cSmartCardLinkCryptoworks(void):cSmartCardLink(SC_NAME,SC_ID) {} virtual cSmartCard *Create(void) { return new cSmartCardCryptoworks(); }};static cSmartCardLinkCryptoworks staticScInit;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -