|
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 <stdlib.h> 00021 #include <string.h> 00022 00023 #include <openssl/rand.h> 00024 00025 #include "system-common.h" 00026 #include "smartcard.h" 00027 #include "parse.h" 00028 #include "crypto.h" 00029 #include "helper.h" 00030 #include "opts.h" 00031 #include "log-sc.h" 00032 #include "log-core.h" 00033 #include "version.h" 00034 00035 SCAPIVERSTAG(); 00036 00037 #define SYSTEM_NAGRA 0x1800 00038 00039 #define SYSTEM_NAME "SC-Nagra" 00040 #define SYSTEM_PRI -5 00041 00042 #define SC_NAME "Nagra" 00043 #define SC_ID MAKE_SC_ID('N','a','g','r') 00044 00045 #define L_SC 11 00046 #define L_SC_PROC LCLASS(L_SC,L_SC_LASTDEF<<1) 00047 #define L_SC_ALL LALL(L_SC_PROC) 00048 00049 static const struct LogModule lm_sc = { 00050 (LMOD_ENABLE|L_SC_ALL)&LOPT_MASK, 00051 (LMOD_ENABLE|L_SC_DEFDEF|L_SC_PROC)&LOPT_MASK, 00052 "sc-nagra", 00053 { L_SC_DEFNAMES,"process" } 00054 }; 00055 ADD_MODULE(L_SC,lm_sc) 00056 00057 static int allowT14=0; 00058 00059 // -- cSystemScNagra --------------------------------------------------------------------- 00060 00061 class cSystemScNagra : public cSystemScCore { 00062 public: 00063 cSystemScNagra(void); 00064 }; 00065 00066 cSystemScNagra::cSystemScNagra(void) 00067 :cSystemScCore(SYSTEM_NAME,SYSTEM_PRI,SC_ID,"SC Nagra") 00068 { 00069 hasLogger=true; 00070 } 00071 00072 // -- cSystemLinkScNagra -------------------------------------------------------------- 00073 00074 class cSystemLinkScNagra : public cSystemLink { 00075 public: 00076 cSystemLinkScNagra(void); 00077 virtual bool CanHandle(unsigned short SysId); 00078 virtual cSystem *Create(void) { return new cSystemScNagra; } 00079 }; 00080 00081 static cSystemLinkScNagra staticInit; 00082 00083 cSystemLinkScNagra::cSystemLinkScNagra(void) 00084 :cSystemLink(SYSTEM_NAME,SYSTEM_PRI) 00085 { 00086 opts=new cOpts(SYSTEM_NAME,1); 00087 opts->Add(new cOptBool("AllowT14",trNOOP("SC-Nagra: use T14 Nagra mode"),&allowT14)); 00088 Feature.NeedsSmartCard(); 00089 } 00090 00091 bool cSystemLinkScNagra::CanHandle(unsigned short SysId) 00092 { 00093 bool res=false; 00094 cSmartCard *card=smartcards.LockCard(SC_ID); 00095 if(card) { 00096 res=card->CanHandle(SysId); 00097 smartcards.ReleaseCard(card); 00098 } 00099 return res; 00100 } 00101 00102 // -- cCamCryptNagra ------------------------------------------------------------------ 00103 00104 class cCamCryptNagra { 00105 private: 00106 cIDEA idea; 00107 cRSA rsa; 00108 cBN camMod, camExp; 00109 IdeaKS sessKey; 00110 unsigned int cardid; 00111 unsigned char boxkey[8], signature[8]; 00112 bool hasMod; 00113 // 00114 void InitKey(unsigned char *key, const unsigned char *bk, unsigned int id); 00115 void Signature(unsigned char *sig, const unsigned char *key, const unsigned char *msg, int len); 00116 public: 00117 cCamCryptNagra(void); 00118 void SetCardData(unsigned int id, const unsigned char *bk, BIGNUM *exp); 00119 void SetCamMod(BIGNUM *m); 00120 bool HasCamMod(void) { return hasMod; } 00121 bool DecryptDT08(const unsigned char *dt08, unsigned int irdid, cBN *irdmod, bool fakeid); 00122 bool MakeSessionKey(unsigned char *out, const unsigned char *in); 00123 void DecryptCW(unsigned char *cw, const unsigned char *ecw1, const unsigned char *ecw2); 00124 }; 00125 00126 cCamCryptNagra::cCamCryptNagra(void) 00127 { 00128 hasMod=false; 00129 } 00130 00131 void cCamCryptNagra::SetCardData(unsigned int id, const unsigned char *bk, BIGNUM *exp) 00132 { 00133 cardid=id; 00134 memcpy(boxkey,bk,sizeof(boxkey)); 00135 BN_copy(camExp,exp); 00136 if(LOG(L_SC_PROC)) { 00137 unsigned char bb[4]; 00138 camExp.Put(bb,2); 00139 LDUMP(L_SC_PROC,boxkey,sizeof(boxkey),"Active card data: CARDID: %08x EXP: %02x%02x BOXKEY:",cardid,bb[0],bb[1]); 00140 } 00141 } 00142 00143 void cCamCryptNagra::SetCamMod(BIGNUM *m) 00144 { 00145 BN_copy(camMod,m); 00146 memcpy(signature,boxkey,sizeof(signature)); 00147 hasMod=true; 00148 } 00149 00150 void cCamCryptNagra::InitKey(unsigned char *key, const unsigned char *bk, unsigned int id) 00151 { 00152 memcpy(key,bk,8); 00153 BYTE4_BE(key+8 , id); 00154 BYTE4_BE(key+12,~id); 00155 } 00156 00157 void cCamCryptNagra::Signature(unsigned char *sig, const unsigned char *key, const unsigned char *msg, int len) 00158 { 00159 unsigned char buff[16]; 00160 memcpy(buff,key,16); 00161 for(int i=0; i<len; i+=8) { 00162 idea.Decrypt(msg+i,8,buff,buff,0); 00163 xxor(buff,8,buff,&msg[i]); 00164 memcpy(&buff[8],buff,8); 00165 } 00166 memcpy(sig,buff,8); 00167 } 00168 00169 bool cCamCryptNagra::DecryptDT08(const unsigned char *dt08, unsigned int irdid, cBN *irdmod, bool fakeid) 00170 { 00171 if(LOG(L_SC_PROC)) { 00172 unsigned char bb[64]; 00173 irdmod->Put(bb,sizeof(bb)); 00174 LDUMP(L_SC_PROC,bb,sizeof(bb),"DT08 decrypt IRDID: %08x IRDMOD:",irdid); 00175 } 00176 unsigned char buff[72]; 00177 if(rsa.RSA(buff,dt08+1,64,camExp,*irdmod)!=64) return false; 00178 memcpy(buff+64,dt08+1+64,8); 00179 buff[63]|=dt08[0]&0x80; 00180 LDUMP(L_SC_PROC,buff,72,"DT08 after RSA"); 00181 00182 unsigned char key[16]; 00183 InitKey(key,boxkey,irdid); 00184 LDUMP(L_SC_PROC,key,16,"DT08 IDEA key"); 00185 IdeaKS dks; 00186 idea.SetDecKey(key,&dks); 00187 idea.Decrypt(buff,72,&dks,0); 00188 LDUMP(L_SC_PROC,buff,72,"DT08 after IDEA"); 00189 00190 memcpy(signature,buff,8); 00191 LDUMP(L_SC_PROC,signature,8,"signature"); 00192 BYTE4_BE(buff ,0); 00193 BYTE4_BE(buff+4,fakeid?0xFFFFFFFF:cardid); 00194 Signature(buff,key,buff,72); 00195 LDUMP(L_SC_PROC,buff,8,"check sig"); 00196 if(memcmp(signature,buff,8)) { 00197 PRINTF(L_SC_PROC,"DT08 signature failed"); 00198 return false; 00199 } 00200 BN_bin2bn(buff+8,64,camMod); 00201 hasMod=true; 00202 return true; 00203 } 00204 00205 bool cCamCryptNagra::MakeSessionKey(unsigned char *out, const unsigned char *camdata) 00206 { 00207 if(!hasMod) return false; 00208 if(LOG(L_SC_PROC)) { 00209 unsigned char bb[64]; 00210 camMod.Put(bb,sizeof(bb)); 00211 LDUMP(L_SC_PROC,bb,sizeof(bb),"Sessionkey negotiation CAMMOD:"); 00212 } 00213 //decrypt $2A data here and prepare $2B reply 00214 if(rsa.RSA(out,camdata,64,camExp,camMod)!=64) return false; 00215 LDUMP(L_SC_PROC,out,64,"CMD 2A/26 after RSA:"); 00216 00217 unsigned char key[16], sess[16]; 00218 InitKey(key,signature,cardid); 00219 LDUMP(L_SC_PROC,key,16,"first IDEA key: "); 00220 Signature(sess,key,out,32); 00221 memcpy(key,sess,8); 00222 memcpy(key+8,sess,8); 00223 LDUMP(L_SC_PROC,key,16,"second IDEA key:"); 00224 Signature(sess+8,key,out,32); 00225 LDUMP(L_SC_PROC,sess,16,"SESSION KEY: "); 00226 idea.SetDecKey(sess,&sessKey); 00227 00228 if(rsa.RSA(out,out,64,camExp,camMod)!=64) return false; 00229 LDUMP(L_SC_PROC,out,64,"CMD 2B/27 data:"); 00230 return true; 00231 } 00232 00233 void cCamCryptNagra::DecryptCW(unsigned char *cw, const unsigned char *ecw1, const unsigned char *ecw2) 00234 { 00235 memcpy(cw+0,ecw1,8); 00236 idea.Decrypt(cw+0,8,&sessKey,0); 00237 memcpy(cw+8,ecw2,8); 00238 idea.Decrypt(cw+8,8,&sessKey,0); 00239 } 00240 00241 // -- cSmartCardDataNagra ------------------------------------------------------ 00242 00243 struct SecondaryKey { 00244 unsigned char irdid[4]; 00245 unsigned char free[8]; 00246 unsigned char exp[2]; 00247 unsigned char y1[8]; 00248 unsigned char mod[64]; 00249 unsigned char y2[8]; 00250 unsigned char cs[2]; 00251 } __attribute__((packed)); 00252 00253 class cSmartCardDataNagra : public cSmartCardData { 00254 private: 00255 unsigned short CRC16(const unsigned char *mem, int len, bool reverse); 00256 public: 00257 unsigned int cardid; 00258 unsigned char bk[8]; 00259 cBN exp, mod; 00260 bool isIrdMod; 00261 // 00262 cSmartCardDataNagra(void); 00263 cSmartCardDataNagra(unsigned int id, bool irdmod); 00264 virtual bool Parse(const char *line); 00265 virtual bool Matches(cSmartCardData *param); 00266 }; 00267 00268 cSmartCardDataNagra::cSmartCardDataNagra(void) 00269 :cSmartCardData(SC_ID) {} 00270 00271 cSmartCardDataNagra::cSmartCardDataNagra(unsigned int id, bool irdmod) 00272 :cSmartCardData(SC_ID) 00273 { 00274 cardid=id; 00275 isIrdMod=irdmod; 00276 } 00277 00278 bool cSmartCardDataNagra::Matches(cSmartCardData *param) 00279 { 00280 cSmartCardDataNagra *cd=(cSmartCardDataNagra *)param; 00281 return cd->cardid==cardid && cd->isIrdMod==isIrdMod; 00282 } 00283 00284 bool cSmartCardDataNagra::Parse(const char *line) 00285 { 00286 bool isSK=false; 00287 int dlen=64; 00288 BN_set_word(exp,3); 00289 line=skipspace(line); 00290 unsigned char id[4]; 00291 if(GetHex(line,id,sizeof(id))!=sizeof(id)) { 00292 PRINTF(L_CORE_LOAD,"smartcarddatanagra: format error: card id"); 00293 return false; 00294 } 00295 cardid=UINT32_BE(id); 00296 line=skipspace(line); 00297 if(!strncasecmp(line,"SK",2)) { isSK=true; dlen=96; line+=2; } 00298 else { 00299 if(GetHex(line,bk,sizeof(bk))!=sizeof(bk)) { 00300 PRINTF(L_CORE_LOAD,"smartcarddatanagra: format error: boxkey"); 00301 return false; 00302 } 00303 line=skipspace(line); 00304 if(!strncasecmp(line,"IRDMOD",6)) { isIrdMod=true; line+=6; } 00305 else if(!strncasecmp(line,"CARDMOD",7)) { isIrdMod=false; line+=7; } 00306 else { 00307 PRINTF(L_CORE_LOAD,"smartcarddatanagra: format error: IRDMOD/CARDMOD"); 00308 return false; 00309 } 00310 } 00311 line=skipspace(line); 00312 00313 unsigned char *buff=AUTOMEM(dlen); 00314 if(GetHex(line,buff,dlen)!=dlen) { 00315 PRINTF(L_CORE_LOAD,"smartcarddatanagra: format error: data block"); 00316 return false; 00317 } 00318 if(!isSK) { 00319 mod.Get(buff,64); 00320 } 00321 else { 00322 struct SecondaryKey *sk=(struct SecondaryKey *)buff; 00323 if(UINT16_BE(sk->cs)!=CRC16(buff,sizeof(*sk)-sizeof(sk->cs),false)) { 00324 PRINTF(L_CORE_LOAD,"smartcarddatanagra: secondary key CRC failed"); 00325 return false; 00326 } 00327 unsigned short e=UINT16_BE(sk->exp); 00328 if(e!=0x0003 && e!=CRC16(buff,12,false)) BN_set_word(exp,e); 00329 xxor(bk,sizeof(bk),sk->y1,sk->y2); 00330 mod.Get(sk->mod,sizeof(sk->mod)); 00331 } 00332 return true; 00333 } 00334 00335 #define CRC_POLY 0x1021 // CRC-16(XMODEM) Polynomial: x16 + x12 + x5 + 1 00336 #define CRC_INIT 0x0000 00337 00338 unsigned short cSmartCardDataNagra::CRC16(const unsigned char *mem, int len, bool reverse) 00339 { 00340 int index=0, dir=1; 00341 if(reverse) { index=len-1; dir=-1; } 00342 unsigned short crc=CRC_INIT; 00343 for(int i=0; i<len; i++) { 00344 crc^=(unsigned short)(mem[index]<<8); 00345 index+=dir; 00346 for(int j=0; j<8; j++) { 00347 if((crc&0x8000)) crc=(unsigned short)(((crc<<1)&0xFFFF)^CRC_POLY); 00348 else crc=(unsigned short)( (crc<<1)&0xFFFF); 00349 } 00350 } 00351 return(crc); 00352 } 00353 00354 // -- cSmartCardNagra ----------------------------------------------------------------- 00355 00356 #define SETIFS 0xC1 00357 00358 // Datatypes 00359 #define IRDINFO 0x00 00360 #define DT01 0x01 00361 #define DT04 0x04 00362 #define TIERS 0x05 00363 #define DT06 0x06 00364 #define CAMDATA 0x08 00365 00366 #define MAX_REC 20 00367 00368 // Card Status checks 00369 #define HAS_CW() ((state[2]&6)==6) 00370 #define RENEW_SESSIONKEY() (state[0]&224) 00371 #define SENDDATETIME() (state[0]&16) 00372 00373 class cSmartCardNagra : public cSmartCard, public cIdSet, private cCamCryptNagra { 00374 private: 00375 unsigned char buff[MAX_LEN+16], state[3], rominfo[15]; 00376 unsigned int cardId, irdId; 00377 int caid, provId, block; 00378 bool isTiger, isT14Nagra, isN3, swapCW; 00379 // 00380 bool GetCardStatus(void); 00381 bool GetDataType(unsigned char dt, int len, int shots=MAX_REC); 00382 bool ParseDataType(unsigned char dt); 00383 bool DoCamExchange(void); 00384 bool SendDateTimeCmd(void); 00385 time_t Date(const unsigned char *data, char *buf, int len); 00386 bool DoBlkCmd(unsigned char cmd, int ilen, unsigned char res, int rlen, const unsigned char *data=0); 00387 bool SetIFS(unsigned char len); 00388 void PostProcess(void); 00389 public: 00390 cSmartCardNagra(void); 00391 virtual bool Init(void); 00392 virtual bool Decode(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw); 00393 virtual bool Update(int pid, int caid, const unsigned char *data); 00394 virtual bool CanHandle(unsigned short CaId); 00395 }; 00396 00397 static const struct StatusMsg msgs[] = { 00398 { { 0x6F,0x00 }, "Instruction not supported", false }, 00399 { { 0x90,0x00 }, "Instruction executed without errors", true }, 00400 { { 0xFF,0xFF }, 0, false } 00401 }; 00402 00403 static const struct CardConfig cardCfg = { 00404 SM_8O2,500,800 00405 }; 00406 00407 cSmartCardNagra::cSmartCardNagra(void) 00408 :cSmartCard(&cardCfg,msgs) 00409 {} 00410 00411 bool cSmartCardNagra::SetIFS(unsigned char size) 00412 { 00413 unsigned char buf[5]; 00414 // NAD, PCB, LEN 00415 buf[0]=0x21; buf[1]=0xC1; buf[2]=0x01; 00416 // Information Field size 00417 buf[3]=size; buf[4]=XorSum(buf,4); 00418 PRINTF(L_SC_INIT,"Setting IFS to 0x%02X",size); 00419 if(SerWrite(buf,5)!=5) { 00420 PRINTF(L_SC_ERROR,"failed to write IFS command"); 00421 return false; 00422 } 00423 if(SerRead(buff,5,cardCfg.workTO)!=5 || XorSum(buff,5)) { 00424 PRINTF(L_SC_ERROR,"setting IFS to %02x failed",size); 00425 return false; 00426 } 00427 return true; 00428 } 00429 00430 bool cSmartCardNagra::GetCardStatus(void) 00431 { 00432 if(!DoBlkCmd(0xC0,0x02,0xB0,0x06) || !Status()) { 00433 PRINTF(L_SC_ERROR,"failed to read card status"); 00434 return false; 00435 } 00436 memcpy(state,buff+6,3); 00437 return true; 00438 } 00439 00440 bool cSmartCardNagra::CanHandle(unsigned short CaId) 00441 { 00442 return CaId==caid; 00443 } 00444 00445 bool cSmartCardNagra::Init(void) 00446 { 00447 block=0; isTiger=isT14Nagra=isN3=swapCW=false; 00448 caid=SYSTEM_NAGRA; 00449 ResetIdSet(); 00450 00451 static const unsigned char atrDNASP[] = { 'D','N','A','S','P' }; 00452 static const unsigned char atrTIGER[] = { 'T','I','G','E','R' }; 00453 static const unsigned char atrNCMED[] = { 'N','C','M','E','D' }; 00454 static const unsigned char atrIRDET[] = { 'I','R','D','E','T','O' }; 00455 if(!memcmp(atr->hist,atrDNASP,sizeof(atrDNASP))) { 00456 if(atr->hist[5]=='2' && atr->hist[6]=='4') isN3=true; 00457 PRINTF(L_SC_INIT,"detected native T1 nagra card (N%d Mode)",isN3?3:2); 00458 if(!SetIFS(0xFE)) return false; 00459 memcpy(rominfo,atr->hist,sizeof(rominfo)); 00460 } 00461 else if(!memcmp(atr->hist,atrTIGER,sizeof(atrTIGER)) || !memcmp(atr->hist,atrNCMED,sizeof(atrNCMED))) { 00462 PRINTF(L_SC_INIT,"detected nagra tiger card"); 00463 if(!SetIFS(0xFE)) return false; 00464 memcpy(rominfo,atr->hist,sizeof(rominfo)); 00465 cardId=0xFFFFFFFF; 00466 isTiger=true; 00467 } 00468 else if(!memcmp(atr->hist,atrIRDET,sizeof(atrIRDET))) { 00469 PRINTF(L_SC_INIT,"detected tunneled T14 nagra card"); 00470 if(!allowT14) { 00471 PRINTF(L_SC_INIT,"Nagra mode for T14 card disabled in setup"); 00472 return false; 00473 } 00474 PRINTF(L_SC_INIT,"using nagra mode"); 00475 isT14Nagra=true; 00476 if(!DoBlkCmd(0x10,0x02,0x90,0x11)) { 00477 PRINTF(L_SC_ERROR,"get rom version failed"); 00478 return false; 00479 } 00480 memcpy(rominfo,&buff[2],15); 00481 } 00482 else { 00483 PRINTF(L_SC_INIT,"doesn't look like a nagra card"); 00484 return false; 00485 } 00486 00487 infoStr.Begin(); 00488 infoStr.Strcat("Nagra smartcard\n"); 00489 char rom[12], rev[12]; 00490 snprintf(rom,sizeof(rom),"%c%c%c%c%c%c%c%c",rominfo[0],rominfo[1],rominfo[2],rominfo[3],rominfo[4],rominfo[5],rominfo[6],rominfo[7]); 00491 snprintf(rev,sizeof(rev),"%c%c%c%c%c%c",rominfo[9],rominfo[10],rominfo[11],rominfo[12],rominfo[13],rominfo[14]); 00492 PRINTF(L_SC_INIT,"rom version: %s revision: %s",rom,rev); 00493 infoStr.Printf("Rom %s Rev %s\n",rom,rev); 00494 00495 if(!isTiger) { 00496 GetCardStatus(); 00497 if(!DoBlkCmd(0x12,0x02,0x92,0x06) || !Status()) return false; 00498 cardId=UINT32_BE(buff+5); 00499 SetCard(new cCardNagra2(buff+5)); 00500 00501 if(!GetDataType(DT01,0x0E)) return false; 00502 GetCardStatus(); 00503 if(!GetDataType(IRDINFO,0x39)) return false; 00504 GetCardStatus(); 00505 if(!GetDataType(CAMDATA,0x55)) return false; 00506 GetCardStatus(); 00507 if(!GetDataType(DT04,0x44)) return false; 00508 GetCardStatus(); 00509 if(memcmp(rominfo+5,"181",3)!=0) { // not working on ROM181 00510 infoStr.Printf("Tiers\n"); 00511 infoStr.Printf("|id |chid| dates |\n"); 00512 infoStr.Printf("+----+----+---------------------+\n"); 00513 if(!GetDataType(TIERS,0x57)) return false; 00514 GetCardStatus(); 00515 } 00516 if(!GetDataType(DT06,0x16)) return false; 00517 GetCardStatus(); 00518 } 00519 00520 if(!HasCamMod()) { 00521 cSmartCardDataNagra cd(cardId,false); 00522 cSmartCardDataNagra *entry=(cSmartCardDataNagra *)smartcards.FindCardData(&cd); 00523 if(entry) { 00524 SetCardData(cardId,entry->bk,entry->exp); 00525 SetCamMod(entry->mod); 00526 } 00527 else { 00528 PRINTF(L_SC_ERROR,"can't find CARD modulus"); 00529 return false; 00530 } 00531 } 00532 if(!DoCamExchange()) return false; 00533 infoStr.Finish(); 00534 return true; 00535 } 00536 00537 bool cSmartCardNagra::DoCamExchange(void) 00538 { 00539 if(!isTiger) { 00540 // N3 cam session negotiation start 00541 if(isN3 && (!DoBlkCmd(0x29,0x02,0xA9,0x04) || !Status())) return false; 00542 00543 unsigned char ext[5]; 00544 BYTE4_BE(ext,irdId); ext[4]=0; // tuner 00545 if((!isN3 && !DoBlkCmd(0x2A,0x02,0xAA,0x42)) || 00546 ( isN3 && !DoBlkCmd(0x26,0x07,0xA6,0x42,ext)) || 00547 !Status()) return false; 00548 unsigned char res[64+5]; 00549 if(!MakeSessionKey(res,buff+5)) return false; 00550 memcpy(res+64,ext,5); 00551 cCondWait::SleepMs(500); 00552 if((!isN3 && !DoBlkCmd(0x2B,0x42,0xAB,0x02,res)) || 00553 ( isN3 && !DoBlkCmd(0x27,0x47,0xA7,0x02,res)) || 00554 !Status() || 00555 !GetCardStatus()) return false; 00556 if(SENDDATETIME()) 00557 SendDateTimeCmd(); 00558 if(RENEW_SESSIONKEY()) { 00559 PRINTF(L_SC_ERROR,"Session key negotiation failed!"); 00560 return false; 00561 } 00562 } 00563 else { 00564 static const unsigned char d1[] = { 0xd2 }; 00565 if(!DoBlkCmd(0xD1,0x03,0x51,0x42,d1) || !Status()) return false; 00566 00567 //XXX need implement Tiger session key handling (see oscam) 00568 return false; 00569 00570 unsigned char res[64]; 00571 if(!DoBlkCmd(0xD2,0x42,0x52,0x03,res) || !Status()) return false; 00572 } 00573 return true; 00574 } 00575 00576 bool cSmartCardNagra::SendDateTimeCmd(void) 00577 { 00578 DoBlkCmd(0xC8,0x02,0xB8,0x06); 00579 return true; 00580 } 00581 00582 void cSmartCardNagra::PostProcess(void) 00583 { 00584 if(!isTiger) { 00585 GetCardStatus(); 00586 cCondWait::SleepMs(10); 00587 if(RENEW_SESSIONKEY()) DoCamExchange(); 00588 if(SENDDATETIME()) SendDateTimeCmd(); 00589 } 00590 } 00591 00592 bool cSmartCardNagra::GetDataType(unsigned char dt, int len, int shots) 00593 { 00594 bool isdt8 = (dt==0x08); 00595 for(int i=0; i<shots; i++) { 00596 if(!DoBlkCmd(0x22,0x03,0xA2,len,&dt) || !Status()) { 00597 PRINTF(L_SC_ERROR,"failed to get datatype %02X",dt); 00598 return false; 00599 } 00600 if(buff[5]==0) break; 00601 if(!ParseDataType(dt&0x0F)) return false; 00602 if(isdt8 && buff[14]==0x49) break; 00603 dt|=0x80; // get next item 00604 } 00605 return true; 00606 } 00607 00608 bool cSmartCardNagra::ParseDataType(unsigned char dt) 00609 { 00610 switch(dt) { 00611 case IRDINFO: 00612 { 00613 provId=(buff[10]*256)|buff[11]; 00614 if(provId==0x0401 || provId==0x3411) swapCW=true; 00615 caid=SYSTEM_NAGRA+buff[14]; 00616 irdId=UINT32_BE(buff+17); 00617 PRINTF(L_SC_INIT,"CAID: %04x PROV: %04x CARD ID: %08x IRD ID: %08x",caid,provId,cardId,irdId); 00618 infoStr.Printf("CAID: %04x PROV: %04x\nCARD ID: %08x\nIRD ID: %08x\n",caid,provId,cardId,irdId); 00619 break; 00620 } 00621 case TIERS: 00622 { 00623 int chid=(buff[14]*256)|buff[15]; 00624 if(chid) { 00625 int id=(buff[10]*256)|buff[11]; 00626 char ds[16], de[16]; 00627 Date(buff+23,ds,sizeof(ds)); 00628 Date(buff+16,de,sizeof(de)); 00629 infoStr.Printf("|%04X|%04X|%s-%s|\n",id,chid,ds,de); 00630 PRINTF(L_SC_INIT,"|%04X|%04X|%s-%s|",id,chid,ds,de); 00631 } 00632 break; 00633 } 00634 case CAMDATA: 00635 if(buff[14]==0x49) { 00636 cSmartCardDataNagra cd(cardId,true); 00637 cSmartCardDataNagra *entry=(cSmartCardDataNagra *)smartcards.FindCardData(&cd); 00638 if(entry) { 00639 SetCardData(cardId,entry->bk,entry->exp); 00640 return DecryptDT08(buff+15,irdId,&entry->mod,swapCW); 00641 } 00642 else { 00643 PRINTF(L_SC_ERROR,"can't find IRD modulus"); 00644 return false; 00645 } 00646 } 00647 break; 00648 } 00649 return true; 00650 } 00651 00652 time_t cSmartCardNagra::Date(const unsigned char *data, char *buf, int len) 00653 { 00654 int day=((data[0]<<8)|data[1])-0x7f7; 00655 time_t ut=870393600L+day*(24*3600); 00656 if(buf) { 00657 struct tm rt; 00658 struct tm *t=gmtime_r(&ut,&rt); 00659 if(t) snprintf(buf,len,"%04d/%02d/%02d",t->tm_year+1900,t->tm_mon+1,t->tm_mday); 00660 else buf[0]=0; 00661 } 00662 return ut; 00663 } 00664 00665 bool cSmartCardNagra::Decode(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw) 00666 { 00667 if(!isTiger) { 00668 unsigned char pkt[256+16]; 00669 memset(pkt,0,sizeof(pkt)); 00670 memcpy(pkt,data+3+2,data[4]); 00671 for(int i=1; i>=0; i--) { 00672 if(((!isN3 && DoBlkCmd(data[3],data[4]+2,0x87,0x02,pkt)) || 00673 ( isN3 && DoBlkCmd(data[3]+1,data[4]+5+2,0x88,0x04,pkt))) && 00674 Status()) 00675 break; 00676 PRINTF(L_SC_ERROR,"ECM cmd failed%s",(i>0)?", retrying":""); 00677 if(i==0) return false; 00678 } 00679 cCondWait::SleepMs(10); 00680 for(int retry=0; !GetCardStatus() && retry<5; retry++) cCondWait::SleepMs(5); 00681 cCondWait::SleepMs(10); 00682 if(HAS_CW() && DoBlkCmd(0x1C,0x02,0x9C,0x36) && Status()) { 00683 DecryptCW(cw,buff+33,buff+7); 00684 PostProcess(); 00685 if(swapCW) { 00686 unsigned char tt[8]; 00687 memcpy(&tt[0],&cw[0],8); 00688 memcpy(&cw[0],&cw[8],8); 00689 memcpy(&cw[8],&tt[0],8); 00690 } 00691 return true; 00692 } 00693 } 00694 else { 00695 // ecm_data: 80 30 89 D3 87 54 11 10 DA A6 0F 4B 92 05 34 00 ... 00696 //serial_data: A0 CA 00 00 8C D3 8A 00 00 00 00 00 10 DA A6 0F . 00697 unsigned char ecm_trim[150]; 00698 memset(ecm_trim,0,150); 00699 memcpy(&ecm_trim[5],data+3+2+2,data[4]+2); 00700 if(DoBlkCmd(data[3],data[4]+5,0x53,0x16,ecm_trim) && Status()) { 00701 DecryptCW(cw,buff+17,buff+9); 00702 PostProcess(); 00703 return true; 00704 } 00705 } 00706 return false; 00707 } 00708 00709 bool cSmartCardNagra::Update(int pid, int caid, const unsigned char *data) 00710 { 00711 if(MatchEMM(data)) { 00712 if(DoBlkCmd(data[8],data[9]+2,0x84,0x02,data+8+2) && Status()) { 00713 cCondWait::SleepMs(300); 00714 PostProcess(); 00715 } 00716 return true; 00717 } 00718 return false; 00719 } 00720 00721 bool cSmartCardNagra::DoBlkCmd(unsigned char cmd, int ilen, unsigned char res, int rlen, const unsigned char *data) 00722 { 00723 /* 00724 here we build the command related to the protocol T1 for ROM142 or T14 for ROM181 00725 the only different that i know is the command length byte msg[4], this msg[4]+=1 by a ROM181 smartcard (_nighti_) 00726 one example for the cmd$C0 00727 T14 protocol: 01 A0 CA 00 00 03 C0 00 06 91 00728 T1 protocol: 21 00 08 A0 CA 00 00 02 C0 00 06 87 00729 */ 00730 unsigned char msg[MAX_LEN+16]; 00731 static char nagra_head[] = { 0xA0,0xCA,0x00,0x00 }; 00732 00733 memset(msg,0,sizeof(msg)); 00734 int c=0; 00735 if(!isT14Nagra) { 00736 msg[c++]=0x21; 00737 msg[c++]=block; block^=0x40; 00738 msg[c++]=ilen+6; 00739 } 00740 else { 00741 msg[c++]=0x01; 00742 } 00743 memcpy(msg+c,nagra_head,sizeof(nagra_head)); c+=sizeof(nagra_head); 00744 msg[c]=ilen; 00745 msg[c+1]=cmd; 00746 int dlen=ilen-2; 00747 if(dlen<0) { 00748 PRINTF(L_SC_ERROR,"invalid data length encountered"); 00749 return false; 00750 } 00751 msg[c+2]=dlen; 00752 if(isT14Nagra) msg[c]++; 00753 c+=3; 00754 if(data && dlen>0) { memcpy(msg+c,data,dlen); c+=dlen; } 00755 msg[c++]=rlen; 00756 msg[c]=XorSum(msg,c); c++; 00757 00758 if(SerWrite(msg,c)==c) { 00759 LDUMP(L_CORE_SC,msg,c,"NAGRA: <-"); 00760 cCondWait::SleepMs(10); 00761 if(SerRead(buff,3,cardCfg.workTO)!=3) { 00762 PRINTF(L_SC_ERROR,"reading back reply failed"); 00763 return false; 00764 } 00765 int xlen=buff[2]+1; 00766 if(SerRead(buff+3,xlen,cardCfg.workTO)!=xlen) { 00767 PRINTF(L_SC_ERROR,"reading back information block failed"); 00768 return false; 00769 } 00770 xlen+=3; 00771 if(XorSum(buff,xlen)) { 00772 PRINTF(L_SC_ERROR,"checksum failed"); 00773 return false; 00774 } 00775 LDUMP(L_CORE_SC,buff,xlen,"NAGRA: ->"); 00776 00777 if(buff[3]!=res) { 00778 PRINTF(L_SC_ERROR,"result not expected (%02X != %02X)",buff[3],res); 00779 return false; 00780 } 00781 if(buff[2]-2!=rlen) { 00782 PRINTF(L_SC_ERROR,"result length not expected (%d != %d)",buff[2]-2,rlen); 00783 return false; 00784 } 00785 memcpy(sb,&buff[3+rlen],2); 00786 LDUMP(L_CORE_SC,sb,2,"NAGRA: ->"); 00787 cCondWait::SleepMs(10); 00788 return true; 00789 } 00790 return false; 00791 } 00792 00793 // -- cSmartCardLinkNagra ------------------------------------------------------------- 00794 00795 class cSmartCardLinkNagra : public cSmartCardLink { 00796 public: 00797 cSmartCardLinkNagra(void):cSmartCardLink(SC_NAME,SC_ID) {} 00798 virtual cSmartCard *Create(void) { return new cSmartCardNagra(); } 00799 virtual cSmartCardData *CreateData(void) { return new cSmartCardDataNagra; } 00800 }; 00801 00802 static cSmartCardLinkNagra staticScInit;