SASC
DVBSoftCAM

cSmartCardViaccess Class Reference

Inheritance diagram for cSmartCardViaccess:

List of all members.

Public Member Functions

 cSmartCardViaccess (void)
virtual bool Init (void)
virtual bool Decode (const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw)
virtual bool Update (int pid, int caid, const unsigned char *data)
 cSmartCardViaccess (void)
virtual bool Init (void)
virtual bool Decode (const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw)
virtual bool Update (int pid, int caid, const unsigned char *data)

Detailed Description

Definition at line 201 of file sc-viaccess.c.


Constructor & Destructor Documentation

cSmartCardViaccess::cSmartCardViaccess ( void  )

Definition at line 227 of file sc-viaccess.c.

:cSmartCard(&cardCfg,msgs)
{
  memset(lastId,0,sizeof(lastId));
}
cSmartCardViaccess::cSmartCardViaccess ( void  )

Member Function Documentation

bool cSmartCardViaccess::Decode ( const cEcmInfo *  ecm,
const unsigned char *  data,
unsigned char *  cw 
) [virtual]

Implements cSmartCard.

Definition at line 386 of file sc-viaccess.c.

References AUTOMEM, data, cAES::Decrypt(), cProviders::FindProv(), cSmartCard::IsoRead(), cSmartCard::IsoWrite(), cParseViaccess::KeyNr(), L_SC_ERROR, MAX_LEN, cParseViaccess::PayloadStart(), PRINTF, cParseViaccess::ProvIdPtr(), SCT_LEN, start(), and cSmartCard::Status().

{
  static unsigned char ins88[] = { 0xca,0x88,0x00,0x00,0x00 }; // set ecm
  static unsigned char insf8[] = { 0xca,0xf8,0x00,0x00,0x00 }; // set geographic info 
  static unsigned char insc0[] = { 0xca,0xc0,0x00,0x00,0x12 }; // read dcw

  cProviderScViaccess *p=(cProviderScViaccess *)FindProv(data);
  if(p) {
    unsigned char keynr=cParseViaccess::KeyNr(data);
    if(CheckKey(p,keynr)) {
      if(!SetProvider(cParseViaccess::ProvIdPtr(data))) return false;

      const unsigned char *start=cParseViaccess::PayloadStart(data);
      bool hasD2=false;
      if(start[0]==0xD2) { // TPS alike, TNTSAT/TNTop
        start+=start[1]+2;
        hasD2=true;
        }
      start+=5;

      const unsigned char *DE04=0;
      if(start[0]==0xDE && start[1]==0x04) {
        DE04=start;
        start+=6;
        }
      const unsigned char *ecm88Data=start;
      int ecm88Len=SCT_LEN(data)-(start-data);
      int ecmf8Len=0;
      while(ecm88Len>0 && ecm88Data[0]<0xA0) {
        const int nanoLen=ecm88Data[1]+2;
        ecmf8Len+=nanoLen;
        ecm88Len-=nanoLen; ecm88Data+=nanoLen;
        }
      if(ecmf8Len) {
        insf8[3]=keynr;
        insf8[4]=ecmf8Len;
        if(!IsoWrite(insf8,start) || !Status()) return false;
        }

      ins88[2]=ecmf8Len?1:0;
      ins88[3]=keynr;
      ins88[4]=ecm88Len;
      if(DE04) {
        unsigned char *mem=AUTOMEM(ecm88Len+6);
        memcpy(mem,DE04,6);
        memcpy(mem+6,ecm88Data,ecm88Len);
        ins88[4]+=6;
        ecm88Data=mem;
        }
      if(!IsoWrite(ins88,ecm88Data) || !Status()) return false; // request dcw
      unsigned char buff[MAX_LEN];
      if(!IsoRead(insc0,buff) || !Status()) return false; // read dcw
      unsigned char cwbuff[16];
      int cwmask=0;
      switch(buff[0]) {
        case 0xe8: // even
          if(buff[1]==8) { memcpy(cwbuff,buff+2,8); cwmask=1; }
          break;
        case 0xe9: // odd
          if(buff[1]==8) { memcpy(cwbuff+8,buff+2,8); cwmask=2; }
          break;
        case 0xea: // complete
          if(buff[1]==16) { memcpy(cwbuff,buff+2,16); cwmask=3; }
          break;
        }
      if(cwmask) {
        if(hasD2 && !Decrypt(cwbuff,16))
          PRINTF(L_SC_ERROR,"no AES key for this card");
        if(cwmask&1) memcpy(cw,cwbuff,8);
        if(cwmask&2) memcpy(cw+8,cwbuff+8,8);
        return true;
        }
      }
    else PRINTF(L_SC_ERROR,"key not found on card");
    }
  else PRINTF(L_SC_ERROR,"provider not found on card");
  return false;
}
virtual bool cSmartCardViaccess::Decode ( const cEcmInfo *  ecm,
const unsigned char *  data,
unsigned char *  cw 
) [virtual]

