Blog

Smartcard 读写器函数库的使用说明

2020-04-23 10:36:09 明申科技 17

一、IC卡与操作系统的整合


前面所谈的标准及各种IC卡的规格,多半只论及IC卡或卡片阅读机。使用者要使用卡片阅读机时,必须安装厂商提供之驱动程序(drivers),开发应用程序。

PC/SC(Personal Computer/Smart Card)支持ISO7816-4的基本指令集,界定了IC卡、卡片阅读机及操作系统的责任与分工,各家卡片阅读机厂商只要遵循PC/SC所定义之接口与方法开发驱动程序,即可结合到Windows或其它操作系统,应用程序只要透过单一标准接口与操作系统沟通,就可轻易操控各种卡片阅读机读写IC卡。

Microsoft也在1997年底提供了Smart Card SDK给应用程序开发者,陆陆续续许多厂商的IC卡、卡片阅读机产品开始宣称其产品符合PC/SC规范,PC/SC俨然成为未来时势的潮流。

应用程序与Smartcard之运作如下:

1、应用程序使用PC/SC API 传送APDU指令传给操作系统。

2、操作系统透过符合PC/SC规范之驱动程序将APDU指令传给卡片阅读机。

3、卡片阅读机使用T=0或T=1之通讯协议将指令传送至Smartcard传输管理器。

4、传输管理器再将APDU指令传送至Smartcard COS运作后回复处理结果。 


二、PC/SC API for Visual C++


1、#i nclude <winscard.h>

winscard.h是Visual C++编译时所需要的参数及基本数据结构,请记得连结时加入winscard.lib,这样才能完成您的程序,此两文件在Visual C++ 的 include及library目录下可以找到,这种方式称为「隐式调用DLL」,程序好像与winscard.dll无关但实际上是透过DLL执行,.h档案内容大致如下:


#define SCARD_STATE_UNAWARE 0x00000000

#define SCARD_STATE_IGNORE 0x00000001

#define SCARD_STATE_CHANGED 0x00000002

#define SCARD_STATE_UNKNOWN 0x00000004

#define SCARD_STATE_UNAVAILABLE 0x00000008


WINSCARDDATA extern const SCARD_IO_REQUEST

g_rgSCardT0Pci,

g_rgSCardT1Pci,

g_rgSCardRawPci;


extern WINSCARDAPI LONG WINAPI

SCardEstablishContext(

IN DWORD dwScope,

IN LPCVOID pvReserved1,

IN LPCVOID pvReserved2,

OUT LPSCARDCONTEXT phContext);


其实 PC/SC 不一定要在Windows 系统执行,以下定义为Linux系统所使用之PC/SC,请比较一下差异在哪里。


typedef struct {

DWORD dwProtocol; /* SCARD_PROTOCOL_T0 or SCARD_PROTOCOL_T1 */

DWORD cbPciLength; /* Length of this structure - not used */

} SCARD_IO_REQUEST;


long SCardEstablishContext(unsigned long dwScope,const void *pvReserved1, const void *pvReserved2, long *phContext);


以下说明一些重要函式之功能,细节部分请参考,附件二、PC/SC API Reference Document。


2、ScardEstablishContext

SCardEstablishContext 直觉的解释就是建立PC/SC在操作系统下的资源,所有PC/SC应用程序开始时一定要呼叫此函式建立资源后才能开始运作,范例如下。


SCARDCONTEXT hContext;

LONG rv;

rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);


3、ScardListReaders

SCardListReaders 直觉的解释就是列出此台机器可用之Smartcard 卡片阅读机,比较特别的是第一次呼叫时并不知道机器有几台可用之卡片阅读机所以mszReaders先代入NULL,取得实际数量后再呼叫一次就可列出卡片阅读机名称,此技巧运用在很多API 呼叫中,第一次看到觉得怪怪,仔细想想此种呼叫方式真聪明。


LPTSTR mszReaders;

DWORD dwReaders;

rv = SCardListReaders(hContext, NULL, NULL, &dwReaders);

mszReaders = (LPTSTR)malloc(sizeof(char)*dwReaders);

rv = SCardListReaders(hContext, NULL, mszReaders, &dwReaders);


4、ScardConnect

SCardConnect 直觉的解释就是建立Smartcard之联机,参数就是代入SCardListReaders 所列出之卡片阅读机名称;当联机完成后Smartcard会被重置,传回ATR讯息。


SCARDHANDLE hCard;

DWORD dwActiveProtocol;

rv = SCardConnect(hContext, "Reader X", SCARD_SHARE_SHARED,

SCARD_PROTOCOL_T0, &hCard, &dwActiveProtocol);


5、ScardBeginTransaction

当卡片阅读机以分享方式开启时,SCardBeginTransaction 就是宣告尔后将执行一连串的APDU指令以确保中间不被插断,当结束所有APDU指令后需呼叫ScardEndTransaction让其它联机继续运作;当卡片阅读机以独占方式开启时,可以不必执行此函式,直接执行SCardTransmit即可。


rv = SCardBeginTransaction(hCard);


6、ScardTransmit

SCardTransmit是在呼叫SCardConnect函式后,传送APDU 指令到Smartcard的函式,可说是整个Smartcard程序设计的核心,在此特别说明下列程序。

DWORD dwSendLength, dwRecvLength;

SCARD_IO_REQUEST pioRecvPci;

/*必须使用BYTE传送及接收数据,如果您输入的指令是CHAR记得转换为BYTE ,很特别的是此函式呼叫时就已经定义好接收数据*/

BYTE pbRecvBuffer[10];

/*此行即为APDU Command,特别解释一下,这行指令是选取Master File。

Command CLA INS P1 P2 Lc Data Le

Select C0 A4 00 00 02 3F00 

*/

BYTE pbSendBuffer[] = { 0xC0, 0xA4, 0x00, 0x00, 0x02, 0x3F, 0x00 };


dwSendLength = sizeof(pbSendBuffer);

dwRecvLength = sizeof(pbRecvBuffer);

rv = SCardTransmit(hCard, SCARD_PCI_T0, pbSendBuffer, dwSendLength,

&pioRecvPci, pbRecvBuffer, &dwRecvLength);


7、SCardEndTransaction

SCardEndTransaction 是结束之前SCardBeginTransaction 之宣告;必须与SCardBeginTransaction配对使用。


rv = SCardEndTransaction(hCard, SCARD_LEAVE_CARD);


8、ScardDisconnect

SCardDisconnect 是结束之前SCardConnect所建立的联机,呼叫此函式后就无法在传送APDU指令了。


rv = SCardDisconnect(hCard, SCARD_UNPOWER_CARD);


9、ScardReleaseContext

SCardReleaseContext 直觉的解释就是释放SCardEstablishContext 在操作系统下所建立的资源,所有PC/SC应用程序结束时一定要呼叫此函式归还资源。


rv = SCardReleaseContext(hContext);


10、其它PC/SC API

PC/SC API函式不只这些,某些应用场合可能会使用到,请参考PC/SC API Reference Document。




三、PC/SC API for Visual Basic


API可说是系统的一部份,请搜寻winscard.dll您会发现它位于system32目录下,这个文件包含PC/SC所有的函式,所以PC/SC API函式VB的定义会变成这样:


Global Const SCARD_CLASS_VENDOR_INFO = 1 ' Vendor information definitions

Global Const SCARD_CLASS_COMMUNICATIONS = 2 ' Communication definitions

Global Const SCARD_CLASS_PROTOCOL = 3 ' Protocol definitions

Global Const SCARD_CLASS_POWER_MGMT = 4 ' Power Management definitions

Global Const SCARD_CLASS_SECURITY = 5 ' Security Assurance definitions

Global Const SCARD_CLASS_MECHANICAL = 6 ' Mechanical characteristic definitions

Global Const SCARD_CLASS_VENDOR_DEFINED = 7 ' Vendor specific definitions

Global Const SCARD_CLASS_IFD_PROTOCOL = 8 ' Interface Device Protocol options


Public Type SCARD_IO_REQUEST

dwProtocol As Long

cbPciLength As Long

End Type 


Public Declare Function SCardEstablishContext Lib "WinScard.dll" ( _

ByVal dwScope As Long, _

ByVal pvReserved1 As Long, _

ByVal pvReserved2 As Long, _

ByRef phContext As Long _

) As Long


从Visual Basic函式定义可以看出,PC/SC API应用程序都是呼叫winscard.dll来处理Window操作系统之资源分配、卡片阅读机及传送APDU指令的功能,这种方式称为「显式调用DLL」。


首页
产品
新闻
联系