1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2019 piwi
4 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
5 // at your option, any later version. See the LICENSE.txt file for the text of
7 //-----------------------------------------------------------------------------
8 // PCSC functions to use alternative Smartcard Readers
9 //-----------------------------------------------------------------------------
18 #if defined (__APPLE__)
19 #include <PCSC/winscard.h>
20 #include <PCSC/wintypes.h>
21 #define SCARD_ATTR_VALUE(Class, Tag) ((((ULONG)(Class)) << 16) | ((ULONG)(Tag)))
22 #define SCARD_CLASS_ICC_STATE 9
23 #define SCARD_ATTR_ATR_STRING SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0303)
24 #elif defined (_WIN32)
35 static SCARDCONTEXT SC_Context
;
36 static SCARDHANDLE SC_Card
;
37 static DWORD SC_Protocol
;
38 static char* AlternativeSmartcardReader
= NULL
;
41 char *getAlternativeSmartcardReader(void)
43 return AlternativeSmartcardReader
;
47 bool pcscCheckForCardReaders(void)
49 LONG res
= SCardEstablishContext(SCARD_SCOPE_SYSTEM
, NULL
, NULL
, &SC_Context
);
50 if (res
!= SCARD_S_SUCCESS
) {
55 res
= SCardListReaders(SC_Context
, NULL
, NULL
, &pcchReaders
);
56 if (res
!= SCARD_S_SUCCESS
) {
57 SCardReleaseContext(SC_Context
);
61 if (res
== SCARD_E_NO_READERS_AVAILABLE
|| res
== SCARD_E_NO_SERVICE
) {
62 SCardReleaseContext(SC_Context
);
70 static char *pickReader(LPTSTR readerlist
)
72 PrintAndLogEx(NORMAL
, "Please select one of these:");
73 PrintAndLogEx(NORMAL
, " [0] PM3 RDV40 Smartcard Slot %s", PM3hasSmartcardSlot() ? "(default)" : "(default, not available)");
76 for (LPTSTR p
= readerlist
; *p
!= '\0'; ) {
77 PrintAndLogEx(NORMAL
, " [%1d] %s", num
++, p
);
78 while (*p
++ != '\0') ; // advance to next entry
84 printf("Your choice (0 or 1)?");
86 printf("Your choice (0...%d)? ", num
);
88 int selection
= getch() - '0';
92 PrintAndLogEx(INFO
, "Selected RDV40 Smartcard Slot");
96 if (selection
>= 1 && selection
<= num
) {
97 LPTSTR p
= readerlist
;
98 for (int i
= 1; i
< selection
; i
++) {
99 while (*p
++ != '\0') ; // advance to next entry
101 PrintAndLogEx(INFO
, "Selected %s", p
);
105 PrintAndLogEx(INFO
, "Invalid selection. Using RDV40 Smartcard Slot");
111 char *matchString(LPTSTR readerlist
, const char *readername
)
113 return pickReader(readerlist
);
117 bool pcscSelectAlternativeCardReader(const char *readername
)
119 DWORD readerlist_len
;
120 LONG res
= SCardListReaders(SC_Context
, NULL
, NULL
, &readerlist_len
);
121 if (res
!= SCARD_S_SUCCESS
) {
125 LPTSTR readerlist
= calloc(readerlist_len
, sizeof(char));
126 res
= SCardListReaders(SC_Context
, NULL
, readerlist
, &readerlist_len
);
127 if (res
!= SCARD_S_SUCCESS
) {
132 char *selected_readername
= NULL
;
134 selected_readername
= matchString(readerlist
, readername
);
136 selected_readername
= pickReader(readerlist
);
139 if (selected_readername
== NULL
) {
144 free(AlternativeSmartcardReader
);
145 AlternativeSmartcardReader
= malloc((strlen(selected_readername
) + 1) * sizeof(char));
146 strcpy(AlternativeSmartcardReader
, selected_readername
);
152 bool pcscGetATR(smart_card_atr_t
*card
)
159 memset(card
->atr
, 0, sizeof(card
->atr
));
161 LONG res
= SCardConnect(SC_Context
, AlternativeSmartcardReader
, SCARD_SHARE_SHARED
,
162 SCARD_PROTOCOL_T0
| SCARD_PROTOCOL_T1
, &SC_Card
, &SC_Protocol
);
163 if (res
!= SCARD_S_SUCCESS
) {
167 DWORD atr_len
= sizeof(card
->atr
);
168 res
= SCardGetAttrib(SC_Card
, SCARD_ATTR_ATR_STRING
, card
->atr
, &atr_len
);
169 if (res
!= SCARD_S_SUCCESS
) {
172 card
->atr_len
= atr_len
;
174 // TODO: LogTrace without device
180 void pcscTransmit(uint8_t *data
, uint32_t data_len
, uint32_t flags
, uint8_t *response
, int *response_len
)
182 LPCSCARD_IO_REQUEST protocol
;
183 if (flags
& SC_RAW_T0
) {
184 protocol
= SCARD_PCI_T0
;
186 protocol
= SCARD_PCI_RAW
;
190 // if ((flags & SC_CONNECT))
193 // set_tracing(true);
195 if ((flags
& SC_CONNECT
|| flags
& SC_SELECT
)) {
196 LONG res
= SCardConnect(SC_Context
, AlternativeSmartcardReader
, SCARD_SHARE_SHARED
,
197 SCARD_PROTOCOL_T0
| SCARD_PROTOCOL_T1
, &SC_Card
, &SC_Protocol
);
198 if (res
!= SCARD_S_SUCCESS
) {
204 if ((flags
& SC_RAW
) || (flags
& SC_RAW_T0
)) {
206 // LogTrace(data, arg1, 0, 0, NULL, true);
207 DWORD len
= *response_len
;
208 LONG res
= SCardTransmit(SC_Card
, protocol
, data
, data_len
, NULL
, response
, &len
);
209 if (res
!= SCARD_S_SUCCESS
) {