PCSC Wrapper to access smartcards

Just starting out? Need help? Post your questions and find answers here.
Leo
User
User
Posts: 21
Joined: Sat Aug 02, 2003 8:48 pm
Location: Netherlands, Wijk bij Duurstede

PCSC Wrapper to access smartcards

Post by Leo »

Hello,

I wrote a little PCSC wrapper to access smartcards. Only the basic functions of the winscard.dll are implemented. I did use the Interface command that is new in PureBasic 3.81. The source code is listed below

Code: Select all

;*******************************************************
;
;  PureBasic : PCSC Wrapper
;  Author : Leo Mijnders
;  Date : 29 March 2004
;  Doc : http://msdn.microsoft.com/library/en-us/security/security/authentication_functions.asp?frame=true#smart_card_functions
;
;*******************************************************

#SCARD_SHARE_EXCLUSIVE = 1 ; This application is not willing To share this
                           ; // card with other applications.
#SCARD_SHARE_SHARED = 2    ; This application is willing To share this
                           ; // card with other applications.
#SCARD_SHARE_DIRECT = 3    ; // This application demands direct control of

#SCARD_PROTOCOL_T0               =$0001   ;/* T=0 active protocol. */
#SCARD_PROTOCOL_T1               =$0002   ;/* T=1 active protocol. */
#SCARD_PROTOCOL_RAW              =$0004   ;/* Raw active protocol. */


#SCARD_UNKNOWN                   =$0001   ;/* Unknown state */
#SCARD_ABSENT                    =$0002   ;/* Card is absent */
#SCARD_PRESENT                   =$0004   ;/* Card is present */
#SCARD_SWALLOWED                 =$0008   ;/* Card not powered */
#SCARD_POWERED                   =$0010   ;/* Card is powered */
#SCARD_NEGOTIABLE                =$0020   ;/* Ready For PTS */
#SCARD_SPECIFIC                  =$0040   ;/* PTS has been set */

#SCARD_LEAVE_CARD                =$0000   ;/* Do nothing on close */
#SCARD_RESET_CARD                =$0001   ;/* Reset on close */
#SCARD_UNPOWER_CARD              =$0002   ;/* Power down on close */
#SCARD_EJECT_CARD                =$0003   ;/* Eject on close */

#SCARD_S_SUCCESS                 =$00000000
#SCARD_E_CANCELLED               =$80100002
#SCARD_E_CANT_DISPOSE            =$8010000E
#SCARD_E_INSUFFICIENT_BUFFER     =$80100008
#SCARD_E_INVALID_ATR             =$80100015
#SCARD_E_INVALID_HANDLE          =$80100003
#SCARD_E_INVALID_PARAMETER       =$80100004
#SCARD_E_INVALID_TARGET          =$80100005
#SCARD_E_INVALID_VALUE           =$80100011
#SCARD_E_NO_MEMORY               =$80100006
#SCARD_F_COMM_ERROR              =$80100013
#SCARD_F_INTERNAL_ERROR          =$80100001
#SCARD_F_UNKNOWN_ERROR           =$80100014
#SCARD_F_WAITED_TOO_LONG         =$80100007
#SCARD_E_UNKNOWN_READER          =$80100009
#SCARD_E_TIMEOUT                 =$8010000A
#SCARD_E_SHARING_VIOLATION       =$8010000B
#SCARD_E_NO_SMARTCARD            =$8010000C
#SCARD_E_UNKNOWN_CARD            =$8010000D
#SCARD_E_PROTO_MISMATCH          =$8010000F
#SCARD_E_NOT_READY               =$80100010
#SCARD_E_SYSTEM_CANCELLED        =$80100012
#SCARD_E_NOT_TRANSACTED          =$80100016
#SCARD_E_READER_UNAVAILABLE      =$80100017


Enumeration
  #SCARD_SCOPE_USER            ;    0x0000/* Scope in user space */
  #SCARD_SCOPE_TERMINAL        ;    0x0001/* Scope in terminal */
  #SCARD_SCOPE_SYSTEM          ;    0x0002/* Scope in system */
EndEnumeration 


Global fSCardEstablishContext, fSCardConnect, fSCardStatus, fSCardDisconnect, fSCardTransmit
Global fSCardListReaders

Global g_rgSCardT0Pci, g_rgSCardT1Pci, g_rgSCardRawPci

Procedure.l InitPCSC(Lib.l)
  If OpenLibrary(Lib, "winscard.dll")

    ; Pointers to SCARD_IO_REQUEST structures
    
    g_rgSCardT0Pci=IsFunction(Lib,"g_rgSCardT0Pci")
    g_rgSCardT1Pci=IsFunction(Lib,"g_rgSCardT1Pci")
    g_rgSCardRawPci=IsFunction(Lib,"g_rgSCardRawPci")

    ; Pointers to Basic PCSC Functions
    
    fSCardEstablishContext=IsFunction(Lib,"SCardEstablishContext")
    fSCardConnect=IsFunction(Lib,"SCardConnectA")
    fSCardStatus=IsFunction(Lib,"SCardStatusA")
    fSCardDisconnect=IsFunction(Lib,"SCardDisconnect")
    fSCardTransmit=IsFunction(Lib,"SCardTransmit")
    fSCardListReaders=IsFunction(Lib,"SCardListReadersA")
    
    ProcedureReturn 0
  EndIf
  ProcedureReturn -1
EndProcedure 

Procedure.l sSCardEstablishContext(self.l, a.l, b.l, c.l, d.l)
  ProcedureReturn CallFunctionFast(fSCardEstablishContext, a, b, c, d)
EndProcedure

Procedure.l sSCardConnect(self.l, a.l, b.l, c.l, d.l, e.l, f.l)
  ProcedureReturn CallFunctionFast(fSCardConnect, a, b, c, d, e, f)
EndProcedure

Procedure.l sSCardStatus(self.l, a.l, b.l, c.l, d.l, e.l, f.l, g.l)
  ProcedureReturn CallFunctionFast(fSCardStatus, a, b, c, d, e, f, g)
EndProcedure

Procedure.l sSCardDisconnect(self.l, a.l, b.l)
  ProcedureReturn CallFunctionFast(fSCardDisconnect, a, b)
EndProcedure

Procedure.l sSCardTransmit(self.l, a.l, b.l, c.l, d.l, e.l, f.l, g.l)
  ProcedureReturn CallFunctionFast(fSCardTransmit, a, b, c, d, e, f, g)
EndProcedure

Procedure.l sSCardListReaders(self.l, a.l, b.l, c.l, d.l)
  ProcedureReturn CallFunctionFast(fSCardListReaders, a, b, c, d)
EndProcedure

Interface IF_PCSC
  EstablishContext(a.l, b.l, c.l, d.l)
  Connect(a.l, b.l, c.l, d.l, e.l, f.l)
  Status(a.l, b.l, c.l, d.l, e.l, f.l, g.l)
  Disconnect(a.l, b.l)
  Transmit(a.l, b.l, c.l, d.l, e.l, f.l, g.l)
  ListReaders(a.l, b.l, c.l, d.l)
EndInterface

Structure strucInterface
  a.l
  b.l
  c.l
  d.l
  e.l
  f.l
EndStructure

SCard.IF_PCSC
Struc.strucInterface

Struc\a=@sSCardEstablishContext()
Struc\b=@sSCardConnect()
Struc\c=@sSCardStatus()
Struc\d=@sSCardDisconnect()
Struc\e=@sSCardTransmit()
Struc\f=@sSCardListReaders()

AddStruc.l=@Struc
PokeL(@SCard,@AddStruc)

Structure IO_REQ
  P.l
  A.l
  B.b[512]
EndStructure

outPCI_T0.IO_REQ

outPCI_T0\P=1
outPCI_T0\A=512


; *************************** CompilerIf 0 if used as IncludeFile  or  1 = if test IncludeFile

CompilerIf 0

  Procedure.s HexString(Source.l, L.l) 
    result.s = ""
    For i = 0 To L-1
        result = result + Right("00" + Hex(PeekB(Source+i)), 2) 
    Next i
    ProcedureReturn result
  EndProcedure
  
  hCTX.l
  Buf.s=Space(1000)
  ATRL.l
  ATR.l=AllocateMemory(2,100)
  hCARD.l
  AP.l
  L.l
  S.L
  In.l=AllocateMemory(3,100)
  Out.l=AllocateMemory(4,100)
  OutL.l

  ; APDU to genarate 8 byte Random at TB100 smartcard

  PokeB(In,$BC)
  PokeB(In+1,$C4)
  PokeB(In+2,$00)
  PokeB(In+3,$00)
  PokeB(In+4,$08)

  If InitPCSC(10)=0
    A=SCard\EstablishContext(0,0,0,@hCTX)
    MessageRequester("hCTX", Hex(A)+" "+Hex(hCTX),0)
    L.l=1000
    A=SCard\ListReaders(hCTX,0,@Buf,@L)
    MessageRequester("Reader", Hex(A)+" "+Buf,0)
    A=SCard\Connect(hCTX,@"TOWITOKO CHIPDRIVE 0",#SCARD_SHARE_SHARED,#SCARD_PROTOCOL_T0 | #SCARD_PROTOCOL_T1,@hCARD,@AP)
    MessageRequester("Connect", Hex(A),0)
    A=SCard\Status(hCARD,@Buf,@L,@S,@AP,ATR,@ATRL)
    MessageRequester("Status", Hex(A)+" "+Hex(S)+" "+Hex(AP)+" "+Hex(ATRL)+" "+Hex(PeekL(ATR)),0)
    A=SCard\DisConnect(hCARD,#SCARD_RESET_CARD)
    MessageRequester("Disconnect", Hex(A))
    A=SCard\Connect(hCTX,@"TOWITOKO CHIPDRIVE 0",#SCARD_SHARE_SHARED,#SCARD_PROTOCOL_T0 | #SCARD_PROTOCOL_T1,@hCARD,@AP)
    MessageRequester("Connect", Hex(A),0)
    A=SCard\Status(hCARD,@Buf,@L,@S,@AP,ATR,@ATRL)
    MessageRequester("Status", Hex(A)+" "+Hex(S)+" "+Hex(AP)+" "+Hex(ATRL)+" "+HexString(ATR,ATRL),0)
    For I=1 To 10
      OutL=10
      A=SCard\Transmit(hCARD, g_rgSCardT0Pci, In, 5, @outPCI_T0, Out, @OutL)
      MessageRequester("Transmit", Hex(A)+" "+HexString(Out,OutL)+" "+Hex(OutL),0)
    Next  
    A=SCard\DisConnect(hCARD,#SCARD_RESET_CARD)
    MessageRequester("Disconnect", Hex(A))
  Else
    MessageRequester("Error", "Lib not loaded",0)
  EndIf  
  
CompilerEndIf
Have fun

Greetings

Leo
Lazarus404
User
User
Posts: 74
Joined: Fri Dec 02, 2005 3:11 pm
Location: England
Contact:

Post by Lazarus404 »

I've modified this, now, to work with Tikitag. Does anyone have any examples of doing this for Linux and Mac OS's?
Laz

Registered PureBasic user since Nov 2005
Check out FlashML at www.designrealm.co.uk... The ultimate Flash Component
Post Reply