⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smartcard.c

📁 这是一个LINUX环境的 VDR 插件源代码,可支持Irdeto, Seca, Viaccess, Nagra, Conax & Cryptoworks等CA系统的读卡、共享等操作。
💻 C
📖 第 1 页 / 共 3 页
字号:
  LBSTARTF(L_CORE_SC);  LBPUT("%d: <- PROC: ",id);  do {    do {      if(Read(&buff,1,cfg->workTO)<=0) return -1;      LBPUT("%02x ",buff);      } while(buff==0x60);    if((buff&0xF0)==0x60 || (buff&0xF0)==0x90) { // SW1/SW2      sb[0]=buff;      if(Read(&buff,1)<=0) return -1;      LBPUT("%02x",buff);      sb[1]=buff;      return 0;      }    else {      if((buff&0xFE)==(ins&0xFE)) r=restLen;      else if((~buff&0xFE)==(ins&0xFE)) r=1;      else {        LBPUT("cannot handle procedure %02x (ins=%02x)\n",buff,ins);        return -1;        }      if(r>restLen) {        LBPUT("data overrun r=%d restLen=%d\n",r,restLen);        return -1;        }      }    } while(r==0);  LBEND();  return r;}bool cSmartCard::IsoRead(const unsigned char *cmd, unsigned char *data){  if(atr->T==0) { // only for ISO complaint cards    LDUMP(L_CORE_SC,cmd,CMD_LEN,"%d: -> INS:",id);    if(Write(cmd,CMD_LEN)<0) return Test(false);    int tr=cmd[LEN_IDX] ? cmd[LEN_IDX] : 256;    int len=0;    while(1) {      int r=Procedure(cmd[INS_IDX],tr-len);      if(r<=0) return Test(r==0);      if(Read(data+len,r)<0) return Test(false);      LDUMP(L_CORE_SC,data+len,r,"%d: <- DATA:",id);      len+=r;      }    }  else PRINTF(L_CORE_SC,"%d: can't IsoRead() from incompatible card (T=%d)",id,atr->T);  return false;}bool cSmartCard::IsoWrite(const unsigned char *cmd, const unsigned char *data){  if(atr->T==0) { // only for ISO complaint cards    LDUMP(L_CORE_SC,cmd,CMD_LEN,"%d: -> INS:",id);    if(Write(cmd,CMD_LEN)<0) return Test(false);    int len=0;    while(1) {      int r=Procedure(cmd[INS_IDX],cmd[LEN_IDX]-len);      if(r<=0) return Test(r==0);      if(Write(data+len,r)<0) return Test(false);      LDUMP(L_CORE_SC,data+len,r,"%d: -> DATA:",id);      len+=r;      }    }  else PRINTF(L_CORE_SC,"%d: can't IsoWrite() to incompatible card (T=%d)",id,atr->T);  return false;}bool cSmartCard::Test(bool res){ if(!res) {   TriggerReset();   PRINTF(L_CORE_SC,"%d: reset triggered",id);   } return res;}bool cSmartCard::Status(void){  const struct StatusMsg *m=msg;  while(m->sb[0]!=0xFF) {    if(sb[0]==m->sb[0] && (m->sb[1]==0xFF || sb[1]==m->sb[1])) {      if(!m->retval) PRINTF(L_CORE_SC,"%d: %s (status: %02x %02x)",id,m->message,sb[0],sb[1]);      return m->retval;      }    m++;    }  PRINTF(L_CORE_SC,"%d: unknown (status: %02x %02x)",id,sb[0],sb[1]);  return false;}int cSmartCard::CheckSctLen(const unsigned char *data, int off){  int l=SCT_LEN(data);  if(l+off > MAX_LEN) {    PRINTF(L_CORE_SC,"section too long %d > %d",l,MAX_LEN-off);    l=-1;    }  return l;}// -- cSmartCardData -----------------------------------------------------------cSmartCardData::cSmartCardData(int Ident){  ident=Ident;}// -- cSmartCardLink -----------------------------------------------------------cSmartCardLink::cSmartCardLink(const char *Name, int Id){  name=Name; id=Id;  cSmartCards::Register(this);}// -- cSmartCards --------------------------------------------------------------cSmartCardLink *cSmartCards::first=0;cSmartCards smartcards;static const char *serModes[] = { 0,"8e2","8o2","8n2" };cSmartCards::cSmartCards(void):cThread("SmartcardWatcher"){  for(int i=0 ; i<MAX_PORTS ; i++) ports[i].Serial=0;  firstRun=true;}void cSmartCards::Register(cSmartCardLink *scl){  PRINTF(L_CORE_DYN,"registering %s smartcard (id %x)",scl->name,scl->id);  scl->next=first;  first=scl;}void cSmartCards::LaunchWatcher(void){  for(int i=0 ; i<MAX_PORTS ; i++)    if(ports[i].Serial) { Start(); return; }  firstRun=false;  PRINTF(L_GEN_WARN,"no smartcard interface defined!");}void cSmartCards::Shutdown(void){  Cancel(3);  mutex.Lock();  for(int i=0 ; i<MAX_PORTS ; i++) {    if(ports[i].Serial) {      delete ports[i].Card;      delete ports[i].Serial;      ports[i].Serial=0;      }    }  dataList.Clear();  mutex.Unlock();}bool cSmartCards::AddPort(const char *devName, bool invCD, bool invRST, int clock){  cMutexLock lock(&mutex);  for(int i=0 ; i<MAX_PORTS ; i++) {    if(!ports[i].Serial) {      cSerial *ser=new cSerial(devName,invCD,invRST);      if(ser && ser->Open()) {        ports[i].Card=0;        ports[i].CardId=0;        ports[i].UseCount=0;        ports[i].Dead=false;        ports[i].PortNum=i;        ports[i].Serial=ser;        ports[i].Clock=clock ? clock : ISO_FREQ;        PRINTF(L_CORE_LOAD,"smartcards: added serial port %s as port %d (%s CD, %s RESET, CLOCK %d)",                  devName,i,invCD?"inverse":"normal",invRST?"inverse":"normal",ports[i].Clock);        return true;        }      PRINTF(L_GEN_ERROR,"failed to open serial port %s",devName);      delete ser;      return false;      }    else if(!strcmp(ports[i].Serial->DeviceName(),devName)) {      PRINTF(L_GEN_ERROR,"duplicate serial port %s. Check your config!",devName);      return false;      }    }  PRINTF(L_GEN_ERROR,"only %d serial ports supported",MAX_PORTS);  return false;}void cSmartCards::LoadData(const char *cfgdir){  mutex.Lock();  dataList.Clear();  ConfRead("smartcard data",AddDirectory(cfgdir,DATAFILE));  mutex.Unlock();}bool cSmartCards::ParseLine(const char *line, bool fromCache){  char *r=index(line,':');  if(!r) return false;  for(cSmartCardLink *scl=first; scl; scl=scl->next) {    if(!strncasecmp(scl->name,line,r-line)) {      cSmartCardData *scd=scl->CreateData();      if(scd && scd->Parse(r+1)) {        dataList.Add(scd);        break;        }      else {        delete scd;        return false;        }      }    }  return true;}cSmartCardData *cSmartCards::FindCardData(cSmartCardData *param){  cMutexLock lock(&mutex);  for(cSmartCardData *cd=dataList.First(); cd; cd=dataList.Next(cd))    if(cd->ident==param->ident && cd->Matches(param))      return cd;  return 0;}bool cSmartCards::HaveCard(int id){  cMutexLock lock(&mutex);  while(Running() && firstRun) cond.Wait(mutex);  for(int i=0 ; i<MAX_PORTS ; i++)    if(ports[i].Serial && ports[i].CardId==id) return true;  return false;}cSmartCard *cSmartCards::LockCard(int id){  mutex.Lock();  while(Running() && firstRun) cond.Wait(mutex);  for(int i=0 ; i<MAX_PORTS ; i++) {    if(ports[i].Serial && ports[i].CardId==id) {      ports[i].UseCount++;      mutex.Unlock();      cSmartCard *sc=ports[i].Card;      sc->Lock();      if(CardInserted(ports[i].Serial) && sc->CardUp() && !sc->NeedsReset())        return sc;      // if failed, unlock the card and decrement UseCount      sc->Unlock();      mutex.Lock();      ports[i].UseCount--;      cond.Broadcast();      break;      }    }  mutex.Unlock();  return 0;}void cSmartCards::ReleaseCard(cSmartCard *sc){  sc->Unlock();  mutex.Lock();  for(int i=0 ; i<MAX_PORTS ; i++) {    if(ports[i].Card==sc) {      ports[i].UseCount--;      cond.Broadcast();      mutex.Unlock();      return;      }    }  mutex.Unlock();  PRINTF(L_GEN_DEBUG,"internal: can't find port in cSmartCards::ReleaseCard()");}bool cSmartCards::CardInserted(cSerial *ser){  return ser->CheckCAR();}bool cSmartCards::CardReset(struct Port *port){  if(Reset(port)<2 || !cSmartCard::ParseAtr(&port->Atr,port->PortNum,port->Clock))    return false;  if(!DoPTS(port)) {    // reset card again and continue without PTS    if(Reset(port)<2 || !cSmartCard::ParseAtr(&port->Atr,port->PortNum,port->Clock))      return false;    }  return true;}int cSmartCards::Reset(struct Port *port){  cSerial *ser=port->Serial;  PRINTF(L_CORE_SC,"%d: reseting card (sermode %s)",port->PortNum,serModes[ser->CurrentMode()]);  ser->ToggleRTS();  cCondWait::SleepMs(20);  ser->ToggleRTS();  int r=ser->Read(port->Atr.atr,-MAX_ATR_LEN,800,2000);  port->Atr.atrLen=r;  if(r>0) LDUMP(L_CORE_SC,port->Atr.atr,r,"%d: <- ATR len=%d:",port->PortNum,r);  return r;}bool cSmartCards::DoPTS(struct Port *port){  const struct Atr *atr=&port->Atr;  if(atr->F!=372 || atr->D!=1.0) { // PTS required    cSerial *ser=port->Serial;    const int id=port->PortNum;    int baud=(int)((float)port->Clock*atr->D/atr->F);    PRINTF(L_CORE_SC,"%d: PTS cycle: calculated baudrate %d",id,baud);    if(atr->Tspec<0) {      PRINTF(L_CORE_SC,"%d: negotiable mode",id);#ifdef NO_PTS_PROTO      PRINTF(L_CORE_SC,"%d: PTS disabled at compile time!!!",id);      return true;#else      unsigned char req[4], conf[16];      req[0]=0xFF;      req[1]=0x10 | atr->T;      req[2]=atr->TA1;      req[3]=XorSum(req,3);      LDUMP(L_CORE_SC,req,4,"%d: PTS request:",id);      if(ser->Write(req,4)!=4) {        PRINTF(L_CORE_SC,"%d: PTS request, write failed",id);        return false;        }      if(ser->Read(conf,4,100,100)!=4) {        PRINTF(L_CORE_SC,"%d: PTS request, echo readback failed",id);        return false;        }      int n=ser->Read(conf,-16,200,1000);      if(n>0) LDUMP(L_CORE_SC,conf,n,"%d: PTS confirm:",id);      if(n<1 || conf[0]!=0xFF || XorSum(conf,n)!=0) {        PRINTF(L_CORE_SC,"%d: PTS confirm, bad format",id);        return false;        }      if(n<4 || conf[1]!=req[1] || conf[2]!=req[2]) {        PRINTF(L_CORE_SC,"%d: PTS not confirmed",id);        return false;        }#endif // NO_PTS_PROTO      }    else      PRINTF(L_CORE_SC,"%d: specific mode Tspec=%d",id,atr->Tspec);    int mode=ser->CurrentMode();    if(atr->N==255) mode|=SM_1SB;    if(!ser->SetMode(mode,baud)) {      PRINTF(L_CORE_SC,"%d: setting baudrate %d failed",id,baud);      return false;      }    } return true;}void cSmartCards::SetPort(struct Port *port, cSmartCard *sc, int id, bool dead){  mutex.Lock();  while(port->UseCount) cond.Wait(mutex);  delete port->Card;  port->Card=sc;  port->CardId=id;  port->Dead=dead;  port->UseCount=0;  mutex.Unlock();}void cSmartCards::Action(void){  while(Running()) {    for(int i=0 ; i<MAX_PORTS ;) {      struct Port *port=&ports[i];      cSerial *ser=port->Serial;      if(ser) {        if(port->Card) {          cSmartCard *sc=port->Card;          sc->Lock();          if(!CardInserted(ser)) {            sc->Unlock(); sc=0;            PRINTF(L_CORE_SC,"%d: card removed (UseCount=%d)",port->PortNum,port->UseCount);            SetPort(port,0,0,false);            }          else if(sc->NeedsReset()) {            PRINTF(L_CORE_SC,"%d: card reset requested",port->PortNum);            if(!ser->SetMode(ser->CurrentMode()&SM_MASK)                || !CardReset(port)                || !sc->Setup(ser,&port->Atr,port->PortNum)) {              sc->Unlock(); sc=0;              PRINTF(L_CORE_SC,"%d: card re-init failed",port->PortNum);              SetPort(port,0,0,true);              }            }          if(sc) sc->Unlock();          }        else if(CardInserted(ser)) {          if(!port->Dead) {            PRINTF(L_CORE_SC,"%d: new card inserted",port->PortNum);            for(int mode=SM_NONE+1 ; mode<SM_MAX ; mode++) {              if(ser->SetMode(mode)) {                if(CardReset(port)) {                  cSmartCardLink *scl=first;                  while(scl) {                    PRINTF(L_CORE_SC,"%d: checking for %s card",port->PortNum,scl->name);                    cSmartCard *sc=scl->Create();                    if(sc && sc->Setup(ser,&port->Atr,port->PortNum)) {                      SetPort(port,sc,scl->id,false);                      goto next; // ugly, any better solution?                      }                    delete sc;                    scl=scl->next;                    }                  PRINTF(L_CORE_SC,"%d: no card handler found",port->PortNum);                  }                else PRINTF(L_CORE_SC,"%d: reset/atr error",port->PortNum);                }              else PRINTF(L_CORE_SC,"%d: failed to set serial mode %s",port->PortNum,serModes[mode]);              }            port->Dead=true;            PRINTF(L_CORE_SC,"%d: can't initialise new card, ignoring port until card reinserted",port->PortNum);            }          }        else {          if(port->Dead) PRINTF(L_CORE_SC,"%d: card removed, port reactivated",port->PortNum);          port->Dead=false;          }        }next: i++;      }    if(firstRun) {      mutex.Lock();      cond.Broadcast();      firstRun=false;      mutex.Unlock();      }    cCondWait::SleepMs(300);    }  }bool cSmartCards::ListCard(int num, char *str, int len){  if(num>=MAX_PORTS || !ports[num].Serial) return false;  str[0]=0;  mutex.Lock();  cSmartCard *sc=ports[num].Card;  if(sc) {    if(!sc->GetCardIdStr(str,len)) {      cSmartCardLink *scl=first;      while(scl) {        if(scl->id==ports[num].CardId) {          strn0cpy(str,scl->name,len);          break;          }        scl=scl->next;        }      }    }  mutex.Unlock();  return true;}bool cSmartCards::CardInfo(int num, char *str, int len){  bool res=false;  if(num<MAX_PORTS && ports[num].Serial) {    str[0]=0;    mutex.Lock();    cSmartCard *sc=ports[num].Card;    if(sc) res=sc->GetCardInfoStr(str,len);    mutex.Unlock();    }  return res;}void cSmartCards::CardReset(int num){  if(num<MAX_PORTS && ports[num].Serial) {    mutex.Lock();    cSmartCard *sc=ports[num].Card;    if(sc) sc->TriggerReset();    mutex.Unlock();    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -