|
SASC-NG
DVBSoftCAM
|
Inheritance diagram for cSmartCardIrdeto:Public Member Functions | |
| cSmartCardIrdeto (void) | |
| 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 CaId) |
Definition at line 353 of file sc-irdeto.c.
| cSmartCardIrdeto::cSmartCardIrdeto | ( | void | ) |
Definition at line 400 of file sc-irdeto.c.
:cSmartCard(&cardCfg,msgs) { ACS=0; caId=0; numProv=0; }
| bool cSmartCardIrdeto::CanHandle | ( | unsigned short | CaId | ) | [virtual] |
| bool cSmartCardIrdeto::Decode | ( | const cEcmInfo * | ecm, |
| const unsigned char * | data, | ||
| unsigned char * | cw | ||
| ) | [virtual] |
Implements cSmartCard.
Definition at line 617 of file sc-irdeto.c.
References cmd, cCamCrypt::RevCamCrypt(), SCT_LEN, and cSmartCard::Status().
{
static const unsigned char ecmCmd[] = { 0x01,0x05,0x00,0x00,0x02,0x00 };
int r=SCT_LEN(data)-6;
if(r<=255) {
unsigned char cmd[257+sizeof(ecmCmd)];
memcpy(cmd,ecmCmd,sizeof(ecmCmd));
cmd[5]=r;
memcpy(cmd+sizeof(ecmCmd),&data[6],r);
if((r=DoCmd(cmd,0x9D00))>0) {
if(Status() && r>=31) {
RevCamCrypt(camKey,&buff[14]);
RevCamCrypt(camKey,&buff[22]);
memcpy(cw,&buff[14],16);
return true;
}
}
}
return false;
}
| bool cSmartCardIrdeto::Init | ( | void | ) | [virtual] |
Implements cSmartCard.
Definition at line 406 of file sc-irdeto.c.
References cProviders::AddProv(), cSmartCard::atr, cInfoStr::Begin(), cSmartCard::CaidsChanged(), cCamCrypt::CamKey(), cCamCrypt::EncryptCamMessage(), cSmartCardDataIrdeto::exp, cSmartCards::FindCardData(), cInfoStr::Finish(), cCamCrypt::HelperKey(), Atr::hist, Atr::histLen, i, cSmartCard::idStr, cSmartCard::infoStr, k, L_GEN_WARN, L_SC_ERROR, L_SC_INIT, LDUMP, cSmartCardDataIrdeto::mod, cSmartCardDataIrdeto::plain, cCamCrypt::PrepareCamMessage(), cLineBuff::Printf(), PRINTF, RECOVER_TIME, cIdSet::ResetIdSet(), cCamCrypt::RevCamCrypt(), SC_NAME, cTimeMs::Set(), cIdSet::SetCard(), cCamCrypt::SetupCardFiles(), smartcards, cSmartCard::Status(), cLineBuff::Strcat(), and strn0cpy().
{
ResetIdSet();
recoverTime.Set(-RECOVER_TIME);
if(atr->histLen<6 || memcmp(atr->hist,"IRDETO",6)) {
PRINTF(L_SC_INIT,"doesn't looks like a Irdeto/Beta card");
return false;
}
infoStr.Begin();
infoStr.Strcat("Irdeto smartcard\n");
int r;
static unsigned char getCountryCode[] = { 0x01,0x02,0x02,0x03,0x00,0x00,0xCC };
if((r=DoCmd(getCountryCode,0x0000))<=0 || !Status() || r<16) {
PRINTF(L_SC_ERROR,"country code error");
return false;
}
ACS=buff[8]*256+buff[9];
int c=buff[13]*256+buff[14];
if(c!=caId) CaidsChanged();
caId=c;
memcpy(coco,&buff[21],3); coco[3]=0;
PRINTF(L_SC_INIT,"ACS Version %04x, CAID %04x, CoCo %s",ACS,caId,coco);
snprintf(idStr,sizeof(idStr),"%s (ACS %x)",SC_NAME,ACS);
infoStr.Printf("ACS: %04x CAID: %04x CoCo: %s\n",ACS,caId,coco);
static unsigned char getAsciiSerial[] = { 0x01,0x02,0x00,0x03,0x00,0x00,0xCC };
if((r=DoCmd(getAsciiSerial,0x0000))<=0 || !Status() || r<10) {
PRINTF(L_SC_ERROR,"ASCII serial error");
return false;
}
strn0cpy(asciiSerial,(char*)buff+8,sizeof(asciiSerial));
PRINTF(L_SC_INIT,"ASCII serial %s",asciiSerial);
static unsigned char getHexSerial[] = { 0x01,0x02,0x01,0x03,0x00,0x00,0xCC };
if((r=DoCmd(getHexSerial,0x0000))<=0 || !Status() || r<25) {
PRINTF(L_SC_ERROR,"hex serial error");
return false;
}
int numProv=buff[18];
SetCard(new cCardIrdeto(buff[23],&buff[20]));
PRINTF(L_SC_INIT,"Providers: %d HEX Serial: %02X%02X%02X HEX Base: %02X",numProv,buff[20],buff[21],buff[22],buff[23]);
infoStr.Printf("HEX: %02X/%02X%02X%02X ASCII: %s\n",buff[23],buff[20],buff[21],buff[22],asciiSerial);
static unsigned char getCardFile[] = { 0x01,0x02,0x0E,0x02,0x00,0x00,0xCC };
unsigned char encr[128], plain[64+6+2];
PrepareCamMessage(plain+6);
getCardFile[3]=0x02;
if((r=DoCmd(getCardFile,0x0000))<=0 || !Status() || r<73) {
PRINTF(L_SC_ERROR,"cardfile2 error");
return false;
}
memcpy(encr,buff+8,64);
getCardFile[3]=0x03;
if((r=DoCmd(getCardFile,0x0000))<=0 || !Status() || r<73) {
PRINTF(L_SC_ERROR,"cardfile3 error");
return false;
}
memcpy(encr+64,buff+8,64);
bool doPlain=false;
if((ACS==0x0383 || ACS==0x0384) && atr->histLen>=12 && atr->hist[12]==0x95)
doPlain=true;
cSmartCardDataIrdeto *entry=0;
if(!doPlain) {
cSmartCardDataIrdeto cd(ACS,caId);
if(!(entry=(cSmartCardDataIrdeto *)smartcards.FindCardData(&cd))) {
PRINTF(L_GEN_WARN,"didn't find Irdeto card specific certificate, falling back to default");
cSmartCardDataIrdeto cd(-1,-1);
if(!(entry=(cSmartCardDataIrdeto *)smartcards.FindCardData(&cd))) {
PRINTF(L_GEN_WARN,"didn't find default Irdeto certificate, please add one");
if(ACS!=0x0384) return false;
PRINTF(L_GEN_WARN,"trying pre-coded ACS 384 challenge. This mode is DEPRECATED. There ARE valid certificates for these cards available!");
}
}
else doPlain=entry->plain;
}
static unsigned char doCamKeyExchange[] = { 0x01,0x02,0x09,0x03,0x00,0x40 };
if(doPlain) {
// plain challenge
memcpy(plain,doCamKeyExchange,sizeof(doCamKeyExchange));
plain[4]=1; // set block counter
r=DoCmd(plain,0x5500,0x0000);
}
else {
// RSA challenge
if(entry) {
if(!SetupCardFiles(encr,sizeof(encr),entry->exp,entry->mod)) {
PRINTF(L_SC_ERROR,"decrypting cardfiles failed. Probably bad certificate.");
return false;
}
if(!EncryptCamMessage(encr+6,plain+6)) {
PRINTF(L_SC_ERROR,"encrypting CAM message failed. Probably bad certificate.");
return false;
}
static unsigned char doRSACheck[] = { 0x01,0x02,0x11,0x00,0x00,0x40 };
memcpy(plain,doRSACheck,sizeof(doRSACheck));
if((r=DoCmd(plain,0x5800,0x0000))<=0 || !Status() || r<73) {
PRINTF(L_SC_ERROR,"card didn't give a proper reply (buggy RSA unit?), trying to continue...");
// non-fatal
}
if(r==73 && memcmp(encr+6,buff+8,64)) {
PRINTF(L_SC_ERROR,"card failed on RSA check, trying to continue...");
// non-fatal
}
}
else {
static const unsigned char enc384cz[] = {
0x18,0xD7,0x55,0x14,0xC0,0x83,0xF1,0x38, 0x39,0x6F,0xF2,0xEC,0x4F,0xE3,0xF1,0x85,
0x01,0x46,0x06,0xCE,0x7D,0x08,0x2C,0x74, 0x46,0x8F,0x72,0xC4,0xEA,0xD7,0x9C,0xE0,
0xE1,0xFF,0x58,0xE7,0x70,0x0C,0x92,0x45, 0x26,0x18,0x4F,0xA0,0xE2,0xF5,0x9E,0x46,
0x6F,0xAE,0x95,0x35,0xB0,0x49,0xB2,0x0E, 0xA4,0x1F,0x8E,0x47,0xD0,0x24,0x11,0xD0
};
static const unsigned char enc384dz[] = {
0x27,0xF2,0xD6,0xCD,0xE6,0x88,0x62,0x46, 0x81,0xB0,0xF5,0x3E,0x6F,0x13,0x4D,0xCC,
0xFE,0xD0,0x67,0xB1,0x93,0xDD,0xF4,0xDE, 0xEF,0xF5,0x3B,0x04,0x1D,0xE5,0xC3,0xB2,
0x54,0x38,0x57,0x7E,0xC8,0x39,0x07,0x2E, 0xD2,0xF4,0x05,0xAA,0x15,0xB5,0x55,0x24,
0x90,0xBB,0x9B,0x00,0x96,0xF0,0xCB,0xF1, 0x8A,0x08,0x7F,0x0B,0xB8,0x79,0xC3,0x5D
};
static const unsigned char ck[] = { 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88 };
static const unsigned char hk[] = { 0x12,0x34,0x56,0x78,0x90,0xAB,0xCD,0xEF };
if(caId==0x1702) memcpy(encr+6,enc384cz,sizeof(enc384cz));
else if(caId==0x1722) memcpy(encr+6,enc384dz,sizeof(enc384dz));
else {
PRINTF(L_GEN_WARN,"no pre-coded Irdeto camkey challenge for caid %04x",caId);
return false;
}
memcpy((void *)CamKey(plain+6),ck,sizeof(ck));
memcpy((void *)HelperKey(plain+6),hk,sizeof(hk));
}
memcpy(encr,doCamKeyExchange,sizeof(doCamKeyExchange));
r=DoCmd(encr,0x5500,0x0000);
}
if(r>0 && Status() && r>=9) {
memcpy(camKey,CamKey(plain+6),8);
if(r>=17) {
RevCamCrypt(camKey,buff+8);
if(memcmp(HelperKey(plain+6),buff+8,8)) {
PRINTF(L_SC_ERROR,"camkey challenge failed");
return false;
}
}
LDUMP(L_SC_INIT,camKey,sizeof(camKey),"camkey");
}
else {
PRINTF(L_SC_ERROR,"camkey error");
return false;
}
static unsigned char getProvider[] = { 0x01,0x02,0x03,0x03,0x00,0x00,0xCC };
static unsigned char getChanelIds[] = { 0x01,0x02,0x04,0x00,0x00,0x01,0x00,0xCC };
for(int i=0; i<numProv; i++) {
getProvider[4]=i;
if((r=DoCmd(getProvider,0x0000))>0 && Status() && r>=33) {
AddProv(new cProviderIrdeto(buff[8]&0x0f,&buff[9]));
PRINTF(L_SC_INIT,"provider %d with ProvBase 0x%02x ProvId 0x%02x%02x%02x",i,buff[8]&0x0f,buff[9],buff[10],buff[11]);
infoStr.Printf("Provider %d Id: %02X/%02X%02X%02X\n",i,buff[8]&0x0f,buff[9],buff[10],buff[11]);
getChanelIds[4]=i;
for(int l=0; l<10; l++) {
getChanelIds[6]=l;
if((r=DoCmd(getChanelIds,0x0000,0x5400))<=0 || !Status() || r<69) break;
for(int k=0; k<buff[7]; k+=6) {
int chanId=buff[k+8+0]*256+buff[k+8+1];
int date =buff[k+8+2]*256+buff[k+8+3];
int durr =buff[k+8+4];
if(chanId!=0x0000 && chanId!=0xFFFF) {
char sdate[16], edate[16];
Date(date,sdate,sizeof(sdate));
Date(date+durr,edate,sizeof(edate));
PRINTF(L_SC_INIT,"ChanId 0x%04x Date 0x%04x %s Duration 0x%02x %s",chanId,date,sdate,durr,edate);
infoStr.Printf("ChanId: %04X Date: %s-%s\n",chanId,sdate,edate);
}
}
}
}
}
#if 0
static unsigned char getCountryCode2[] = { 0x01,0x02,0x0B,0x00,0x00,0x00,0xCC };
if((r=DoCmd(getCountryCode2,0x0000))>0 && Status() && r>=32) {
PRINTF(L_SC_INIT,"max ChID's %d,%d,%d,%d",buff[14],buff[15],buff[16],buff[17]);
}
#endif
infoStr.Finish();
return true;
}
| bool cSmartCardIrdeto::Update | ( | int | pid, |
| int | caid, | ||
| const unsigned char * | data | ||
| ) | [virtual] |
Reimplemented from cSmartCard.
Definition at line 639 of file sc-irdeto.c.
References ADDRLEN, cParseIrdeto::AddrLen(), cmd, L_SC_ERROR, cIdSet::MatchEMM(), PRINTF, SCT_LEN, and cSmartCard::Status().
{
static const unsigned char emmCmd[] = { 0x01,0x01,0x00,0x00,0x00,0x00 };
if(MatchEMM(data)) {
int len=cParseIrdeto::AddrLen(data)+1;
if(len<=ADDRLEN) {
const int dataLen=SCT_LEN(data)-5-len; // sizeof of data bytes (nanos)
if(dataLen<=255-ADDRLEN) {
unsigned char cmd[257+sizeof(emmCmd)];
memcpy(cmd,emmCmd,sizeof(emmCmd));
cmd[5]=dataLen+ADDRLEN;
memset(cmd+sizeof(emmCmd),0,ADDRLEN);
memcpy(cmd+sizeof(emmCmd),&data[3],len);
memcpy(cmd+sizeof(emmCmd)+ADDRLEN,&data[len+5],dataLen);
if(DoCmd(cmd,0x0000)>0 && Status()) return true;
}
}
else PRINTF(L_SC_ERROR,"addrlen %d > %d",len,ADDRLEN);
}
return false;
}