📄 sc-cryptoworks.c
字号:
return false; } memcpy(Caid,&buff[2],2); caid=buff[2]*256+buff[3]; if(ReadRecord(buff,0x80)<7) { PRINTF(L_SC_ERROR,"reading record 2f01/80 failed"); return false; } SetCard(new cCardCryptoworks(&buff[2])); memcpy(serial,&buff[2],5); 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)); PRINTF(L_SC_INIT,"card v.%d (pindown=%d) caid %04x serial %s MF %04X",atr->hist[2],atr->hist[3],caid,HexStr(str,&buff[2],5),mfid); if(ReadRecord(buff,0x9F)>=3) { const char *n="(unknown)"; if(ReadRecord(buff+10,0xC0)>=18) n=(char *)buff+10+2; infoStr.Printf("Issuer: 0x%02x (%.16s)\n",buff[2],n); PRINTF(L_SC_INIT,"card issuer: 0x%02x %.16s",buff[2],n); } if(ReadRecord(buff,0x9E)>=66) { HEXDUMP(L_SC_EXTRA,&buff[2],64,"card ISK"); cSmartCardDataCryptoworks cd(dtIPK,Caid); cSmartCardDataCryptoworks *entry=(cSmartCardDataCryptoworks *)smartcards.FindCardData(&cd); if(entry) { PRINTF(L_SC_EXTRA,"got IPK from smartcard.conf"); if(rsa.RSA(&buff[2],&buff[2],64,exp,entry->key,false)>0) { HEXDUMP(L_SC_EXTRA,&buff[2],64,"decrypted ISK"); if(buff[2] == ((mfid&0xFF)>>1)) { buff[2]|=0x80; BN_bin2bn(&buff[2],64,ucpk); ucpkValid=true; PRINTF(L_SC_INIT,"got UCPK from IPK/ISK"); } else PRINTF(L_SC_ERROR,"UCPK check failed %02x != %02x",buff[2],(mfid&0xFF)>>1); } else PRINTF(L_SC_ERROR,"RSA failed for UCPK"); } } if(!ucpkValid) { cSmartCardDataCryptoworks cd(dtUCPK,serial); cSmartCardDataCryptoworks *entry=(cSmartCardDataCryptoworks *)smartcards.FindCardData(&cd); if(entry) { BN_copy(ucpk,entry->key); ucpkValid=true; PRINTF(L_SC_INIT,"got UCPK from smartcard.conf"); } } if(!ucpkValid) PRINTF(L_GEN_WARN,"no valid UCPK for cryptoworks smartcard"); // 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])) { const 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); PRINTF(L_SC_INIT,"provider %d: 0x%02x %.16s",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"); PRINTF(L_SC_INIT,"| id | chid | stat | date | version | name "); first=false; } infoStr.Printf( "--+----+--+-----------------+------\n" "%s\n", fnName[j]); PRINTF(L_SC_INIT,"+----+------+------+-------------------+----------+-------------"); PRINTF(L_SC_INIT,"| %s",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); PRINTF(L_SC_INIT,"| %02x | %04x | %02x | %s-%s | %08x | %.12s", chid.id,chid.chid,chid.status,chid.from,chid.to,chid.version,chid.name); insb2[3]=0x01; } } } } } } if(disableParental) { bool pinOK=false; if(SelectFile(0x2F11) && ReadRecord(buff,atr->hist[3])>=7) { pinOK=true; PRINTF(L_SC_INIT,"read PIN from card."); } if(!pinOK) { cSmartCardDataCryptoworks cd(dtPIN,serial); cSmartCardDataCryptoworks *entry=(cSmartCardDataCryptoworks *)smartcards.FindCardData(&cd); if(entry) { memcpy(&buff[2],entry->pin,4); pinOK=true; PRINTF(L_SC_INIT,"got PIN from smartcard.conf."); } } if(pinOK) { static const unsigned char ins24[] = { 0xA4,0x24,0x00,0x01,0x05 }; PRINTF(L_SC_INIT,"your card PIN is %.4s",&buff[2]); // parental rating // 0x00 - undefined // 0x01-0x0f - minimum age=rating+3 years // 0x10-0xff - reserved for provider usage buff[6]=0; if(IsoWrite(ins24,&buff[2]) && Status()) PRINTF(L_SC_INIT,"parental rating set to %02x",buff[6]); else PRINTF(L_SC_ERROR,"failed to set parental rating."); } else PRINTF(L_SC_INIT,"no PIN available."); } 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 }; unsigned char nanoD4[10]; int l=CheckSctLen(data,-5+(ucpkValid ? sizeof(nanoD4):0)); if(l>5) { unsigned char buff[MAX_LEN]; if(ucpkValid) { memcpy(buff,data,l); nanoD4[0]=0xD4; nanoD4[1]=0x08; for(unsigned int i=2; i<sizeof(nanoD4); i++) nanoD4[i]=rand(); memcpy(&buff[l],nanoD4,sizeof(nanoD4)); data=buff; l+=sizeof(nanoD4); } ins4c[3]=ucpkValid ? 2 : 0; ins4c[4]=l-5; if(IsoWrite(ins4c,&data[5]) && Status() && (l=GetLen())>0 && ReadData(buff,l)==l) { int r=0; for(int i=0; i<l && r<2; ) { int n=buff[i+1]; switch(buff[i]) { case 0xDB: // CW PRINTF(L_SC_EXTRA,"nano DB (cw)"); if(n==0x10) { memcpy(cw,&buff[i+2],16); r|=1; } break; case 0xDF: // signature PRINTF(L_SC_EXTRA,"nano DF %02x (sig)",n); if(n==0x08) { if((buff[i+2]&0x50)==0x50) { if(buff[i+3]&0x01) PRINTF(L_SC_ERROR,"not decyphered. PIN protected?"); else if(!(buff[i+5]&0x80)) PRINTF(L_SC_ERROR,"missing entitlement. Check your subscription"); else r|=2; } } else if(n==0x40) { // camcrypt if(ucpkValid) { if(rsa.RSA(&buff[i+2],&buff[i+2],n,exp,ucpk,false)<=0) { PRINTF(L_SC_ERROR,"camcrypt RSA failed."); return false; } HEXDUMP(L_SC_EXTRA,&buff[i+2],n,"after camcrypt"); if(!memmem(&buff[i+2+4],n-4,nanoD4,sizeof(nanoD4))) { PRINTF(L_SC_ERROR,"camcrypt failed. Check IPK/UCPK in your smartcard.conf!"); return false; } r=0; l=n-4; n=4; } else { PRINTF(L_SC_ERROR,"valid UCPK needed for camcrypt! Check your smartcard.conf for a IPK/UCPK!"); return false; } } break; default: PRINTF(L_SC_EXTRA,"nano %02x (unhandled)",buff[i]); break; } i+=n+2; } return r==3; } } return false;}bool cSmartCardCryptoworks::Update(int pid, int caid, const unsigned char *data){ static unsigned char ins[] = { 0xA4,0x42,0x00,0x00,0x00 }; cAssembleData ad(data); if(MatchAndAssemble(&ad,0,0)) { while((data=ad.Assembled())) { int c, n; switch(data[0]) { case 0x82: c=0x42; n=10; break; case 0x84: c=0x48; n=9; break; case 0x88: case 0x89: c=0x44; n=5; break; default: continue; } int len=CheckSctLen(data,-n); if(len>n) { ins[1]=c; ins[4]=len-n; if(IsoWrite(ins,&data[n])) Status(); } } return true; } return false;}// -- cSmartCardLinkCryptoworks -------------------------------------------------------class cSmartCardLinkCryptoworks : public cSmartCardLink {public: cSmartCardLinkCryptoworks(void):cSmartCardLink(SC_NAME,SC_ID) {} virtual cSmartCard *Create(void) { return new cSmartCardCryptoworks(); } virtual cSmartCardData *CreateData(void) { return new cSmartCardDataCryptoworks; } };static cSmartCardLinkCryptoworks staticScInit;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -