source: trunk/csctapi/ifd_pcsc.c@ 3181

Last change on this file since 3181 was 3181, checked in by dingo35, 10 years ago

Adding threadsafety FIXMEs, feel free to join checking..

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