SASC-NG
DVBSoftCAM

sc-cryptoworks.c

Go to the documentation of this file.
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;
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines