]> www.vanbest.org Git - sasc-ng.git/commitdiff
smartcards: add support for CCID smartcards via pcscd
authorleslie <unknown>
Sun, 8 Mar 2009 14:12:23 +0000 (22:12 +0800)
committerleslie <unknown>
Sun, 8 Mar 2009 14:12:23 +0000 (22:12 +0800)
Makefile
examples/cardslot.conf.example
smartcard.c

index 5a410f2fb9f4c0679de9289ae1058fd3758413db..3cd15d6f4ae31eb86500775470ec2807ad991701 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -115,6 +115,11 @@ ifdef DEFAULT_PORT
   $(error DEFAULT_PORT support was removed, use cardslot.conf)
 endif
 
+ifdef WITH_PCSC
+  DEFINES  += -DWITH_PCSC
+  LIBS     += -lpcsclite
+endif
+
 # max number of CAIDs per slot
 MAXCAID := $(shell sed -ne '/define MAXCASYSTEMIDS/ s/^.[a-zA-Z ]*\([0-9]*\).*$$/\1/p' $(VDRDIR)/ci.c)
 ifneq ($(strip $(MAXCAID)),)
index 163b3aa2e9a49b0484f5356734b7685a6525c91f..7de2e63cbce58cdaed95e22ca4b8da7aab25c025 100644 (file)
@@ -27,6 +27,20 @@ serial:/dev/ttyS1:1:0:3579545
 srplus:/dev/ttyS0
 srplus:/dev/ttyS1:6000000
 
+; cardslot talking to PCSCd using CCID protocol for communication
+;
+; ccid:dev
+;
+; dev   - serial device e.g. /dev/ttyS0
+;
+; For using this cardslot type, you must have installed pcsd-lite and ccid
+; driver package. Before compiling you should add something like this to your
+; Make.config file:
+; WITH_PCSC = 1
+; INCLUDES += /usr/include/PCSC
+;
+ccid:/dev/usb0
+
 ; emulated smartcard on dummy port. For testing/debugging purpose only!
 ; The emulation code has to be enabled with the CARD_EMU define im smartcard.c
 ;
index e5ac24ad5c2ba87d6313b1f18e978e017ff6a6f4..5f1369a7c2ac74368ca951c6a56803b3832cc078 100644 (file)
@@ -1059,6 +1059,150 @@ bool cSmartCardSlotSRPlus::SRConfig(int F, float D, int fs, int N, int T, int in
   return true;
 }
 
+// -- cSmartCardSlotCCID -------------------------------------------------------
+
+#ifdef WITH_PCSC
+#include <winscard.h>
+
+class cSmartCardSlotCCID : public cSmartCardSlot {
+private:
+  SCARDCONTEXT hContext;
+  SCARDHANDLE hCard;
+  DWORD dwActiveProtocol, dwProtocol;
+  DWORD dwState, dwReaderLen;
+  bool needsReOpen;
+  //
+  int Transmit(const unsigned char *request, int requestlen, unsigned char *answer, int answerlen);
+protected:
+  virtual bool DeviceOpen(const char *cfg);
+  virtual void DeviceClose(void);
+  virtual bool DeviceSetMode(int mode, int baud);
+  virtual int DeviceRead(unsigned char *mem, int len, int timeout, int initialTimeout=0) { return -1; }
+  virtual int DeviceWrite(const unsigned char *mem, int len, int delay=0) { return -1; }
+  virtual void DeviceToggleReset(void) {}
+  virtual bool DevicePTS(void) { return false; }
+  virtual bool DeviceIsInserted(void);
+  //
+  virtual bool Reset(void);
+public:
+  virtual bool IsoRead(const unsigned char *cmd, unsigned char *data);
+  virtual bool IsoWrite(const unsigned char *cmd, const unsigned char *data);
+  virtual int RawRead(unsigned char *data, int len, int to=0) { return -1; }
+  virtual int RawWrite(const unsigned char *data, int len) { return -1; }
+  };
+
+static cSmartCardSlotLinkReg<cSmartCardSlotCCID> __scs_ccid("ccid");
+
+bool cSmartCardSlotCCID::DeviceOpen(const char *cfg)
+{
+  if(sscanf(cfg,"%255[^:]",devName)==1) {
+    LONG rv=SCardEstablishContext(SCARD_SCOPE_SYSTEM,NULL,NULL,&hContext);
+    PRINTF(L_CORE_SC,"%s: establish Context: %ld:%s",devName,rv,pcsc_stringify_error(rv));
+    DWORD protocol=SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1;
+    rv=SCardConnect(hContext,devName,SCARD_SHARE_SHARED,protocol,&hCard,&dwActiveProtocol);
+    dwProtocol=dwActiveProtocol;
+    PRINTF(L_CORE_SC,"%s: connect: %ld:%s",devName,rv,pcsc_stringify_error(rv));
+    needsReOpen=false;
+    return true;
+    }
+  else PRINTF(L_GEN_ERROR,"bad parameter for cardslot type 'ccid'");
+  return false;
+}
+
+void cSmartCardSlotCCID::DeviceClose(void)
+{
+  SCardDisconnect(hCard,SCARD_RESET_CARD);
+  SCardReleaseContext(hContext);
+}
+
+bool cSmartCardSlotCCID::DeviceSetMode(int mode, int baud)
+{
+  currMode=mode;
+  return true;
+}
+
+bool cSmartCardSlotCCID::DeviceIsInserted(void)
+{
+  BYTE pbAtr[MAX_ATR_SIZE];
+  DWORD dwAtrLen=sizeof(pbAtr);
+  LONG rv=SCardStatus(hCard,NULL,&dwReaderLen,&dwState,&dwProtocol,pbAtr,&dwAtrLen);
+  if(rv==SCARD_S_SUCCESS && (dwState&SCARD_NEGOTIABLE)) return true;
+  needsReOpen=true;
+  return false;
+}
+
+bool cSmartCardSlotCCID::Reset(void)
+{
+  PRINTF(L_CORE_SC,"%d: reseting card (sermode %s)",slotnum,serModes[DeviceCurrentMode()]);
+  if(needsReOpen) { DeviceClose(); DeviceOpen(0); }
+  LONG rv=SCardReconnect(hCard,SCARD_SHARE_EXCLUSIVE,dwProtocol,SCARD_RESET_CARD,&dwActiveProtocol);
+  if(rv!=SCARD_S_SUCCESS) {
+    PRINTF(L_CORE_SC,"%d: reset failed: %lx:%sn",slotnum,rv,pcsc_stringify_error(rv));
+    return false;
+    }
+  DWORD dwAtrLen=sizeof(atr.atr);
+  rv=SCardStatus(hCard,NULL,&dwReaderLen,&dwState,&dwProtocol,atr.atr,&dwAtrLen);
+  if(rv==SCARD_S_SUCCESS) {
+    atr.atrLen=dwAtrLen;
+    LDUMP(L_CORE_SC,atr.atr,dwAtrLen,"%d: <- ATR len=%ld:",slotnum,dwAtrLen);
+    return true;
+    }
+  return false;
+}
+
+int cSmartCardSlotCCID::Transmit(const unsigned char *request, int requestlen, unsigned char *answer, int answerlen)
+{
+  SCARD_IO_REQUEST pioRecvPci, pioSendPci;
+  switch (dwProtocol) {
+    case SCARD_PROTOCOL_T0:
+    case SCARD_PROTOCOL_T1:
+       pioSendPci.dwProtocol=dwProtocol;
+       pioSendPci.cbPciLength=sizeof(pioSendPci);
+       pioRecvPci.dwProtocol=dwProtocol;
+       pioRecvPci.cbPciLength=sizeof(pioRecvPci);
+       break;
+    default:
+       PRINTF(L_CORE_SC,"%d: protocol failure: %ld",slotnum,dwProtocol);
+        return 0;
+    }
+  DWORD answlen=answerlen;
+  DWORD rv=SCardTransmit(hCard,&pioSendPci,(LPCBYTE)request,(DWORD)requestlen,&pioRecvPci,(LPBYTE)answer,&answlen);
+  if(rv!=SCARD_S_SUCCESS) {
+     PRINTF(L_CORE_SC, "%d: transmit failed: %0lx:%s\n",slotnum,rv,pcsc_stringify_error(rv));
+     return -1;
+     }
+  return answlen;
+}
+
+bool cSmartCardSlotCCID::IsoRead(const unsigned char *cmd, unsigned char *data)
+{
+  LDUMP(L_CORE_SC,cmd,CMD_LEN,"%d: -> INS:",slotnum);
+  int restlen=Transmit(cmd,CMD_LEN,data,MAX_LEN);
+  if(restlen<2) return Test(false);
+  sb[0]=data[restlen-2];
+  sb[1]=data[restlen-1];
+  LDUMP(L_CORE_SC,sb,2,"%d: <- SB: ",slotnum);
+  LDUMP(L_CORE_SC,data,restlen-2,"%d: <- DATA:",slotnum);
+  return true;
+}
+
+bool cSmartCardSlotCCID::IsoWrite(const unsigned char *cmd, const unsigned char *data)
+{
+  LDUMP(L_CORE_SC,cmd,CMD_LEN,"%d: -> INS:",slotnum);
+  LDUMP(L_CORE_SC,data,cmd[LEN_IDX],"%d: -> DATA:",slotnum);
+  unsigned char sendbuf[MAX_LEN+CMD_LEN], recvbuf[MAX_LEN];
+  memcpy(sendbuf,cmd,CMD_LEN);
+  memcpy(sendbuf+CMD_LEN,data,sendbuf[LEN_IDX]);
+  int restlen=Transmit(sendbuf,CMD_LEN+sendbuf[LEN_IDX],recvbuf,MAX_LEN);
+  if(restlen<2) return Test(false);
+  sb[0]=recvbuf[restlen-2];
+  sb[1]=recvbuf[restlen-1];
+  LDUMP(L_CORE_SC,sb,2,"%d: <- SB: ",slotnum);
+  return true;
+}
+
+#endif //WITH_PCSC
+
 // -- cSmartCardSlotEmuGeneric -------------------------------------------------
 
 #ifdef CARD_EMU