Implements cSmartCard.

bool cSmartCardViaccess::Init ( void  ) [virtual]

Implements cSmartCard.

Definition at line 233 of file sc-viaccess.c.

References cProviders::AddProv(), cSmartCardDataViaccess::aes, cSmartCard::atr, cProviderScViaccess::availKeys, cInfoStr::Begin(), Bin2Int, Bin2LongLong(), disableParental, dtAES, dtPIN, cSmartCards::FindCardData(), cInfoStr::Finish(), Atr::hist, Atr::histLen, cSmartCard::idStr, cSmartCard::infoStr, cSmartCard::IsoRead(), cSmartCard::IsoWrite(), L_SC_ERROR, L_SC_INIT, MAX_LEN, cProviderScViaccess::name, cSmartCardDataViaccess::pin, cLineBuff::Printf(), PRINTF, cProviderViaccess::ProvId(), cIdSet::ResetIdSet(), SC_NAME, cIdSet::SetCard(), cAES::SetKey(), smartcards, cSmartCard::Status(), cLineBuff::Strcat(), and Atr::T.

{
  static const unsigned char verifyBytes[] = { 0x90,0x00 };
  if(atr->T!=0 || atr->histLen<7 || memcmp(&atr->hist[5],verifyBytes,sizeof(verifyBytes))) {
    PRINTF(L_SC_INIT,"doesn't look like a Viaccess card");
    return false;
    }

  infoStr.Begin();
  infoStr.Strcat("Viaccess smartcard\n");
  const char *ver=0;
  switch((atr->hist[3]<<8)|atr->hist[4]) {
    case 0x6268: ver="2.3"; break;
    case 0x6468:
    case 0x6668: ver="2.4"; break;
    case 0xa268: ver="2.5"; break;
    case 0xc168: ver="2.6"; break;
    default: ver="unknown"; break;
    }
      
  PRINTF(L_SC_INIT,"card v.%s",ver);
  snprintf(idStr,sizeof(idStr),"%s (V.%s)",SC_NAME,ver);

  static unsigned char insac[] = { 0xca, 0xac, 0x00, 0x00, 0x00 }; // select data
  static unsigned char insb8[] = { 0xca, 0xb8, 0x00, 0x00, 0x00 }; // read selected data
  static unsigned char insa4[] = { 0xca, 0xa4, 0x00, 0x00, 0x00 }; // select issuer
  static unsigned char insc0[] = { 0xca, 0xc0, 0x00, 0x00, 0x00 }; // read data item
  unsigned char buff[MAX_LEN];

  ResetIdSet();
  insac[2]=0xa4; // request unique id
  if(!IsoWrite(insac,buff) || !Status()) {
    PRINTF(L_SC_ERROR,"failed to request ua");
    return false;
    }
  insb8[4]=0x07; // read unique id
  if(!IsoRead(insb8,buff) || !Status() || buff[1]!=0x05) {
    PRINTF(L_SC_ERROR,"failed to read ua");
    return false;
    }
  memcpy(ua,&buff[2],sizeof(ua));
  SetCard(new cCardViaccess(ua));
  PRINTF(L_SC_INIT,"card UA: %llu",Bin2LongLong(ua,5));
  infoStr.Printf("Card v.%s UA %010llu\n",ver,Bin2LongLong(ua,5));

  insa4[2]=0x00; // select issuer 0
  if(!IsoWrite(insa4,buff) || !Status()) {
    PRINTF(L_SC_ERROR,"failed to select issuer 0");
    return false;
    }
  int issuer=0;
  do {
    insc0[4]=0x1a; // show provider properties
    if(!IsoRead(insc0,buff) || !Status()) {
      PRINTF(L_SC_ERROR,"failed to read prov properties");
      return false;
      }

    unsigned char buff2[MAX_LEN];
    insac[2]=0xa5; // request sa
    if(!IsoWrite(insac,buff2) || !Status()) {
      PRINTF(L_SC_ERROR,"failed to request sa");
      return false;
      }
    insb8[4]=0x06; // read sa
    if(!IsoRead(insb8,buff2) || !Status()) {
      PRINTF(L_SC_ERROR,"failed to read sa");
      return false;
      }
    if(issuer==0) memcpy(sa0,&buff[2],sizeof(sa0));
    cProviderScViaccess *p=new cProviderScViaccess(&buff[0],&buff2[2]);
    if(p) {
      AddProv(p);
      memcpy(p->availKeys,buff+10,sizeof(p->availKeys));

      insac[2]=0xa7; // request name
      if(!IsoWrite(insac,buff) || !Status()) {
        PRINTF(L_SC_ERROR,"failed to request prov name");
        return false;
        }
      insb8[4]=0x02; // read name nano + len
      if(!IsoRead(insb8,buff) || !Status()) {
        PRINTF(L_SC_ERROR,"failed to read prov name length");
        return false;
        }
      unsigned int nameLen=buff[1];
      if(nameLen>=sizeof(p->name)) {
        PRINTF(L_SC_ERROR,"provider name buffer overflow");
        nameLen=sizeof(p->name)-1;
        }
      insb8[4]=nameLen;
      if(!IsoRead(insb8,buff) || !Status()) {
        PRINTF(L_SC_ERROR,"failed to read prov name");
        return false;
        }
      memcpy(p->name,buff,nameLen); p->name[nameLen]=0;

      PRINTF(L_SC_INIT,"provider %06x (%s)",(int)p->ProvId(),p->name);
      infoStr.Printf("Prov %06x (%s) SA %08u\n",(int)p->ProvId(),p->name,Bin2Int(&buff2[2],4));
      }
    else PRINTF(L_SC_ERROR,"no memory for provider");

    insa4[2]=0x02; // next issuer
    if(!IsoWrite(insa4,buff) || !Status()) {
      PRINTF(L_SC_ERROR,"failed to select next issuer");
      return false;
      }
    issuer++;
    } while(GetSW1()==0x00);
  infoStr.Finish();

  if(disableParental) {
      static unsigned char ins24[] = { 0xca,0x24,0x02,0x00,0x09 };
      static unsigned char pindt[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F };
      cSmartCardDataViaccess cd(dtPIN,ua);
      cSmartCardDataViaccess *entry=(cSmartCardDataViaccess *)smartcards.FindCardData(&cd);
      if(entry) {
        PRINTF(L_SC_INIT,"got PIN from smartcard.conf.");
        memcpy(&pindt[0],entry->pin,8);
        if(!IsoWrite(ins24,pindt) || !Status())
          PRINTF(L_SC_ERROR,"failed to disable parental lock");
        }
      else PRINTF(L_SC_INIT,"no PIN available.");
    }
  cSmartCardDataViaccess cd(dtAES,ua);
  cSmartCardDataViaccess *entry=(cSmartCardDataViaccess *)smartcards.FindCardData(&cd);
  if(entry) {
    PRINTF(L_SC_INIT,"got AES key from smartcard.conf.");
    SetKey(entry->aes);
    }

  return true;
}
virtual bool cSmartCardViaccess::Init ( void  ) [virtual]

Implements cSmartCard.

bool cSmartCardViaccess::Update ( int  pid,
int  caid,
const unsigned char *  data 
) [virtual]

Reimplemented from cSmartCard.

Definition at line 465 of file sc-viaccess.c.

References cAssembleData::Assembled(), AUTOMEM, data, cSmartCard::IsoWrite(), cParseViaccess::KeyNrFromNano(), cIdSet::MatchAndAssemble(), MAX_LEN, cParseViaccess::NanoStart(), SCT_LEN, start(), and cSmartCard::Status().

{
  static unsigned char insf0[] = { 0xca,0xf0,0x00,0x00,0x00 };
  static unsigned char ins18[] = { 0xca,0x18,0x00,0x00,0x00 };
  static unsigned char insf4[] = { 0xca,0xf4,0x00,0x00,0x00 };
  static unsigned char ins1c[] = { 0xca,0x1c,0x01,0x00,0x00 };

  int updtype;
  cAssembleData ad(data);
  if(MatchAndAssemble(&ad,&updtype,0)) {
    while((data=ad.Assembled())) {
      const unsigned char *start=cParseViaccess::NanoStart(data);
      int nanolen=SCT_LEN(data)-(start-data);

      if(start && nanolen>=5) {
        const unsigned char *nano81=0, *nano91=0, *nano92=0, *nano9e=0, *nanof0=0;
        unsigned char *nanos18=AUTOMEM(nanolen+10);
        bool provOK=false;
        int len18=0, keynr=0;
        
        while(nanolen>0) {
          switch(start[0]) {
            case 0x90:
              if(SetProvider(&start[2])) {
                provOK=true;
                keynr=cParseViaccess::KeyNrFromNano(start);
                }
              break;
            case 0x9E: // ADF
              if(!nano91) { // not crypted
                unsigned char custwp=sa0[3];
                const unsigned char *afd=&start[2];
                if(!(afd[31-custwp/8] & (1<<(custwp&7)))) { // not for this card
                  provOK=false; nanolen=0; // skip, next assemble data
                  break;
                  }
                }
              nano9e=start;
              break;
            case 0x81: nano81=start; break;
            case 0x91: nano91=start; break;
            case 0x92: nano92=start; break;
            case 0xF0: nanof0=start; break;
            default:
              {
              int l=start[1]+2;
              memcpy(nanos18+len18,start,l);
              len18+=l;
              }
            }
          int l=start[1]+2;
          start+=l; nanolen-=l;
          }

        if(provOK && nanof0) {
          unsigned char buff[MAX_LEN*2];
          if(nano9e) {
            int l9e=nano9e[1]+2;
            if(!nano91) {
              insf0[3]=keynr;
              insf0[4]=l9e;
              if(!IsoWrite(insf0,nano9e) || !Status()) continue;
              }
            else {
              int l91=nano91[1]+2;
              insf4[3]=keynr;
              insf4[4]=l91+l9e;
              memcpy(buff,nano91,l91);
              memcpy(buff+l91,nano9e,l9e);
              if(!IsoWrite(insf4,buff) || !Status()) continue;
              }
            }
          if(!nano92) {
            int lf0=nanof0[1]+2;
            ins18[2]=updtype>0 ? updtype-1 : updtype;
            ins18[3]=keynr;
            ins18[4]=len18+lf0;
            memcpy(buff,nanos18,len18);
            memcpy(buff+len18,nanof0,lf0);
            if(IsoWrite(ins18,buff)) Status();
            }
          else if(nano81) {
            int l92=nano92[1]+2, l81=nano81[1]+2, lf0=nanof0[1]+2;
            ins1c[3]=keynr;
            ins1c[4]=l92+l81+lf0;
            memcpy(buff,nano92,l92);
            memcpy(buff+l92,nano81,l81);
            memcpy(buff+l92+l81,nanof0,lf0);
            if(IsoWrite(ins1c,buff)) Status();
            }
          }
        }
      }
    return true;
    }
  return false;
}
virtual bool cSmartCardViaccess::Update ( int  pid,
int  caid,
const unsigned char *  data 
) [virtual]

Reimplemented from cSmartCard.


The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines