source: trunk/csctapi/ifd_pcsc.c@ 3715

Last change on this file since 3715 was 3715, checked in by cogsi, 13 years ago

Fix pcsc reader on x86, x86_64

File size: 8.9 KB
Line 
1#ifdef HAVE_PCSC
2
3#include "ifd_pcsc.h"
4int pcsc_reader_init(struct s_reader *pcsc_reader, char *device)
5{
6 ULONG rv;
7 DWORD dwReaders;
8 LPSTR mszReaders = NULL;
9 char *ptr, **readers = NULL;
10 int nbReaders;
11 int reader_nb;
12
13 cs_debug("PCSC establish context for PCSC reader %s", device);
14 rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &pcsc_reader->hContext);
15 if ( rv == SCARD_S_SUCCESS ) {
16 // here we need to list the pcsc readers and get the name from there,
17 // the pcsc_reader->device should contain the reader number
18 // and after the actual device name is copied in pcsc_reader->pcsc_name .
19 rv = SCardListReaders(pcsc_reader->hContext, NULL, NULL, &dwReaders);
20 if( rv != SCARD_S_SUCCESS ) {
21 cs_debug("PCSC failed listing readers [1] : (%lx)", rv);
22 return 0;
23 }
24 mszReaders = malloc(sizeof(char)*dwReaders);
25 if (mszReaders == NULL) {
26 cs_debug("PCSC failed malloc");
27 return 0;
28 }
29 rv = SCardListReaders(pcsc_reader->hContext, NULL, mszReaders, &dwReaders);
30 if( rv != SCARD_S_SUCCESS ) {
31 cs_debug("PCSC failed listing readers [2]: (%lx)", rv);
32 free(mszReaders);
33 return 0;
34 }
35 /* Extract readers from the null separated string and get the total
36 * number of readers */
37 nbReaders = 0;
38 ptr = mszReaders;
39 while (*ptr != '\0') {
40 ptr += strlen(ptr)+1;
41 nbReaders++;
42 }
43
44 if (nbReaders == 0) {
45 cs_debug("PCSC : no reader found");
46 free(mszReaders);
47 return 0;
48 }
49
50 readers = calloc(nbReaders, sizeof(char *));
51 if (readers == NULL) {
52 cs_debug("PCSC failed malloc");
53 return 0;
54 }
55
56 /* fill the readers table */
57 nbReaders = 0;
58 ptr = mszReaders;
59 while (*ptr != '\0') {
60 cs_debug("PCSC reader %d: %s", nbReaders, ptr);
61 readers[nbReaders] = ptr;
62 ptr += strlen(ptr)+1;
63 nbReaders++;
64 }
65
66 reader_nb=atoi((const char *)&pcsc_reader->device);
67 if (reader_nb < 0 || reader_nb >= nbReaders) {
68 cs_debug("Wrong reader index: %d\n", reader_nb);
69 free(mszReaders);
70 free(readers);
71 return 0;
72 }
73
74 snprintf(pcsc_reader->pcsc_name,sizeof(pcsc_reader->pcsc_name),"%s",readers[reader_nb]);
75 pcsc_reader->pcsc_has_card=0;
76 pcsc_reader->hCard=0;
77 free(mszReaders);
78 free(readers);
79 }
80 else {
81 cs_debug("PCSC failed establish context (%lx)", rv);
82 }
83 return 0;
84}
85
86int pcsc_reader_do_api(struct s_reader *pcsc_reader, const uchar *buf, uchar *cta_res, ushort *cta_lr, int l)
87{
88 ULONG rv;
89 SCARD_IO_REQUEST pioRecvPci;
90 DWORD dwSendLength, dwRecvLength;
91
92 if(!l) {
93 cs_log("ERROR : data length to be send to the reader is %d" , l);
94 return ERR_INVALID;
95 }
96
97 dwRecvLength = CTA_RES_LEN;
98
99 if(pcsc_reader->dwActiveProtocol == SCARD_PROTOCOL_T0) {
100 // explanantion as to why we do the test on buf[4] :
101 // Issuing a command without exchanging data :
102 //To issue a command to the card that does not involve the exchange of data (either sent or received), the send and receive buffers must be formatted as follows.
103 //The pbSendBuffer buffer must contain the CLA, INS, P1, and P2 values for the T=0 operation. The P3 value is not sent. (This is to differentiate the header from the case where 256 bytes are expected to be returned.)
104 //The cbSendLength parameter must be set to four, the size of the T=0 header information (CLA, INS, P1, and P2).
105 //The pbRecvBuffer will receive the SW1 and SW2 status codes from the operation.
106 //The pcbRecvLength should be at least two and will be set to two upon return.
107 cs_debug("command = %02X %02X %02X %02X %02X", buf[0],buf[1],buf[2],buf[3],buf[4]);
108 if(buf[4])
109 dwSendLength = l;
110 else
111 dwSendLength = l-1;
112 cs_debug("sending %d bytes to PCSC", dwSendLength);
113 rv = SCardTransmit(pcsc_reader->hCard, SCARD_PCI_T0, (LPCBYTE) buf, dwSendLength, &pioRecvPci, (LPBYTE) cta_res, (LPDWORD) &dwRecvLength);
114 }
115 else if(pcsc_reader->dwActiveProtocol == SCARD_PROTOCOL_T1) {
116 dwSendLength = l;
117 cs_debug("sending %d bytes to PCSC", dwSendLength);
118 rv = SCardTransmit(pcsc_reader->hCard, SCARD_PCI_T1, (LPCBYTE) buf, dwSendLength, &pioRecvPci, (LPBYTE) cta_res, (LPDWORD) &dwRecvLength);
119 }
120 else {
121 cs_debug("PCSC invalid protocol (T=%d)", pcsc_reader->dwActiveProtocol);
122 return ERR_INVALID;
123 }
124
125 *cta_lr=dwRecvLength;
126 cs_debug("received %d bytes from PCSC with rv=%lx", *cta_lr, rv);
127
128 cs_debug("PCSC doapi (%lx ) (T=%d), %d", rv, ( pcsc_reader->dwActiveProtocol == SCARD_PROTOCOL_T0 ? 0 : 1), dwRecvLength );
129 if ( rv == SCARD_S_SUCCESS ){
130 return OK;
131 }
132 else {
133 return ERR_INVALID;
134 }
135
136}
137
138int pcsc_activate_card(struct s_reader *pcsc_reader, uchar *atr, ushort *atr_size)
139{
140 ULONG rv;
141 DWORD dwState, dwAtrLen, dwReaderLen;
142 BYTE pbAtr[64];
143
144 cs_debug("PCSC initializing card in (%s)", pcsc_reader->pcsc_name);
145 dwAtrLen = sizeof(pbAtr);
146 dwReaderLen=0;
147
148 cs_debug("PCSC resetting card in (%s)", pcsc_reader->pcsc_name);
149 rv = SCardReconnect(pcsc_reader->hCard, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, SCARD_RESET_CARD, &pcsc_reader->dwActiveProtocol);
150 cs_debug("PCSC resetting done on card in (%s)", pcsc_reader->pcsc_name);
151 cs_debug("PCSC Protocol (T=%d)",( pcsc_reader->dwActiveProtocol == SCARD_PROTOCOL_T0 ? 0 : 1));
152
153 if ( rv != SCARD_S_SUCCESS ) {
154 cs_debug("Error PCSC failed to reset card (%lx)", rv);
155 return(0);
156 }
157
158
159 cs_log("PCSC getting ATR for card in (%s) %d", pcsc_reader->pcsc_name, pcsc_reader->hCard);
160 rv = SCardStatus(pcsc_reader->hCard,NULL, &dwReaderLen, &dwState, &pcsc_reader->dwActiveProtocol, pbAtr, &dwAtrLen);
161 if ( rv == SCARD_S_SUCCESS ) {
162 cs_debug("PCSC Protocol (T=%d)",( pcsc_reader->dwActiveProtocol == SCARD_PROTOCOL_T0 ? 0 : 1));
163 memcpy(atr, pbAtr, dwAtrLen);
164 *atr_size=dwAtrLen;
165 pcsc_reader->init_history_pos=0;
166
167 //cs_ri_log("ATR: %s", cs_hexdump(1, (uchar *)pbAtr, dwAtrLen));
168 return(1);
169 }
170 else {
171 cs_debug("Error PCSC failed to get ATR for card (%lx)", rv);
172 }
173
174 return(0);
175}
176
177
178int pcsc_check_card_inserted(struct s_reader *pcsc_reader)
179{
180 DWORD dwState, dwAtrLen, dwReaderLen;
181 BYTE pbAtr[64];
182 ULONG rv;
183
184 dwAtrLen = sizeof(pbAtr);
185 rv=0;
186 dwState=0;
187 dwReaderLen=0;
188
189 // Do we have a card ?
190 if (!pcsc_reader->pcsc_has_card && !pcsc_reader->hCard) {
191 // try connecting to the card
192 rv = SCardConnect(pcsc_reader->hContext, pcsc_reader->pcsc_name, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &pcsc_reader->hCard, &pcsc_reader->dwActiveProtocol);
193 if (rv==SCARD_E_NO_SMARTCARD) {
194 // no card in reader
195 pcsc_reader->pcsc_has_card=0;
196 if(pcsc_reader->hCard) {
197// //SCardDisconnect(pcsc_reader->hCard,SCARD_RESET_CARD);
198 pcsc_reader->hCard=0;
199 }
200 // cs_debug("PCSC card in %s removed / absent [dwstate=%lx rv=(%lx)]", pcsc_reader->pcsc_name, dwState, rv );
201 return 0;
202 }
203 else if( rv == SCARD_W_UNRESPONSIVE_CARD ) {
204 // there is a problem with the card in the reader
205 pcsc_reader->pcsc_has_card=0;
206 pcsc_reader->hCard=0;
207 cs_log("PCSC card in %s is unresponsive. Eject and re-insert please.", pcsc_reader->pcsc_name);
208 return 0;
209 }
210 else if( rv == SCARD_S_SUCCESS ) {
211 // we have a card
212 pcsc_reader->pcsc_has_card=1;
213 }
214 else {
215 // if we get here we have a bigger problem -> display status and debug
216 // cs_debug("PCSC reader %s status [dwstate=%lx rv=(%lx)]", pcsc_reader->pcsc_name, dwState, rv );
217 return 0;
218 }
219
220 }
221
222 // if we get there the card is ready, check its status
223 rv = SCardStatus(pcsc_reader->hCard, NULL, &dwReaderLen, &dwState, &pcsc_reader->dwActiveProtocol, pbAtr, &dwAtrLen);
224
225 if (rv == SCARD_S_SUCCESS && (dwState & (SCARD_PRESENT | SCARD_NEGOTIABLE | SCARD_POWERED ) )) {
226 return CARD_INSERTED;
227 }
228 else {
229 //SCardDisconnect(pcsc_reader->hCard,SCARD_RESET_CARD);
230 pcsc_reader->hCard=0;
231 pcsc_reader->pcsc_has_card=0;
232 }
233
234 return 0;
235}
236
237void pcsc_close(struct s_reader *pcsc_reader)
238{
239 cs_debug_mask (D_IFD, "PCSC : Closing device %s", pcsc_reader->device);
240 //SCardDisconnect(pcsc_reader->hCard,SCARD_RESET_CARD);
241 SCardReleaseContext(pcsc_reader->hContext);
242 pcsc_reader->hCard=0;
243 pcsc_reader->pcsc_has_card=0;
244}
245#endif
246
Note: See TracBrowser for help on using the repository browser.