- fix Building without Nagra not possible at Nagra_Merlin https://trac.streamboard...
[oscam.git] / csctapi / ifd_pcsc.c
blobb8f77ffe4b9c7aa2e8ff7ec1e29d70c4b245b084
1 #include "../globals.h"
3 #ifdef CARDREADER_PCSC
5 #include "atr.h"
6 #include "../oscam-string.h"
8 #if defined(__CYGWIN__)
9 #define __reserved
10 #define __nullnullterminated
11 #include <specstrings.h>
12 #include <WinSCard.h>
13 #endif
15 #if !defined(__CYGWIN__)
16 #if !defined(__APPLE__)
17 #include <PCSC/pcsclite.h>
18 #include <PCSC/winscard.h>
19 #include <PCSC/wintypes.h>
20 #include <PCSC/reader.h>
21 #endif
22 #endif
24 #if defined(__APPLE__)
25 #include "pcsclite.h"
26 #include "winscard.h"
27 #include "wintypes.h"
28 #include "reader.h"
29 #endif
31 #ifndef ERR_INVALID
32 #define ERR_INVALID -1
33 #endif
35 #if defined(__CYGWIN__)
36 #undef OK
37 #undef ERROR
38 #undef LOBYTE
39 #undef HIBYTE
40 #endif
42 #define OK 0
43 #define ERROR 1
45 struct pcsc_data
47 bool pcsc_has_card;
48 char pcsc_name[128];
49 SCARDCONTEXT hContext;
50 SCARDHANDLE hCard;
51 DWORD dwActiveProtocol;
54 static int32_t pcsc_init(struct s_reader *pcsc_reader)
56 ULONG rv;
57 DWORD dwReaders = 0;
58 LPSTR mszReaders = NULL;
59 char *ptr, **readers = NULL;
60 char *device = pcsc_reader->device;
61 int32_t nbReaders;
62 int32_t reader_nb;
64 rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC establish context for PCSC pcsc_reader %s", device);
65 SCARDCONTEXT hContext;
66 memset(&hContext, 0, sizeof(hContext));
67 rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
68 if(rv == SCARD_S_SUCCESS)
70 if(!cs_malloc(&pcsc_reader->crdr_data, sizeof(struct pcsc_data)))
71 { return ERROR; }
72 struct pcsc_data *crdr_data = pcsc_reader->crdr_data;
73 crdr_data->hContext = hContext;
75 // here we need to list the pcsc readers and get the name from there,
76 // the pcsc_reader->device should contain the pcsc_reader number
77 // and after the actual device name is copied in crdr_data->pcsc_name .
78 rv = SCardListReaders(crdr_data->hContext, NULL, NULL, &dwReaders);
79 if(rv != SCARD_S_SUCCESS)
81 rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC failed listing readers [1] : (%lx)", (unsigned long)rv);
82 return ERROR;
84 if(!cs_malloc(&mszReaders, dwReaders))
85 { return ERROR; }
86 rv = SCardListReaders(crdr_data->hContext, NULL, mszReaders, &dwReaders);
87 if(rv != SCARD_S_SUCCESS)
89 rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC failed listing readers [2]: (%lx)", (unsigned long)rv);
90 NULLFREE(mszReaders);
91 return ERROR;
93 /* Extract readers from the null separated string and get the total
94 * number of readers
96 nbReaders = 0;
97 ptr = mszReaders;
98 while(*ptr != '\0')
100 ptr += cs_strlen(ptr) + 1;
101 nbReaders++;
104 if(nbReaders == 0)
106 rdr_log(pcsc_reader, "PCSC : no pcsc_reader found");
107 NULLFREE(mszReaders);
108 return ERROR;
111 if(!cs_malloc(&readers, nbReaders * sizeof(char *)))
113 NULLFREE(mszReaders);
114 return ERROR;
117 char* device_line;
118 char* device_first;
119 char* device_second;
121 device_line = strdup((const char *)&pcsc_reader->device);
122 device_first = strsep(&device_line, ":");
123 device_second = strsep(&device_line, ":");
124 reader_nb = atoi(device_first);
126 /* fill the readers table */
127 nbReaders = 0;
128 ptr = mszReaders;
129 while(*ptr != '\0')
131 rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC pcsc_reader %d: %s", nbReaders, ptr);
132 readers[nbReaders] = ptr;
133 if ((reader_nb == -1) && (device_second != NULL) && strstr(ptr,device_second)){
134 reader_nb = nbReaders;
136 ptr += cs_strlen(ptr) + 1;
137 nbReaders++;
140 if(reader_nb < 0 || reader_nb >= nbReaders)
142 rdr_log(pcsc_reader, "Wrong pcsc_reader index: %d", reader_nb);
143 NULLFREE(mszReaders);
144 NULLFREE(readers);
145 NULLFREE(device_line);
146 return ERROR;
149 if (readers)
151 snprintf(crdr_data->pcsc_name, sizeof(crdr_data->pcsc_name), "%s", readers[reader_nb]);
152 NULLFREE(readers);
154 NULLFREE(mszReaders);
155 NULLFREE(device_line);
157 else
159 rdr_log(pcsc_reader, "PCSC failed establish context (%lx)", (unsigned long)rv);
160 return ERROR;
162 return OK;
165 static int32_t pcsc_do_api(struct s_reader *pcsc_reader, const uint8_t *buf, uint8_t *cta_res, uint16_t *cta_lr, int32_t l)
167 LONG rv;
168 DWORD dwSendLength, dwRecvLength;
170 *cta_lr = 0;
171 if(!l)
173 rdr_log(pcsc_reader, "ERROR: Data length to be send to the pcsc_reader is %d", l);
174 return ERROR;
177 char tmp[l * 3];
178 dwRecvLength = CTA_RES_LEN;
180 struct pcsc_data *crdr_data = pcsc_reader->crdr_data;
181 if(crdr_data->dwActiveProtocol == SCARD_PROTOCOL_T0)
183 // explanantion as to why we do the test on buf[4] :
184 // Issuing a command without exchanging data :
185 //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.
186 //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.)
187 //The cbSendLength parameter must be set to four, the size of the T=0 header information (CLA, INS, P1, and P2).
188 //The pbRecvBuffer will receive the SW1 and SW2 status codes from the operation.
189 //The pcbRecvLength should be at least two and will be set to two upon return.
190 if(buf[4])
191 { dwSendLength = l; }
192 else
193 { dwSendLength = l - 1; }
194 rdr_log_dbg(pcsc_reader, D_DEVICE, "sending %lu bytes to PCSC : %s", (unsigned long)dwSendLength, cs_hexdump(1, buf, l, tmp, sizeof(tmp)));
195 rv = SCardTransmit(crdr_data->hCard, SCARD_PCI_T0, (LPCBYTE) buf, dwSendLength, NULL, (LPBYTE) cta_res, (LPDWORD) &dwRecvLength);
196 *cta_lr = dwRecvLength;
198 else if(crdr_data->dwActiveProtocol == SCARD_PROTOCOL_T1)
200 dwSendLength = l;
201 rdr_log_dbg(pcsc_reader, D_DEVICE, "sending %lu bytes to PCSC : %s", (unsigned long)dwSendLength, cs_hexdump(1, buf, l, tmp, sizeof(tmp)));
202 rv = SCardTransmit(crdr_data->hCard, SCARD_PCI_T1, (LPCBYTE) buf, dwSendLength, NULL, (LPBYTE) cta_res, (LPDWORD) &dwRecvLength);
203 *cta_lr = dwRecvLength;
205 else
207 rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC invalid protocol (T=%lu)", (unsigned long)crdr_data->dwActiveProtocol);
208 return ERROR;
211 rdr_log_dbg(pcsc_reader, D_DEVICE, "received %d bytes from PCSC with rv=%lx : %s", *cta_lr, (unsigned long)rv, cs_hexdump(1, cta_res, *cta_lr, tmp, sizeof(tmp)));
213 rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC doapi (%lx ) (T=%d), %d", (unsigned long)rv, (crdr_data->dwActiveProtocol == SCARD_PROTOCOL_T0 ? 0 : 1), *cta_lr);
215 if(rv == SCARD_S_SUCCESS)
217 return OK;
219 else
221 return ERROR;
226 static int32_t pcsc_activate_card(struct s_reader *pcsc_reader, uint8_t *atr, uint16_t *atr_size)
228 struct pcsc_data *crdr_data = pcsc_reader->crdr_data;
229 LONG rv;
230 DWORD dwState, dwAtrLen, dwReaderLen;
231 unsigned char pbAtr[ATR_MAX_SIZE];
232 char tmp[sizeof(pbAtr) * 3 + 1];
234 rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC initializing card in (%s)", crdr_data->pcsc_name);
235 dwAtrLen = sizeof(pbAtr);
236 dwReaderLen = 0;
238 rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC resetting card in (%s) with handle %ld", crdr_data->pcsc_name, (long)(crdr_data->hCard));
239 rv = SCardReconnect(crdr_data->hCard, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, SCARD_RESET_CARD, &crdr_data->dwActiveProtocol);
241 if(rv != SCARD_S_SUCCESS)
243 rdr_log_dbg(pcsc_reader, D_DEVICE, "ERROR: PCSC failed to reset card (%lx)", (unsigned long)rv);
244 return ERROR;
247 rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC resetting done on card in (%s)", crdr_data->pcsc_name);
248 rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC Protocol (T=%d)", (crdr_data->dwActiveProtocol == SCARD_PROTOCOL_T0 ? 0 : 1));
250 rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC getting ATR for card in (%s)", crdr_data->pcsc_name);
251 rv = SCardStatus(crdr_data->hCard, NULL, &dwReaderLen, &dwState, &crdr_data->dwActiveProtocol, pbAtr, &dwAtrLen);
252 if(rv == SCARD_S_SUCCESS)
254 rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC Protocol (T=%d)", (crdr_data->dwActiveProtocol == SCARD_PROTOCOL_T0 ? 0 : 1));
255 memcpy(atr, pbAtr, dwAtrLen);
256 *atr_size = dwAtrLen;
258 rdr_log(pcsc_reader, "ATR: %s", cs_hexdump(1, (uint8_t *)pbAtr, dwAtrLen, tmp, sizeof(tmp)));
259 memcpy(pcsc_reader->card_atr, pbAtr, dwAtrLen);
260 pcsc_reader->card_atr_length = dwAtrLen;
261 return OK;
263 else
265 rdr_log_dbg(pcsc_reader, D_DEVICE, "ERROR: PCSC failed to get ATR for card (%lx)", (unsigned long)rv);
268 return ERROR;
271 static int32_t pcsc_activate(struct s_reader *reader, struct s_ATR *atr)
273 unsigned char atrarr[ATR_MAX_SIZE];
274 uint16_t atr_size = 0;
275 if(pcsc_activate_card(reader, atrarr, &atr_size) == OK)
277 if(ATR_InitFromArray(atr, atrarr, atr_size) != ERROR) // ATR is OK or softfail malformed
278 { return OK; }
279 else
280 { return ERROR; }
282 else
283 { return ERROR; }
286 static int32_t pcsc_check_card_inserted(struct s_reader *pcsc_reader)
288 struct pcsc_data *crdr_data = pcsc_reader->crdr_data;
289 DWORD dwState, dwAtrLen, dwReaderLen;
290 unsigned char pbAtr[64];
291 SCARDHANDLE rv;
293 dwAtrLen = sizeof(pbAtr);
294 rv = 0;
295 dwState = 0;
296 dwReaderLen = 0;
298 // Do we have a card ?
299 if(!crdr_data->pcsc_has_card && !crdr_data->hCard)
301 // try connecting to the card
302 rv = SCardConnect(crdr_data->hContext, crdr_data->pcsc_name, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &crdr_data->hCard, &crdr_data->dwActiveProtocol);
303 if(rv == (SCARDHANDLE)SCARD_E_NO_SMARTCARD)
305 // no card in pcsc_reader
306 crdr_data->pcsc_has_card = 0;
307 if(crdr_data->hCard)
309 SCardDisconnect(crdr_data->hCard, SCARD_RESET_CARD);
310 crdr_data->hCard = 0;
312 // rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC card in %s removed / absent [dwstate=%lx rv=(%lx)]", crdr_data->pcsc_name, dwState, (unsigned long)rv );
313 return OK;
315 else if(rv == (SCARDHANDLE)SCARD_W_UNRESPONSIVE_CARD)
317 // there is a problem with the card in the pcsc_reader
318 crdr_data->pcsc_has_card = 0;
319 crdr_data->hCard = 0;
320 rdr_log(pcsc_reader, "PCSC card in %s is unresponsive. Eject and re-insert please.", crdr_data->pcsc_name);
321 return ERROR;
323 else if(rv == SCARD_S_SUCCESS)
325 // we have a card
326 crdr_data->pcsc_has_card = 1;
327 rdr_log(pcsc_reader, "PCSC was opened with handle: %ld", (long)crdr_data->hCard);
329 else
331 // if we get here we have a bigger problem -> display status and debug
332 // rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC pcsc_reader %s status [dwstate=%lx rv=(%lx)]", crdr_data->pcsc_name, dwState, (unsigned long)rv );
333 return ERROR;
338 // if we get there the card is ready, check its status
339 rv = SCardStatus(crdr_data->hCard, NULL, &dwReaderLen, &dwState, &crdr_data->dwActiveProtocol, pbAtr, &dwAtrLen);
341 if(rv == SCARD_S_SUCCESS && (dwState & (SCARD_PRESENT | SCARD_NEGOTIABLE | SCARD_POWERED)))
343 return OK;
345 else
347 SCardDisconnect(crdr_data->hCard, SCARD_RESET_CARD);
348 crdr_data->hCard = 0;
349 crdr_data->pcsc_has_card = 0;
352 return ERROR;
355 static int32_t pcsc_get_status(struct s_reader *reader, int32_t *in)
357 struct pcsc_data *crdr_data = reader->crdr_data;
358 int32_t ret = pcsc_check_card_inserted(reader);
359 *in = crdr_data->pcsc_has_card;
360 return ret;
363 static int32_t pcsc_close(struct s_reader *pcsc_reader)
365 struct pcsc_data *crdr_data = pcsc_reader->crdr_data;
366 rdr_log_dbg(pcsc_reader, D_IFD, "PCSC : Closing device %s", pcsc_reader->device);
367 SCardDisconnect(crdr_data->hCard, SCARD_LEAVE_CARD);
368 SCardReleaseContext(crdr_data->hContext);
369 return OK;
372 const struct s_cardreader cardreader_pcsc =
374 .desc = "pcsc",
375 .typ = R_PCSC,
376 .skip_extra_atr_parsing = 1,
377 .skip_t1_command_retries = 1,
378 .skip_setting_ifsc = 1,
379 .reader_init = pcsc_init,
380 .get_status = pcsc_get_status,
381 .activate = pcsc_activate,
382 .card_write = pcsc_do_api,
383 .close = pcsc_close,
386 #endif