|
SASC
DVBSoftCAM
|
00001 /* 00002 * Softcam plugin to VDR (C++) 00003 * 00004 * This code is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This code is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software 00016 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00017 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html 00018 */ 00019 00020 #include <stdio.h> 00021 #include <string.h> 00022 00023 #include <openssl/rand.h> 00024 00025 #include "system-common.h" 00026 #include "smartcard.h" 00027 #include "crypto.h" 00028 #include "data.h" 00029 #include "misc.h" 00030 #include "parse.h" 00031 #include "log-sc.h" 00032 #include "log-core.h" 00033 #include "version.h" 00034 00035 SCAPIVERSTAG(); 00036 00037 #define SYSTEM_NAME "SC-Irdeto" 00038 #define SYSTEM_PRI -5 00039 00040 #define SC_NAME "Irdeto" 00041 #define SC_ID MAKE_SC_ID('I','r','d','t') 00042 00043 #define L_SC 8 00044 #define L_SC_ALL LALL(L_SC_LASTDEF) 00045 00046 static const struct LogModule lm_sc = { 00047 (LMOD_ENABLE|L_SC_ALL)&LOPT_MASK, 00048 (LMOD_ENABLE|L_SC_DEFDEF)&LOPT_MASK, 00049 "sc-irdeto", 00050 { L_SC_DEFNAMES } 00051 }; 00052 ADD_MODULE(L_SC,lm_sc) 00053 00054 static void BN_complement(const unsigned char *data, int len, BIGNUM *bn) 00055 { 00056 unsigned char *buff=AUTOMEM(len); 00057 for(int i=len-1; i>=0; i--) buff[i]=~data[i]; 00058 BN_bin2bn(buff,len,bn); 00059 BN_add_word(bn,1); 00060 } 00061 00062 // -- cSystemScIrdeto ---------------------------------------------------------- 00063 00064 class cSystemScIrdeto : public cSystemScCore { 00065 public: 00066 cSystemScIrdeto(void); 00067 }; 00068 00069 cSystemScIrdeto::cSystemScIrdeto(void) 00070 :cSystemScCore(SYSTEM_NAME,SYSTEM_PRI,SC_ID,"SC Irdeto") 00071 { 00072 hasLogger=true; 00073 } 00074 00075 // -- cSystemLinkScIrdeto ------------------------------------------------------ 00076 00077 class cSystemLinkScIrdeto : public cSystemLink { 00078 public: 00079 cSystemLinkScIrdeto(void); 00080 virtual bool CanHandle(unsigned short SysId); 00081 virtual cSystem *Create(void) { return new cSystemScIrdeto; } 00082 }; 00083 00084 static cSystemLinkScIrdeto staticInit; 00085 00086 cSystemLinkScIrdeto::cSystemLinkScIrdeto(void) 00087 :cSystemLink(SYSTEM_NAME,SYSTEM_PRI) 00088 { 00089 Feature.NeedsSmartCard(); 00090 } 00091 00092 bool cSystemLinkScIrdeto::CanHandle(unsigned short SysId) 00093 { 00094 bool res=false; 00095 cSmartCard *card=smartcards.LockCard(SC_ID); 00096 if(card) { 00097 res=card->CanHandle(SysId); 00098 smartcards.ReleaseCard(card); 00099 } 00100 return res; 00101 } 00102 00103 // -- cCamCrypt ---------------------------------------------------------------- 00104 00105 class cCamCrypt { 00106 private: 00107 static const unsigned char cryptTable[]; 00108 bool randomInit; 00109 cRSA rsa; 00110 cBN cardExp, cardMod; 00111 // 00112 void GenerateRandom(unsigned char *buf, int len); 00113 void RotateRight8Byte(unsigned char *key); 00114 void RotateLeft8Byte(unsigned char *key); 00115 protected: 00116 void CamCrypt(const unsigned char *key, unsigned char *data); 00117 void RevCamCrypt(const unsigned char *key, unsigned char *data); 00118 // 00119 bool SetupCardFiles(unsigned char *data, int len, BIGNUM *exp, BIGNUM *mod); 00120 void PrepareCamMessage(unsigned char *plain); 00121 bool EncryptCamMessage(unsigned char *encrypted, const unsigned char *plain); 00122 const unsigned char *CamKey(const unsigned char *data) { return data+8; } 00123 const unsigned char *HelperKey(const unsigned char *data) { return data+24; } 00124 public: 00125 cCamCrypt(void); 00126 }; 00127 00128 const unsigned char cCamCrypt::cryptTable[256] = { 00129 0xDA,0x26,0xE8,0x72,0x11,0x52,0x3E,0x46,0x32,0xFF,0x8C,0x1E,0xA7,0xBE,0x2C,0x29, 00130 0x5F,0x86,0x7E,0x75,0x0A,0x08,0xA5,0x21,0x61,0xFB,0x7A,0x58,0x60,0xF7,0x81,0x4F, 00131 0xE4,0xFC,0xDF,0xB1,0xBB,0x6A,0x02,0xB3,0x0B,0x6E,0x5D,0x5C,0xD5,0xCF,0xCA,0x2A, 00132 0x14,0xB7,0x90,0xF3,0xD9,0x37,0x3A,0x59,0x44,0x69,0xC9,0x78,0x30,0x16,0x39,0x9A, 00133 0x0D,0x05,0x1F,0x8B,0x5E,0xEE,0x1B,0xC4,0x76,0x43,0xBD,0xEB,0x42,0xEF,0xF9,0xD0, 00134 0x4D,0xE3,0xF4,0x57,0x56,0xA3,0x0F,0xA6,0x50,0xFD,0xDE,0xD2,0x80,0x4C,0xD3,0xCB, 00135 0xF8,0x49,0x8F,0x22,0x71,0x84,0x33,0xE0,0x47,0xC2,0x93,0xBC,0x7C,0x3B,0x9C,0x7D, 00136 0xEC,0xC3,0xF1,0x89,0xCE,0x98,0xA2,0xE1,0xC1,0xF2,0x27,0x12,0x01,0xEA,0xE5,0x9B, 00137 0x25,0x87,0x96,0x7B,0x34,0x45,0xAD,0xD1,0xB5,0xDB,0x83,0x55,0xB0,0x9E,0x19,0xD7, 00138 0x17,0xC6,0x35,0xD8,0xF0,0xAE,0xD4,0x2B,0x1D,0xA0,0x99,0x8A,0x15,0x00,0xAF,0x2D, 00139 0x09,0xA8,0xF5,0x6C,0xA1,0x63,0x67,0x51,0x3C,0xB2,0xC0,0xED,0x94,0x03,0x6F,0xBA, 00140 0x3F,0x4E,0x62,0x92,0x85,0xDD,0xAB,0xFE,0x10,0x2E,0x68,0x65,0xE7,0x04,0xF6,0x0C, 00141 0x20,0x1C,0xA9,0x53,0x40,0x77,0x2F,0xA4,0xFA,0x6D,0x73,0x28,0xE2,0xCD,0x79,0xC8, 00142 0x97,0x66,0x8E,0x82,0x74,0x06,0xC7,0x88,0x1A,0x4A,0x6B,0xCC,0x41,0xE9,0x9D,0xB8, 00143 0x23,0x9F,0x3D,0xBF,0x8D,0x95,0xC5,0x13,0xB9,0x24,0x5A,0xDC,0x64,0x18,0x38,0x91, 00144 0x7F,0x5B,0x70,0x54,0x07,0xB6,0x4B,0x0E,0x36,0xAC,0x31,0xE6,0xD6,0x48,0xAA,0xB4 00145 }; 00146 00147 cCamCrypt::cCamCrypt(void) 00148 { 00149 randomInit=false; 00150 } 00151 00152 void cCamCrypt::GenerateRandom(unsigned char *randVal, int len) 00153 { 00154 static const unsigned int seed = 0x9E3779B9; 00155 if(!randomInit) { 00156 RAND_seed(&seed,sizeof(seed)); 00157 randomInit=true; 00158 } 00159 RAND_bytes(randVal,len); 00160 } 00161 00162 // 00163 // Rotates the 8 bytes bitwise right 00164 // 00165 void cCamCrypt::RotateRight8Byte(unsigned char *key) 00166 { 00167 unsigned char t1=key[0]; 00168 for(int k=7 ; k>=0 ; k--) { 00169 unsigned char t2=t1<<7; 00170 t1=key[k]; key[k]=(t1>>1) | t2; 00171 } 00172 } 00173 00174 // 00175 // Rotates the 8 bytes bitwise left 00176 // 00177 void cCamCrypt::RotateLeft8Byte(unsigned char *key) 00178 { 00179 unsigned char t1=key[7]; 00180 for(int k=0 ; k<8 ; k++) { 00181 unsigned char t2=t1>>7; 00182 t1=key[k]; key[k]=(t1<<1) | t2; 00183 } 00184 } 00185 00186 void cCamCrypt::RevCamCrypt(const unsigned char *key, unsigned char *data) 00187 { 00188 unsigned char localKey[8]; 00189 memcpy(localKey,key,sizeof(localKey)); 00190 for(int idx1=0 ; idx1<8 ; idx1++) { 00191 for(int idx2=0 ; idx2<8 ; idx2++) { 00192 const unsigned char tmp1=cryptTable[data[7] ^ localKey[idx2] ^ idx1]; 00193 const unsigned char tmp2=data[0]; 00194 data[0]=data[1]; 00195 data[1]=data[2]; 00196 data[2]=data[3]; 00197 data[3]=data[4]; 00198 data[4]=data[5]; 00199 data[5]=data[6] ^ tmp1; 00200 data[6]=data[7]; 00201 data[7]=tmp1 ^ tmp2 ; 00202 } 00203 RotateLeft8Byte(localKey); 00204 } 00205 } 00206 00207 void cCamCrypt::CamCrypt(const unsigned char *key, unsigned char *data) 00208 { 00209 unsigned char localKey[8]; 00210 memcpy(localKey,key,sizeof(localKey)); 00211 for(int idx1=0 ; idx1<7 ; idx1++) RotateLeft8Byte(localKey); 00212 for(int idx1=7 ; idx1>=0 ; idx1--) { 00213 for(int idx2=7 ; idx2>=0 ; idx2--) { 00214 const unsigned char tmp1=cryptTable[data[6] ^ localKey[idx2] ^ idx1]; 00215 const unsigned char tmp2=data[0]; 00216 data[0]=data[7] ^ tmp1; 00217 data[7]=data[6]; 00218 data[6]=data[5] ^ tmp1; 00219 data[5]=data[4]; 00220 data[4]=data[3]; 00221 data[3]=data[2]; 00222 data[2]=data[1]; 00223 data[1]=tmp2; 00224 } 00225 RotateRight8Byte(localKey); 00226 } 00227 } 00228 00229 bool cCamCrypt::SetupCardFiles(unsigned char *data, int len, BIGNUM *exp, BIGNUM *mod) 00230 { 00231 if(rsa.RSA(data,data,len,exp,mod,false)<=0 || (data[0]!=0x80 || data[11]!=0x40 || data[12]!=0x06)) 00232 return false; 00233 BN_complement(data+13,64,cardMod); 00234 BN_bin2bn(data+13+64,6,cardExp); 00235 return true; 00236 } 00237 00238 void cCamCrypt::PrepareCamMessage(unsigned char *plain) 00239 { 00240 /* 00241 static const unsigned char camMsg[] = { 00242 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 00243 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 00244 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 00245 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00 00246 }; 00247 memcpy(plain,camMsg,sizeof(camMsg)); 00248 */ 00249 plain[0]=0x80; 00250 memset(plain+1 ,0x00,7); 00251 GenerateRandom(plain+16,16); 00252 memcpy(plain+8,plain+16,8); 00253 memset(plain+32,0xFF,31); 00254 plain[63]=0x00; 00255 } 00256 00257 bool cCamCrypt::EncryptCamMessage(unsigned char *encrypted, const unsigned char *plain) 00258 { 00259 return rsa.RSA(encrypted,plain,64,cardExp,cardMod,false)>0; 00260 } 00261 00262 // -- cSmartCardDataIrdeto ----------------------------------------------------- 00263 00264 class cSmartCardDataIrdeto : public cSmartCardData { 00265 public: 00266 int acs, caid; 00267 cBN mod, exp; 00268 bool plain; 00269 // 00270 cSmartCardDataIrdeto(void); 00271 cSmartCardDataIrdeto(int Acs, int Caid); 00272 virtual bool Parse(const char *line); 00273 virtual bool Matches(cSmartCardData *param); 00274 }; 00275 00276 cSmartCardDataIrdeto::cSmartCardDataIrdeto(void) 00277 :cSmartCardData(SC_ID) 00278 { 00279 plain=false; 00280 } 00281 00282 cSmartCardDataIrdeto::cSmartCardDataIrdeto(int Acs, int Caid) 00283 :cSmartCardData(SC_ID) 00284 { 00285 acs=Acs; caid=Caid; 00286 plain=false; 00287 } 00288 00289 bool cSmartCardDataIrdeto::Matches(cSmartCardData *param) 00290 { 00291 cSmartCardDataIrdeto *cd=(cSmartCardDataIrdeto *)param; 00292 return cd->acs==acs && (cd->caid==caid || caid==-1); 00293 } 00294 00295 bool cSmartCardDataIrdeto::Parse(const char *line) 00296 { 00297 unsigned char buff[512]; 00298 acs=caid=-1; // default 00299 line=skipspace(line); 00300 if(*line=='[') { // parse acs & caid 00301 line++; 00302 if(GetHex(line,buff,2)!=2) { 00303 PRINTF(L_CORE_LOAD,"smartcarddatairdeto: format error: acs"); 00304 return false; 00305 } 00306 acs=buff[0]*256+buff[1]; 00307 00308 line=skipspace(line); 00309 if(*line=='/') { 00310 line++; 00311 if(GetHex(line,buff,2)!=2) { 00312 PRINTF(L_CORE_LOAD,"smartcarddatairdeto: format error: caid"); 00313 return false; 00314 } 00315 caid=buff[0]*256+buff[1]; 00316 line=skipspace(line); 00317 } 00318 00319 if(!*line==']') { 00320 PRINTF(L_CORE_LOAD,"smartcarddatairdeto: format error: closing ]"); 00321 return false; 00322 } 00323 line++; 00324 } 00325 00326 line=skipspace(line); 00327 if(!strncasecmp(line,"plain",5)) { 00328 plain=true; 00329 return true; 00330 } 00331 int l; 00332 if((l=GetHex(line,buff,sizeof(buff),false))<=0) { 00333 PRINTF(L_CORE_LOAD,"smartcarddatairdeto: format error: mod"); 00334 return false; 00335 } 00336 BN_complement(buff,l,mod); 00337 if((l=GetHex(line,buff,sizeof(buff),false))<=0) { 00338 PRINTF(L_CORE_LOAD,"smartcarddatairdeto: format error: exp"); 00339 return false; 00340 } 00341 BN_bin2bn(buff,l,exp); 00342 return true; 00343 } 00344 00345 // -- cSmartCardIrdeto --------------------------------------------------------- 00346 00347 #define XOR_START 0x3F // Start value for xor checksumm 00348 #define ADDRLEN 4 // Address length in EMM commands 00349 #define MAX_PROV 16 00350 #define RECOVER_TIME 100 // Time in ms which the card needs to recover after 00351 // a failed command 00352 00353 class cSmartCardIrdeto : public cSmartCard, private cCamCrypt, private cIdSet { 00354 private: 00355 unsigned char buff[MAX_LEN+1]; 00356 unsigned char camKey[8]; 00357 char asciiSerial[22], coco[4]; 00358 int ACS, caId; 00359 int numProv; 00360 cTimeMs recoverTime; 00361 // 00362 int DoCmd(unsigned char *cmd, int goodSB, int secGoodSB=-1); 00363 bool ReadCardInfo(void); 00364 time_t Date(int date, char *buff, int len); 00365 public: 00366 cSmartCardIrdeto(void); 00367 virtual bool Init(void); 00368 virtual bool Decode(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw); 00369 virtual bool Update(int pid, int caid, const unsigned char *data); 00370 virtual bool CanHandle(unsigned short CaId); 00371 }; 00372 00373 static const struct StatusMsg msgs[] = { 00374 { { 0x00,0x00 }, "Instruction executed without error", true }, 00375 { { 0x55,0x00 }, "Instruction executed without error", true }, 00376 { { 0x57,0x00 }, "CAM string rejected", false }, 00377 { { 0x58,0x00 }, "Instruction executed without error", true }, 00378 { { 0x9D,0x00 }, "Decoding successfull", true }, 00379 { { 0x90,0x00 }, "ChID missing. Not subscribed?", false }, 00380 { { 0x93,0x00 }, "ChID out of date. Subscription expired?", false }, 00381 { { 0x9C,0x00 }, "Master key error", false }, 00382 { { 0x9E,0x00 }, "Wrong decryption key", false }, 00383 { { 0x9F,0x00 }, "Missing key", false }, 00384 { { 0x70,0x00 }, "Wrong hex serial", false }, 00385 { { 0x71,0x00 }, "Wrong provider", false }, 00386 { { 0x72,0x00 }, "Wrong provider group", false }, 00387 { { 0x73,0x00 }, "Wrong provider group", false }, 00388 { { 0x7C,0x00 }, "Wrong signature", false }, 00389 { { 0x7D,0x00 }, "Masterkey missing", false }, 00390 { { 0x7E,0x00 }, "Wrong provider identifier", false }, 00391 { { 0x7F,0x00 }, "Invalid nano", false }, 00392 { { 0x54,0x00 }, "No more ChID's", true }, 00393 { { 0xFF,0xFF }, 0, false } 00394 }; 00395 00396 static const struct CardConfig cardCfg = { 00397 SM_8N2,3000,100 00398 }; 00399 00400 cSmartCardIrdeto::cSmartCardIrdeto(void) 00401 :cSmartCard(&cardCfg,msgs) 00402 { 00403 ACS=0; caId=0; numProv=0; 00404 } 00405 00406 bool cSmartCardIrdeto::Init(void) 00407 { 00408 ResetIdSet(); 00409 recoverTime.Set(-RECOVER_TIME); 00410 if(atr->histLen<6 || memcmp(atr->hist,"IRDETO",6)) { 00411 PRINTF(L_SC_INIT,"doesn't looks like a Irdeto/Beta card"); 00412 return false; 00413 } 00414 00415 infoStr.Begin(); 00416 infoStr.Strcat("Irdeto smartcard\n"); 00417 int r; 00418 static unsigned char getCountryCode[] = { 0x01,0x02,0x02,0x03,0x00,0x00,0xCC }; 00419 if((r=DoCmd(getCountryCode,0x0000))<=0 || !Status() || r<16) { 00420 PRINTF(L_SC_ERROR,"country code error"); 00421 return false; 00422 } 00423 ACS=buff[8]*256+buff[9]; 00424 int c=buff[13]*256+buff[14]; 00425 if(c!=caId) CaidsChanged(); 00426 caId=c; 00427 memcpy(coco,&buff[21],3); coco[3]=0; 00428 PRINTF(L_SC_INIT,"ACS Version %04x, CAID %04x, CoCo %s",ACS,caId,coco); 00429 snprintf(idStr,sizeof(idStr),"%s (ACS %x)",SC_NAME,ACS); 00430 infoStr.Printf("ACS: %04x CAID: %04x CoCo: %s\n",ACS,caId,coco); 00431 00432 static unsigned char getAsciiSerial[] = { 0x01,0x02,0x00,0x03,0x00,0x00,0xCC }; 00433 if((r=DoCmd(getAsciiSerial,0x0000))<=0 || !Status() || r<10) { 00434 PRINTF(L_SC_ERROR,"ASCII serial error"); 00435 return false; 00436 } 00437 strn0cpy(asciiSerial,(char*)buff+8,sizeof(asciiSerial)); 00438 PRINTF(L_SC_INIT,"ASCII serial %s",asciiSerial); 00439 00440 static unsigned char getHexSerial[] = { 0x01,0x02,0x01,0x03,0x00,0x00,0xCC }; 00441 if((r=DoCmd(getHexSerial,0x0000))<=0 || !Status() || r<25) { 00442 PRINTF(L_SC_ERROR,"hex serial error"); 00443 return false; 00444 } 00445 int numProv=buff[18]; 00446 SetCard(new cCardIrdeto(buff[23],&buff[20])); 00447 PRINTF(L_SC_INIT,"Providers: %d HEX Serial: %02X%02X%02X HEX Base: %02X",numProv,buff[20],buff[21],buff[22],buff[23]); 00448 infoStr.Printf("HEX: %02X/%02X%02X%02X ASCII: %s\n",buff[23],buff[20],buff[21],buff[22],asciiSerial); 00449 00450 static unsigned char getCardFile[] = { 0x01,0x02,0x0E,0x02,0x00,0x00,0xCC }; 00451 unsigned char encr[128], plain[64+6+2]; 00452 PrepareCamMessage(plain+6); 00453 getCardFile[3]=0x02; 00454 if((r=DoCmd(getCardFile,0x0000))<=0 || !Status() || r<73) { 00455 PRINTF(L_SC_ERROR,"cardfile2 error"); 00456 return false; 00457 } 00458 memcpy(encr,buff+8,64); 00459 getCardFile[3]=0x03; 00460 if((r=DoCmd(getCardFile,0x0000))<=0 || !Status() || r<73) { 00461 PRINTF(L_SC_ERROR,"cardfile3 error"); 00462 return false; 00463 } 00464 memcpy(encr+64,buff+8,64); 00465 00466 bool doPlain=false; 00467 if((ACS==0x0383 || ACS==0x0384) && atr->histLen>=12 && atr->hist[12]==0x95) 00468 doPlain=true; 00469 cSmartCardDataIrdeto *entry=0; 00470 if(!doPlain) { 00471 cSmartCardDataIrdeto cd(ACS,caId); 00472 if(!(entry=(cSmartCardDataIrdeto *)smartcards.FindCardData(&cd))) { 00473 PRINTF(L_GEN_WARN,"didn't find Irdeto card specific certificate, falling back to default"); 00474 cSmartCardDataIrdeto cd(-1,-1); 00475 if(!(entry=(cSmartCardDataIrdeto *)smartcards.FindCardData(&cd))) { 00476 PRINTF(L_GEN_WARN,"didn't find default Irdeto certificate, please add one"); 00477 if(ACS!=0x0384) return false; 00478 PRINTF(L_GEN_WARN,"trying pre-coded ACS 384 challenge. This mode is DEPRECATED. There ARE valid certificates for these cards available!"); 00479 } 00480 } 00481 else doPlain=entry->plain; 00482 } 00483 static unsigned char doCamKeyExchange[] = { 0x01,0x02,0x09,0x03,0x00,0x40 }; 00484 if(doPlain) { 00485 // plain challenge 00486 memcpy(plain,doCamKeyExchange,sizeof(doCamKeyExchange)); 00487 plain[4]=1; // set block counter 00488 r=DoCmd(plain,0x5500,0x0000); 00489 } 00490 else { 00491 // RSA challenge 00492 if(entry) { 00493 if(!SetupCardFiles(encr,sizeof(encr),entry->exp,entry->mod)) { 00494 PRINTF(L_SC_ERROR,"decrypting cardfiles failed. Probably bad certificate."); 00495 return false; 00496 } 00497 if(!EncryptCamMessage(encr+6,plain+6)) { 00498 PRINTF(L_SC_ERROR,"encrypting CAM message failed. Probably bad certificate."); 00499 return false; 00500 } 00501 00502 static unsigned char doRSACheck[] = { 0x01,0x02,0x11,0x00,0x00,0x40 }; 00503 memcpy(plain,doRSACheck,sizeof(doRSACheck)); 00504 if((r=DoCmd(plain,0x5800,0x0000))<=0 || !Status() || r<73) { 00505 PRINTF(L_SC_ERROR,"card didn't give a proper reply (buggy RSA unit?), trying to continue..."); 00506 // non-fatal 00507 } 00508 if(r==73 && memcmp(encr+6,buff+8,64)) { 00509 PRINTF(L_SC_ERROR,"card failed on RSA check, trying to continue..."); 00510 // non-fatal 00511 } 00512 } 00513 else { 00514 static const unsigned char enc384cz[] = { 00515 0x18,0xD7,0x55,0x14,0xC0,0x83,0xF1,0x38, 0x39,0x6F,0xF2,0xEC,0x4F,0xE3,0xF1,0x85, 00516 0x01,0x46,0x06,0xCE,0x7D,0x08,0x2C,0x74, 0x46,0x8F,0x72,0xC4,0xEA,0xD7,0x9C,0xE0, 00517 0xE1,0xFF,0x58,0xE7,0x70,0x0C,0x92,0x45, 0x26,0x18,0x4F,0xA0,0xE2,0xF5,0x9E,0x46, 00518 0x6F,0xAE,0x95,0x35,0xB0,0x49,0xB2,0x0E, 0xA4,0x1F,0x8E,0x47,0xD0,0x24,0x11,0xD0 00519 }; 00520 static const unsigned char enc384dz[] = { 00521 0x27,0xF2,0xD6,0xCD,0xE6,0x88,0x62,0x46, 0x81,0xB0,0xF5,0x3E,0x6F,0x13,0x4D,0xCC, 00522 0xFE,0xD0,0x67,0xB1,0x93,0xDD,0xF4,0xDE, 0xEF,0xF5,0x3B,0x04,0x1D,0xE5,0xC3,0xB2, 00523 0x54,0x38,0x57,0x7E,0xC8,0x39,0x07,0x2E, 0xD2,0xF4,0x05,0xAA,0x15,0xB5,0x55,0x24, 00524 0x90,0xBB,0x9B,0x00,0x96,0xF0,0xCB,0xF1, 0x8A,0x08,0x7F,0x0B,0xB8,0x79,0xC3,0x5D 00525 }; 00526 static const unsigned char ck[] = { 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88 }; 00527 static const unsigned char hk[] = { 0x12,0x34,0x56,0x78,0x90,0xAB,0xCD,0xEF }; 00528 00529 if(caId==0x1702) memcpy(encr+6,enc384cz,sizeof(enc384cz)); 00530 else if(caId==0x1722) memcpy(encr+6,enc384dz,sizeof(enc384dz)); 00531 else { 00532 PRINTF(L_GEN_WARN,"no pre-coded Irdeto camkey challenge for caid %04x",caId); 00533 return false; 00534 } 00535 memcpy((void *)CamKey(plain+6),ck,sizeof(ck)); 00536 memcpy((void *)HelperKey(plain+6),hk,sizeof(hk)); 00537 } 00538 00539 memcpy(encr,doCamKeyExchange,sizeof(doCamKeyExchange)); 00540 r=DoCmd(encr,0x5500,0x0000); 00541 } 00542 00543 if(r>0 && Status() && r>=9) { 00544 memcpy(camKey,CamKey(plain+6),8); 00545 if(r>=17) { 00546 RevCamCrypt(camKey,buff+8); 00547 if(memcmp(HelperKey(plain+6),buff+8,8)) { 00548 PRINTF(L_SC_ERROR,"camkey challenge failed"); 00549 return false; 00550 } 00551 } 00552 LDUMP(L_SC_INIT,camKey,sizeof(camKey),"camkey"); 00553 } 00554 else { 00555 PRINTF(L_SC_ERROR,"camkey error"); 00556 return false; 00557 } 00558 00559 static unsigned char getProvider[] = { 0x01,0x02,0x03,0x03,0x00,0x00,0xCC }; 00560 static unsigned char getChanelIds[] = { 0x01,0x02,0x04,0x00,0x00,0x01,0x00,0xCC }; 00561 for(int i=0; i<numProv; i++) { 00562 getProvider[4]=i; 00563 if((r=DoCmd(getProvider,0x0000))>0 && Status() && r>=33) { 00564 AddProv(new cProviderIrdeto(buff[8]&0x0f,&buff[9])); 00565 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]); 00566 infoStr.Printf("Provider %d Id: %02X/%02X%02X%02X\n",i,buff[8]&0x0f,buff[9],buff[10],buff[11]); 00567 00568 getChanelIds[4]=i; 00569 for(int l=0; l<10; l++) { 00570 getChanelIds[6]=l; 00571 if((r=DoCmd(getChanelIds,0x0000,0x5400))<=0 || !Status() || r<69) break; 00572 for(int k=0; k<buff[7]; k+=6) { 00573 int chanId=buff[k+8+0]*256+buff[k+8+1]; 00574 int date =buff[k+8+2]*256+buff[k+8+3]; 00575 int durr =buff[k+8+4]; 00576 if(chanId!=0x0000 && chanId!=0xFFFF) { 00577 char sdate[16], edate[16]; 00578 Date(date,sdate,sizeof(sdate)); 00579 Date(date+durr,edate,sizeof(edate)); 00580 PRINTF(L_SC_INIT,"ChanId 0x%04x Date 0x%04x %s Duration 0x%02x %s",chanId,date,sdate,durr,edate); 00581 infoStr.Printf("ChanId: %04X Date: %s-%s\n",chanId,sdate,edate); 00582 } 00583 } 00584 } 00585 } 00586 } 00587 00588 #if 0 00589 static unsigned char getCountryCode2[] = { 0x01,0x02,0x0B,0x00,0x00,0x00,0xCC }; 00590 if((r=DoCmd(getCountryCode2,0x0000))>0 && Status() && r>=32) { 00591 PRINTF(L_SC_INIT,"max ChID's %d,%d,%d,%d",buff[14],buff[15],buff[16],buff[17]); 00592 } 00593 #endif 00594 00595 infoStr.Finish(); 00596 return true; 00597 } 00598 00599 time_t cSmartCardIrdeto::Date(int date, char *buff, int len) 00600 { 00601 // Irdeto date starts 01.08.1997 which is 00602 // 870393600 seconds in unix calendar time 00603 time_t utcTime=870393600L+date*(24*3600); 00604 if(buff) { 00605 struct tm utcTm; 00606 gmtime_r(&utcTime,&utcTm); 00607 snprintf(buff,len,"%04d/%02d/%02d",utcTm.tm_year+1900,utcTm.tm_mon+1,utcTm.tm_mday); 00608 } 00609 return utcTime; 00610 } 00611 00612 bool cSmartCardIrdeto::CanHandle(unsigned short CaId) 00613 { 00614 return (CaId==caId); 00615 } 00616 00617 bool cSmartCardIrdeto::Decode(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw) 00618 { 00619 static const unsigned char ecmCmd[] = { 0x01,0x05,0x00,0x00,0x02,0x00 }; 00620 00621 int r=SCT_LEN(data)-6; 00622 if(r<=255) { 00623 unsigned char cmd[257+sizeof(ecmCmd)]; 00624 memcpy(cmd,ecmCmd,sizeof(ecmCmd)); 00625 cmd[5]=r; 00626 memcpy(cmd+sizeof(ecmCmd),&data[6],r); 00627 if((r=DoCmd(cmd,0x9D00))>0) { 00628 if(Status() && r>=31) { 00629 RevCamCrypt(camKey,&buff[14]); 00630 RevCamCrypt(camKey,&buff[22]); 00631 memcpy(cw,&buff[14],16); 00632 return true; 00633 } 00634 } 00635 } 00636 return false; 00637 } 00638 00639 bool cSmartCardIrdeto::Update(int pid, int caid, const unsigned char *data) 00640 { 00641 static const unsigned char emmCmd[] = { 0x01,0x01,0x00,0x00,0x00,0x00 }; 00642 00643 if(MatchEMM(data)) { 00644 int len=cParseIrdeto::AddrLen(data)+1; 00645 if(len<=ADDRLEN) { 00646 const int dataLen=SCT_LEN(data)-5-len; // sizeof of data bytes (nanos) 00647 if(dataLen<=255-ADDRLEN) { 00648 unsigned char cmd[257+sizeof(emmCmd)]; 00649 memcpy(cmd,emmCmd,sizeof(emmCmd)); 00650 cmd[5]=dataLen+ADDRLEN; 00651 memset(cmd+sizeof(emmCmd),0,ADDRLEN); 00652 memcpy(cmd+sizeof(emmCmd),&data[3],len); 00653 memcpy(cmd+sizeof(emmCmd)+ADDRLEN,&data[len+5],dataLen); 00654 if(DoCmd(cmd,0x0000)>0 && Status()) return true; 00655 } 00656 } 00657 else PRINTF(L_SC_ERROR,"addrlen %d > %d",len,ADDRLEN); 00658 } 00659 return false; 00660 } 00661 00662 int cSmartCardIrdeto::DoCmd(unsigned char *cmd, int goodSB, int secGoodSB) 00663 { 00664 int len=cmd[5]+6; 00665 cmd[len]=XorSum(cmd,len) ^ XOR_START; 00666 // wait until recover time is over 00667 int r=RECOVER_TIME-recoverTime.Elapsed(); 00668 if(r>0) { 00669 PRINTF(L_SC_ERROR,"recover time, waiting %d ms",r); 00670 cCondWait::SleepMs(r+1); 00671 } 00672 r=-1; 00673 LDUMP(L_CORE_SC,cmd,len+1,"IRDETO: CMD ->"); 00674 if(SerWrite(cmd,len+1)>0 && SerRead(buff,4,cardCfg.workTO)>0) { 00675 len=4; 00676 if(buff[0]==cmd[0] && buff[1]==cmd[1]) { 00677 sb[0]=buff[2]; sb[1]=buff[3]; 00678 int SB=buff[2]*256+buff[3]; 00679 if(SB==goodSB || (secGoodSB>=0 && SB==secGoodSB)) { 00680 if(SerRead(buff+len,5)>0) { 00681 len+=5; 00682 if(buff[7]) { 00683 if(SerRead(buff+len,buff[7])<=0) return -1; 00684 len+=buff[7]; 00685 } 00686 if(XorSum(buff,len)==XOR_START) r=len; 00687 else LDUMP(L_CORE_SC,buff,len,"IRDETO: checksum failed"); 00688 } 00689 } 00690 else r=len; 00691 } 00692 else { 00693 sb[0]=buff[1]; sb[1]=buff[2]; 00694 r=3; 00695 } 00696 } 00697 if(r>0) LDUMP(L_CORE_SC,buff,r,"IRDETO: RESP <-"); 00698 if(r<=4) { 00699 recoverTime.Set(); 00700 PRINTF(L_SC_ERROR,"setting %d ms recover time",RECOVER_TIME); 00701 } 00702 return r; 00703 } 00704 00705 // -- cSmartCardLinkIrdeto ----------------------------------------------------- 00706 00707 class cSmartCardLinkIrdeto : public cSmartCardLink { 00708 public: 00709 cSmartCardLinkIrdeto(void):cSmartCardLink(SC_NAME,SC_ID) {} 00710 virtual cSmartCard *Create(void) { return new cSmartCardIrdeto(); } 00711 virtual cSmartCardData *CreateData(void) { return new cSmartCardDataIrdeto; } 00712 }; 00713 00714 static cSmartCardLinkIrdeto staticScInit;