1 | #ifdef HAVE_PCSC
|
---|
2 |
|
---|
3 | #include "reader-pcsc.h"
|
---|
4 | int 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 | return 0;
|
---|
33 | }
|
---|
34 | /* Extract readers from the null separated string and get the total
|
---|
35 | * number of readers */
|
---|
36 | nbReaders = 0;
|
---|
37 | ptr = mszReaders;
|
---|
38 | while (*ptr != '\0') {
|
---|
39 | ptr += strlen(ptr)+1;
|
---|
40 | nbReaders++;
|
---|
41 | }
|
---|
42 |
|
---|
43 | if (nbReaders == 0) {
|
---|
44 | cs_debug("PCSC : no reader found");
|
---|
45 | return 0;
|
---|
46 | }
|
---|
47 |
|
---|
48 | readers = calloc(nbReaders, sizeof(char *));
|
---|
49 | if (readers == NULL) {
|
---|
50 | cs_debug("PCSC failed malloc");
|
---|
51 | return 0;
|
---|
52 | }
|
---|
53 |
|
---|
54 | /* fill the readers table */
|
---|
55 | nbReaders = 0;
|
---|
56 | ptr = mszReaders;
|
---|
57 | while (*ptr != '\0') {
|
---|
58 | cs_debug("PCSC reader %d: %s", nbReaders, ptr);
|
---|
59 | readers[nbReaders] = ptr;
|
---|
60 | ptr += strlen(ptr)+1;
|
---|
61 | nbReaders++;
|
---|
62 | }
|
---|
63 |
|
---|
64 | reader_nb=atoi((const char *)&pcsc_reader->device);
|
---|
65 | if (reader_nb < 0 || reader_nb >= nbReaders) {
|
---|
66 | cs_debug("Wrong reader index: %d\n", reader_nb);
|
---|
67 | return 0;
|
---|
68 | }
|
---|
69 |
|
---|
70 | snprintf(pcsc_reader->pcsc_name,sizeof(pcsc_reader->pcsc_name),"%s",readers[reader_nb]);
|
---|
71 | pcsc_reader->pcsc_has_card=0;
|
---|
72 | pcsc_reader->hCard=0;
|
---|
73 | }
|
---|
74 | else {
|
---|
75 | cs_debug("PCSC failed establish context (%lx)", rv);
|
---|
76 | }
|
---|
77 |
|
---|
78 | return 0;
|
---|
79 | }
|
---|
80 |
|
---|
81 | int pcsc_reader_do_api(struct s_reader *pcsc_reader, uchar *buf, uchar *cta_res, ushort *cta_lr, int l, int dbg)
|
---|
82 | {
|
---|
83 | ULONG rv;
|
---|
84 | SCARD_IO_REQUEST pioRecvPci;
|
---|
85 | DWORD dwSendLength, dwRecvLength;
|
---|
86 | if(buf[4])
|
---|
87 | dwSendLength = l;
|
---|
88 | else
|
---|
89 | dwSendLength = l-1;
|
---|
90 |
|
---|
91 | dwRecvLength = CTA_RES_LEN;
|
---|
92 | cs_debug("sending %d bytes to PCSC", dwSendLength);
|
---|
93 |
|
---|
94 | if(pcsc_reader->dwActiveProtocol == SCARD_PROTOCOL_T0) {
|
---|
95 | rv = SCardTransmit(pcsc_reader->hCard, SCARD_PCI_T0, buf, dwSendLength, &pioRecvPci, cta_res, &dwRecvLength);
|
---|
96 | }
|
---|
97 | else if(pcsc_reader->dwActiveProtocol == SCARD_PROTOCOL_T1) {
|
---|
98 | rv = SCardTransmit(pcsc_reader->hCard, SCARD_PCI_T1, buf, dwSendLength, &pioRecvPci, cta_res, &dwRecvLength);
|
---|
99 | }
|
---|
100 | else {
|
---|
101 | cs_debug("PCSC invalid protocol (T=%d)", pcsc_reader->dwActiveProtocol);
|
---|
102 | return ERR_INVALID;
|
---|
103 | }
|
---|
104 |
|
---|
105 | *cta_lr=dwRecvLength;
|
---|
106 | cs_debug("received %d bytes from PCSC with rv=%lx", *cta_lr, rv);
|
---|
107 |
|
---|
108 | cs_debug("PCSC doapi (%lx ) (T=%d), %d", rv, ( pcsc_reader->dwActiveProtocol == SCARD_PROTOCOL_T0 ? 0 : 1), dwRecvLength );
|
---|
109 | if ( rv == SCARD_S_SUCCESS ){
|
---|
110 | return OK;
|
---|
111 | }
|
---|
112 | else {
|
---|
113 | return ERR_INVALID;
|
---|
114 | }
|
---|
115 |
|
---|
116 | }
|
---|
117 |
|
---|
118 | int pcsc_activate_card(struct s_reader *pcsc_reader, uchar *atr, ushort *atr_size)
|
---|
119 | {
|
---|
120 | ULONG rv;
|
---|
121 | DWORD dwState, dwAtrLen, dwReaderLen;
|
---|
122 | BYTE pbAtr[64];
|
---|
123 |
|
---|
124 | cs_debug("PCSC initializing card in (%s)", pcsc_reader->pcsc_name);
|
---|
125 | dwAtrLen = sizeof(pbAtr);
|
---|
126 | dwReaderLen=0;
|
---|
127 |
|
---|
128 | cs_debug("PCSC resetting card in (%s)", pcsc_reader->pcsc_name);
|
---|
129 | rv = SCardReconnect(pcsc_reader->hCard, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, SCARD_RESET_CARD, &pcsc_reader->dwActiveProtocol);
|
---|
130 | cs_debug("PCSC resetting done on card in (%s)", pcsc_reader->pcsc_name);
|
---|
131 | cs_debug("PCSC Protocol (T=%d)",( pcsc_reader->dwActiveProtocol == SCARD_PROTOCOL_T0 ? 0 : 1));
|
---|
132 |
|
---|
133 | if ( rv != SCARD_S_SUCCESS ) {
|
---|
134 | cs_debug("Error PCSC failed to reset card (%lx)", rv);
|
---|
135 | return(0);
|
---|
136 | }
|
---|
137 |
|
---|
138 |
|
---|
139 | cs_debug("PCSC getting ATR for card in (%s)", pcsc_reader->pcsc_name);
|
---|
140 | rv = SCardStatus(pcsc_reader->hCard,NULL, &dwReaderLen, &dwState, &pcsc_reader->dwActiveProtocol, pbAtr, &dwAtrLen);
|
---|
141 | if ( rv == SCARD_S_SUCCESS ) {
|
---|
142 | cs_debug("PCSC Protocol (T=%d)",( pcsc_reader->dwActiveProtocol == SCARD_PROTOCOL_T0 ? 0 : 1));
|
---|
143 | memcpy(atr, pbAtr, dwAtrLen);
|
---|
144 | *atr_size=dwAtrLen;
|
---|
145 | #ifdef CS_RDR_INIT_HIST
|
---|
146 | pcsc_reader->init_history_pos=0;
|
---|
147 | memset(pcsc_reader->init_history, 0, sizeof(pcsc_reader->init_history));
|
---|
148 | #endif
|
---|
149 | cs_ri_log("ATR: %s", cs_hexdump(1, (uchar *)pbAtr, dwAtrLen));
|
---|
150 | return(1);
|
---|
151 | }
|
---|
152 | else {
|
---|
153 | cs_debug("Error PCSC failed to get ATR for card (%lx)", rv);
|
---|
154 | }
|
---|
155 |
|
---|
156 | return(0);
|
---|
157 | }
|
---|
158 |
|
---|
159 |
|
---|
160 | int pcsc_check_card_inserted(struct s_reader *pcsc_reader)
|
---|
161 | {
|
---|
162 | DWORD dwState, dwAtrLen, dwReaderLen;
|
---|
163 | BYTE pbAtr[64];
|
---|
164 | ULONG rv;
|
---|
165 |
|
---|
166 | dwAtrLen = sizeof(pbAtr);
|
---|
167 | rv=0;
|
---|
168 | dwState=0;
|
---|
169 | dwReaderLen=0;
|
---|
170 |
|
---|
171 | // Do we have a card ?
|
---|
172 | if (!pcsc_reader->pcsc_has_card && !pcsc_reader->hCard) {
|
---|
173 | // try connecting to the card
|
---|
174 | rv = SCardConnect(pcsc_reader->hContext, pcsc_reader->pcsc_name, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &pcsc_reader->hCard, &pcsc_reader->dwActiveProtocol);
|
---|
175 | if (rv==SCARD_E_NO_SMARTCARD) {
|
---|
176 | // no card in reader
|
---|
177 | pcsc_reader->pcsc_has_card=0;
|
---|
178 | if(pcsc_reader->hCard) {
|
---|
179 | SCardDisconnect(pcsc_reader->hCard,SCARD_RESET_CARD);
|
---|
180 | pcsc_reader->hCard=0;
|
---|
181 | }
|
---|
182 | cs_debug("PCSC card in %s removed / absent [dwstate=%lx rv=(%lx)]", pcsc_reader->pcsc_name, dwState, rv );
|
---|
183 | return 0;
|
---|
184 | }
|
---|
185 | else if( rv == SCARD_W_UNRESPONSIVE_CARD ) {
|
---|
186 | // there is a problem with the card in the reader
|
---|
187 | pcsc_reader->pcsc_has_card=0;
|
---|
188 | pcsc_reader->hCard=0;
|
---|
189 | cs_log("PCSC card in %s is unresponsive. Eject and re-insert please.", pcsc_reader->pcsc_name);
|
---|
190 | return 0;
|
---|
191 | }
|
---|
192 | else if( rv == SCARD_S_SUCCESS ) {
|
---|
193 | // we have a card
|
---|
194 | pcsc_reader->pcsc_has_card=1;
|
---|
195 | }
|
---|
196 | else {
|
---|
197 | // if we get here we have a bigger problem -> display status and debug
|
---|
198 | cs_debug("PCSC reader %s status [dwstate=%lx rv=(%lx)]", pcsc_reader->pcsc_name, dwState, rv );
|
---|
199 | return 0;
|
---|
200 | }
|
---|
201 |
|
---|
202 | }
|
---|
203 |
|
---|
204 | // if we get there the card is ready, check its status
|
---|
205 | rv = SCardStatus(pcsc_reader->hCard, NULL, &dwReaderLen, &dwState, &pcsc_reader->dwActiveProtocol, pbAtr, &dwAtrLen);
|
---|
206 |
|
---|
207 | if (rv == SCARD_S_SUCCESS && (dwState & (SCARD_PRESENT | SCARD_NEGOTIABLE | SCARD_POWERED ) )) {
|
---|
208 | cs_debug("PCSC card IS inserted in %s card state [dwstate=%lx rv=(%lx)]", pcsc_reader->pcsc_name, dwState,rv);
|
---|
209 | return CARD_INSERTED;
|
---|
210 | }
|
---|
211 | else {
|
---|
212 | SCardDisconnect(pcsc_reader->hCard,SCARD_RESET_CARD);
|
---|
213 | pcsc_reader->hCard=0;
|
---|
214 | pcsc_reader->pcsc_has_card=0;
|
---|
215 | cs_debug("PCSC card in %s removed / absent [dwstate=%lx rv=(%lx)]", pcsc_reader->pcsc_name, dwState, rv );
|
---|
216 | }
|
---|
217 |
|
---|
218 | return 0;
|
---|
219 | }
|
---|
220 | #endif
|
---|
221 |
|
---|