|
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 #include <ctype.h> 00023 00024 #include "system-common.h" 00025 #include "smartcard.h" 00026 #include "data.h" 00027 #include "parse.h" 00028 #include "crypto.h" 00029 #include "opts.h" 00030 #include "misc.h" 00031 #include "log-sc.h" 00032 #include "log-core.h" 00033 #include "version.h" 00034 00035 SCAPIVERSTAG(); 00036 00037 #define SYSTEM_NAME "SC-Cryptoworks" 00038 #define SYSTEM_PRI -5 00039 00040 #define SC_NAME "Cryptoworks" 00041 #define SC_ID MAKE_SC_ID('C','r','W','o') 00042 00043 #define L_SC 10 00044 #define L_SC_EXTRA LCLASS(L_SC,L_SC_LASTDEF<<1) 00045 #define L_SC_ALL LALL(L_SC_EXTRA) 00046 00047 static const struct LogModule lm_sc = { 00048 (LMOD_ENABLE|L_SC_ALL)&LOPT_MASK, 00049 (LMOD_ENABLE|L_SC_DEFDEF)&LOPT_MASK, 00050 "sc-cryptoworks", 00051 { L_SC_DEFNAMES,"extra" } 00052 }; 00053 ADD_MODULE(L_SC,lm_sc) 00054 00055 static int disableParental=0; 00056 00057 // -- cSystemScCryptoworks --------------------------------------------------------------- 00058 00059 class cSystemScCryptoworks : public cSystemScCore { 00060 public: 00061 cSystemScCryptoworks(void); 00062 }; 00063 00064 cSystemScCryptoworks::cSystemScCryptoworks(void) 00065 :cSystemScCore(SYSTEM_NAME,SYSTEM_PRI,SC_ID,"SC Cryptoworks") 00066 { 00067 hasLogger=true; 00068 } 00069 00070 // -- cSystemLinkScCryptoworks -------------------------------------------------------- 00071 00072 class cSystemLinkScCryptoworks : public cSystemLink { 00073 public: 00074 cSystemLinkScCryptoworks(void); 00075 virtual bool CanHandle(unsigned short SysId); 00076 virtual cSystem *Create(void) { return new cSystemScCryptoworks; } 00077 }; 00078 00079 static cSystemLinkScCryptoworks staticInit; 00080 00081 cSystemLinkScCryptoworks::cSystemLinkScCryptoworks(void) 00082 :cSystemLink(SYSTEM_NAME,SYSTEM_PRI) 00083 { 00084 static const char *rat[] = { 00085 trNOOP("don't touch"), 00086 trNOOP("disable") 00087 }; 00088 00089 opts=new cOpts(SYSTEM_NAME,1); 00090 opts->Add(new cOptSel("DisableParental",trNOOP("SC-Cryptoworks: Parental rating"),&disableParental,sizeof(rat)/sizeof(char *),rat)); 00091 Feature.NeedsSmartCard(); 00092 } 00093 00094 bool cSystemLinkScCryptoworks::CanHandle(unsigned short SysId) 00095 { 00096 bool res=false; 00097 cSmartCard *card=smartcards.LockCard(SC_ID); 00098 if(card) { 00099 res=card->CanHandle(SysId); 00100 smartcards.ReleaseCard(card); 00101 } 00102 return res; 00103 } 00104 00105 // -- cSmartCardDataCryptoworks ----------------------------------------------------- 00106 00107 enum eDataType { dtIPK, dtUCPK, dtPIN }; 00108 00109 class cSmartCardDataCryptoworks : public cSmartCardData { 00110 private: 00111 int IdLen(void) const { return type==dtIPK ? 2:5; } 00112 public: 00113 eDataType type; 00114 unsigned char id[5], pin[4]; 00115 cBN key; 00116 // 00117 cSmartCardDataCryptoworks(void); 00118 cSmartCardDataCryptoworks(eDataType Type, unsigned char *Id); 00119 virtual bool Parse(const char *line); 00120 virtual bool Matches(cSmartCardData *param); 00121 }; 00122 00123 cSmartCardDataCryptoworks::cSmartCardDataCryptoworks(void) 00124 :cSmartCardData(SC_ID) 00125 {} 00126 00127 cSmartCardDataCryptoworks::cSmartCardDataCryptoworks(eDataType Type, unsigned char *Id) 00128 :cSmartCardData(SC_ID) 00129 { 00130 type=Type; 00131 memset(id,0,sizeof(id)); 00132 memcpy(id,Id,IdLen()); 00133 } 00134 00135 bool cSmartCardDataCryptoworks::Matches(cSmartCardData *param) 00136 { 00137 cSmartCardDataCryptoworks *cd=(cSmartCardDataCryptoworks *)param; 00138 return cd->type==type && !memcmp(cd->id,id,IdLen()); 00139 } 00140 00141 bool cSmartCardDataCryptoworks::Parse(const char *line) 00142 { 00143 line=skipspace(line); 00144 if(!strncasecmp(line,"IPK",3)) { type=dtIPK; line+=3; } 00145 else if(!strncasecmp(line,"UCPK",4)) { type=dtUCPK; line+=4; } 00146 else if(!strncasecmp(line,"PIN",3)) { type=dtPIN; line+=3; } 00147 else { 00148 PRINTF(L_CORE_LOAD,"smartcarddatacryptoworks: format error: datatype"); 00149 return false; 00150 } 00151 line=skipspace(line); 00152 if(GetHex(line,id,IdLen())!=IdLen()) { 00153 PRINTF(L_CORE_LOAD,"smartcarddatacryptoworks: format error: caid/serial"); 00154 return false; 00155 } 00156 line=skipspace(line); 00157 if(type==dtPIN) { 00158 for(int i=0; i<4; i++) { 00159 if(!isdigit(*line)) { 00160 PRINTF(L_CORE_LOAD,"smartcarddatacryptoworks: format error: pin"); 00161 return false; 00162 } 00163 pin[i]=*line++; 00164 } 00165 } 00166 else { 00167 unsigned char buff[64]; 00168 if(GetHex(line,buff,64,true)!=64) { 00169 PRINTF(L_CORE_LOAD,"smartcarddatacryptoworks: format error: ipk/ucpk"); 00170 return false; 00171 } 00172 BN_bin2bn(buff,64,key); 00173 } 00174 return true; 00175 } 00176 00177 // -- cSmartCardCryptoworks ----------------------------------------------------------- 00178 00179 class cSmartCardCryptoworks : public cSmartCard, public cIdSet { 00180 private: 00181 int caid; 00182 cRSA rsa; 00183 cBN ucpk, exp; 00184 bool ucpkValid; 00185 // 00186 int GetLen(void); 00187 bool EndOfData(void); 00188 bool SelectFile(int file); 00189 int ReadRecord(unsigned char *buff, int num); 00190 int ReadData(unsigned char *buff, int len); 00191 public: 00192 cSmartCardCryptoworks(void); 00193 virtual bool Init(void); 00194 virtual bool Decode(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw); 00195 virtual bool Update(int pid, int caid, const unsigned char *data); 00196 virtual bool CanHandle(unsigned short CaId); 00197 }; 00198 00199 static const struct StatusMsg msgs[] = { 00200 { { 0x90,0x00 }, "Instruction executed without errors", true }, 00201 { { 0x92,0x40 }, "Memory problem", false }, 00202 { { 0x94,0x02 }, "Out of range", false }, 00203 { { 0x94,0x04 }, "File not found", false }, 00204 { { 0x98,0x04 }, "Verification failed (wrong PIN)", false }, 00205 { { 0x98,0x05 }, "Wrong signature", false }, 00206 { { 0x98,0x40 }, "Verification failed, card blocked (deblocking by uplink required)", false }, 00207 { { 0x9F,0xFF }, "Instruction accepted, data to be read", true }, 00208 { { 0xFF,0xFF }, 0, false } 00209 }; 00210 00211 static const struct CardConfig cardCfg = { 00212 SM_8E2,1000,100 00213 }; 00214 00215 struct chid_dat { 00216 unsigned int chid, version; 00217 unsigned char id, status; 00218 char from[16], to[16], name[16]; 00219 }; 00220 00221 cSmartCardCryptoworks::cSmartCardCryptoworks(void) 00222 :cSmartCard(&cardCfg,msgs) 00223 { 00224 static const unsigned char cwexp[] = { 0x01,0x00,0x01 }; 00225 BN_bin2bn(cwexp,sizeof(cwexp),exp); 00226 caid=0; ucpkValid=false; 00227 } 00228 00229 int cSmartCardCryptoworks::GetLen(void) 00230 { 00231 return (sb[0]==0x9F) ? sb[1] : -1; 00232 } 00233 00234 bool cSmartCardCryptoworks::EndOfData(void) 00235 { 00236 return sb[0]==0x94 && sb[1]==0x02; 00237 } 00238 00239 bool cSmartCardCryptoworks::SelectFile(int file) 00240 { 00241 static unsigned char insa4[] = { 0xA4,0xA4,0x00,0x00,0x02,0x00,0x00 }; 00242 insa4[5]=file>>8; 00243 insa4[6]=file&0xFF; 00244 return IsoWrite(insa4,&insa4[5]) && Status(); 00245 } 00246 00247 int cSmartCardCryptoworks::ReadRecord(unsigned char *buff, int num) 00248 { 00249 static unsigned char insa2[] = { 0xA4,0xA2,0x00,0x00,0x01,0x00 }; 00250 static unsigned char insb2[] = { 0xA4,0xB2,0x00,0x00,0x00 }; 00251 insa2[5]=num; 00252 if(IsoWrite(insa2,&insa2[5]) && Status() && (num=GetLen())>0) { 00253 insb2[4]=num; 00254 if(IsoRead(insb2,buff) && Status()) return num; 00255 } 00256 return -1; 00257 } 00258 00259 int cSmartCardCryptoworks::ReadData(unsigned char *buff, int len) 00260 { 00261 static unsigned char insc0[] = { 0xA4,0xC0,0x00,0x00,0x00 }; 00262 insc0[4]=len; 00263 if(IsoRead(insc0,buff) && Status()) return len; 00264 return -1; 00265 } 00266 00267 bool cSmartCardCryptoworks::Init(void) 00268 { 00269 if(atr->histLen<6 || atr->hist[1]!=0xC4 || atr->hist[4]!=0x8F || atr->hist[5]!=0xF1) { 00270 PRINTF(L_SC_INIT,"doesn't look like a Cryptoworks card"); 00271 return false; 00272 } 00273 infoStr.Begin(); 00274 infoStr.Strcat("Cryptoworks smartcard\n"); 00275 ucpkValid=false; 00276 unsigned char buff[MAX_LEN]; 00277 int mfid=0x3F20; 00278 if(ReadData(buff,0x11)>0 && buff[0]==0xDF && buff[1]>=6) 00279 mfid=buff[6]*256+buff[7]; 00280 else PRINTF(L_SC_ERROR,"reading MF-ID failed, using default 3F20"); 00281 00282 unsigned char Caid[2], serial[5]; 00283 if(!SelectFile(0x2F01) || ReadRecord(buff,0xD1)<4) { 00284 PRINTF(L_SC_ERROR,"reading record 2f01/d1 failed"); 00285 return false; 00286 } 00287 memcpy(Caid,&buff[2],2); 00288 int c=buff[2]*256+buff[3]; 00289 if(c!=caid) CaidsChanged(); 00290 caid=c; 00291 if(ReadRecord(buff,0x80)<7) { 00292 PRINTF(L_SC_ERROR,"reading record 2f01/80 failed"); 00293 return false; 00294 } 00295 SetCard(new cCardCryptoworks(&buff[2])); 00296 memcpy(serial,&buff[2],5); 00297 snprintf(idStr,sizeof(idStr),"%s (V.%d)",SC_NAME,atr->hist[2]); 00298 char str[20]; 00299 infoStr.Printf("Card v.%d (PINcount=%d)\n" 00300 "Caid %04x Serial %s\n", 00301 atr->hist[2],atr->hist[3],caid,HexStr(str,&buff[2],5)); 00302 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); 00303 if(ReadRecord(buff,0x9F)>=3) { 00304 const char *n="(unknown)"; 00305 if(ReadRecord(buff+10,0xC0)>=18) n=(char *)buff+10+2; 00306 infoStr.Printf("Issuer: 0x%02x (%.16s)\n",buff[2],n); 00307 PRINTF(L_SC_INIT,"card issuer: 0x%02x %.16s",buff[2],n); 00308 } 00309 if(ReadRecord(buff,0x9E)>=66) { 00310 HEXDUMP(L_SC_EXTRA,&buff[2],64,"card ISK"); 00311 cSmartCardDataCryptoworks cd(dtIPK,Caid); 00312 cSmartCardDataCryptoworks *entry=(cSmartCardDataCryptoworks *)smartcards.FindCardData(&cd); 00313 if(entry) { 00314 PRINTF(L_SC_EXTRA,"got IPK from smartcard.conf"); 00315 if(rsa.RSA(&buff[2],&buff[2],64,exp,entry->key,false)>0) { 00316 HEXDUMP(L_SC_EXTRA,&buff[2],64,"decrypted ISK"); 00317 if(buff[2] == ((mfid&0xFF)>>1)) { 00318 buff[2]|=0x80; 00319 BN_bin2bn(&buff[2],64,ucpk); 00320 ucpkValid=true; 00321 PRINTF(L_SC_INIT,"got UCPK from IPK/ISK"); 00322 } 00323 else PRINTF(L_SC_ERROR,"UCPK check failed %02x != %02x",buff[2],(mfid&0xFF)>>1); 00324 } 00325 else PRINTF(L_SC_ERROR,"RSA failed for UCPK"); 00326 } 00327 } 00328 if(!ucpkValid) { 00329 cSmartCardDataCryptoworks cd(dtUCPK,serial); 00330 cSmartCardDataCryptoworks *entry=(cSmartCardDataCryptoworks *)smartcards.FindCardData(&cd); 00331 if(entry) { 00332 BN_copy(ucpk,entry->key); 00333 ucpkValid=true; 00334 PRINTF(L_SC_INIT,"got UCPK from smartcard.conf"); 00335 } 00336 } 00337 if(!ucpkValid) PRINTF(L_GEN_WARN,"no valid UCPK for cryptoworks smartcard"); 00338 00339 // read entitlements 00340 static unsigned char insb8[] = { 0xA4,0xB8,0x00,0x00,0x0C }; 00341 unsigned char provId[16]; 00342 unsigned int count=0; 00343 insb8[2]=insb8[3]=0x00; 00344 while(IsoRead(insb8,buff) && !EndOfData() && Status()) { 00345 if(buff[0]==0xDF && buff[1]==0x0A) { 00346 int fileno=(buff[4]&0x3F)*256+buff[5]; 00347 if((fileno&0xFF00)==0x1F00) { 00348 provId[count++]=fileno&0xFF; 00349 if(count>=sizeof(provId)) break; 00350 } 00351 } 00352 insb8[2]=insb8[3]=0xFF; 00353 } 00354 for(unsigned int i=0; i<count ; i++) { 00355 if(SelectFile(0x1F00+provId[i])) { 00356 const char *n="(unknown)"; 00357 if(SelectFile(0x0E11) && ReadRecord(buff,0xD6)>=18) n=(char *)buff+2; 00358 infoStr.Printf("Provider %d: 0x%02x (%.16s)\n",i,provId[i],n); 00359 PRINTF(L_SC_INIT,"provider %d: 0x%02x %.16s",i,provId[i],n); 00360 static unsigned char insa2_0[] = { 0xA4,0xA2,0x01,0x00,0x03,0x83,0x01,0x00 }; 00361 static unsigned char insa2_1[] = { 0xA4,0xA2,0x01,0x00,0x05,0x8C,0x00,0x00,0x00,0x00 }; 00362 static unsigned char insb2[] = { 0xA4,0xB2,0x00,0x00,0x00 }; 00363 static const unsigned int fn[] = { 0x0f00,0x0f20,0x0f40,0x0f60,0 }; 00364 static const char *fnName[] = { "Download","Subscriptions","PPV Events","PPV Events",0 }; 00365 bool first=true; 00366 for(int j=0; fn[j]; j++) { 00367 if(SelectFile(fn[j])) { 00368 insa2_0[7]=provId[i]; 00369 unsigned char *ins=(j==1) ? insa2_1 : insa2_0; 00370 int l; 00371 if(IsoWrite(ins,&ins[5]) && Status() && (l=GetLen())>0) { 00372 if(first) { 00373 infoStr.Printf("id|chid|st|date |name\n"); 00374 PRINTF(L_SC_INIT,"| id | chid | stat | date | version | name "); 00375 first=false; 00376 } 00377 infoStr.Printf( "--+----+--+-----------------+------\n" 00378 "%s\n", 00379 fnName[j]); 00380 PRINTF(L_SC_INIT,"+----+------+------+-------------------+----------+-------------"); 00381 PRINTF(L_SC_INIT,"| %s",fnName[j]); 00382 insb2[3]=0x00; 00383 insb2[4]=l; 00384 while(IsoRead(insb2,buff) && !EndOfData() && Status()) { 00385 struct chid_dat chid; 00386 memset(&chid,0,sizeof(chid)); 00387 for(int k=0; k<l; k+=buff[k+1]+2) { 00388 switch(buff[k]) { 00389 case 0x83: 00390 chid.id=buff[k+2]; 00391 break; 00392 case 0x8c: 00393 chid.status=buff[k+2]; 00394 chid.chid=buff[k+3]*256+buff[k+4]; 00395 break; 00396 case 0x8D: 00397 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); 00398 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); 00399 break; 00400 case 0xD5: 00401 snprintf(chid.name,sizeof(chid.name),"%.12s",&buff[k+2]); 00402 chid.version=Bin2Int(&buff[k+14],4); 00403 break; 00404 } 00405 } 00406 infoStr.Printf("%02x|%04x|%02x|%s-%s|%.12s\n", 00407 chid.id,chid.chid,chid.status,chid.from,chid.to,chid.name); 00408 PRINTF(L_SC_INIT,"| %02x | %04x | %02x | %s-%s | %08x | %.12s", 00409 chid.id,chid.chid,chid.status,chid.from,chid.to,chid.version,chid.name); 00410 insb2[3]=0x01; 00411 } 00412 } 00413 } 00414 } 00415 } 00416 } 00417 00418 if(disableParental) { 00419 bool pinOK=false; 00420 if(SelectFile(0x2F11) && ReadRecord(buff,atr->hist[3])>=7) { 00421 pinOK=true; 00422 PRINTF(L_SC_INIT,"read PIN from card."); 00423 } 00424 if(!pinOK) { 00425 cSmartCardDataCryptoworks cd(dtPIN,serial); 00426 cSmartCardDataCryptoworks *entry=(cSmartCardDataCryptoworks *)smartcards.FindCardData(&cd); 00427 if(entry) { 00428 memcpy(&buff[2],entry->pin,4); 00429 pinOK=true; 00430 PRINTF(L_SC_INIT,"got PIN from smartcard.conf."); 00431 } 00432 } 00433 if(pinOK) { 00434 //static const unsigned char ins[] = { 0xA4,0x24,0x00,0x01,0x05 }; 00435 static const unsigned char ins[] = { 0xA4,0x20,0x00,0x00,0x04 }; // verify PIN 00436 //static const unsigned char ins[] = { 0xA4,0x26,0x00,0x00,0x04 }; // disable PIN 00437 PRINTF(L_SC_INIT,"your card PIN is %.4s",&buff[2]); 00438 // parental rating 00439 // 0x00 - undefined 00440 // 0x01-0x0f - minimum age=rating+3 years 00441 // 0x10-0xff - reserved for provider usage 00442 buff[6]=0; 00443 if(IsoWrite(ins,&buff[2]) && Status()) 00444 PRINTF(L_SC_INIT,"parental rating set to %02x",buff[6]); 00445 else 00446 PRINTF(L_SC_ERROR,"failed to set parental rating."); 00447 } 00448 else PRINTF(L_SC_INIT,"no PIN available."); 00449 } 00450 00451 infoStr.Finish(); 00452 return true; 00453 } 00454 00455 bool cSmartCardCryptoworks::CanHandle(unsigned short CaId) 00456 { 00457 return CaId==caid; 00458 } 00459 00460 bool cSmartCardCryptoworks::Decode(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw) 00461 { 00462 static unsigned char ins4c[] = { 0xA4,0x4C,0x00,0x00,0x00 }; 00463 00464 unsigned char nanoD4[10]; 00465 int l=CheckSctLen(data,-5+(ucpkValid ? sizeof(nanoD4):0)); 00466 if(l>5) { 00467 unsigned char buff[MAX_LEN]; 00468 if(ucpkValid) { 00469 memcpy(buff,data,l); 00470 nanoD4[0]=0xD4; 00471 nanoD4[1]=0x08; 00472 for(unsigned int i=2; i<sizeof(nanoD4); i++) nanoD4[i]=rand(); 00473 memcpy(&buff[l],nanoD4,sizeof(nanoD4)); 00474 data=buff; l+=sizeof(nanoD4); 00475 } 00476 ins4c[3]=ucpkValid ? 2 : 0; 00477 ins4c[4]=l-5; 00478 if(IsoWrite(ins4c,&data[5]) && Status() && 00479 (l=GetLen())>0 && ReadData(buff,l)==l) { 00480 int r=0; 00481 for(int i=0; i<l && r<2; ) { 00482 int n=buff[i+1]; 00483 switch(buff[i]) { 00484 case 0xDB: // CW 00485 PRINTF(L_SC_EXTRA,"nano DB (cw)"); 00486 if(n==0x10) { 00487 memcpy(cw,&buff[i+2],16); 00488 r|=1; 00489 } 00490 break; 00491 case 0xDF: // signature 00492 PRINTF(L_SC_EXTRA,"nano DF %02x (sig)",n); 00493 if(n==0x08) { 00494 if((buff[i+2]&0x50)==0x50) { 00495 if(buff[i+3]&0x01) PRINTF(L_SC_ERROR,"not decyphered. PIN protected?"); 00496 else if(!(buff[i+5]&0x80)) PRINTF(L_SC_ERROR,"missing entitlement. Check your subscription"); 00497 else r|=2; 00498 } 00499 } 00500 else if(n==0x40) { // camcrypt 00501 if(ucpkValid) { 00502 if(rsa.RSA(&buff[i+2],&buff[i+2],n,exp,ucpk,false)<=0) { 00503 PRINTF(L_SC_ERROR,"camcrypt RSA failed."); 00504 return false; 00505 } 00506 HEXDUMP(L_SC_EXTRA,&buff[i+2],n,"after camcrypt"); 00507 if(!memmem(&buff[i+2+4],n-4,nanoD4,sizeof(nanoD4))) { 00508 PRINTF(L_SC_ERROR,"camcrypt failed. Check IPK/UCPK in your smartcard.conf!"); 00509 return false; 00510 } 00511 r=0; l=n-4; n=4; 00512 } 00513 else { 00514 PRINTF(L_SC_ERROR,"valid UCPK needed for camcrypt! Check your smartcard.conf for a IPK/UCPK!"); 00515 return false; 00516 } 00517 } 00518 break; 00519 default: 00520 PRINTF(L_SC_EXTRA,"nano %02x (unhandled)",buff[i]); 00521 break; 00522 } 00523 i+=n+2; 00524 } 00525 return r==3; 00526 } 00527 } 00528 return false; 00529 } 00530 00531 bool cSmartCardCryptoworks::Update(int pid, int caid, const unsigned char *data) 00532 { 00533 static unsigned char ins[] = { 0xA4,0x42,0x00,0x00,0x00 }; 00534 00535 cAssembleData ad(data); 00536 if(MatchAndAssemble(&ad,0,0)) { 00537 while((data=ad.Assembled())) { 00538 int c, n; 00539 switch(data[0]) { 00540 case 0x82: c=0x42; n=10; break; 00541 case 0x84: c=0x48; n=9; break; 00542 case 0x88: 00543 case 0x89: c=0x44; n=5; break; 00544 default: continue; 00545 } 00546 00547 int len=CheckSctLen(data,-n); 00548 if(len>n) { 00549 ins[1]=c; 00550 ins[4]=len-n; 00551 if(IsoWrite(ins,&data[n])) Status(); 00552 } 00553 } 00554 return true; 00555 } 00556 return false; 00557 } 00558 00559 // -- cSmartCardLinkCryptoworks ------------------------------------------------------- 00560 00561 class cSmartCardLinkCryptoworks : public cSmartCardLink { 00562 public: 00563 cSmartCardLinkCryptoworks(void):cSmartCardLink(SC_NAME,SC_ID) {} 00564 virtual cSmartCard *Create(void) { return new cSmartCardCryptoworks(); } 00565 virtual cSmartCardData *CreateData(void) { return new cSmartCardDataCryptoworks; } 00566 }; 00567 00568 static cSmartCardLinkCryptoworks staticScInit;