]> cvs.zerfleddert.de Git - proxmark3-svn/blob - client/pcsc.c
7d03d05212085b161e912c2cefe4a914bc0f0e6f
[proxmark3-svn] / client / pcsc.c
1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2019 piwi
3 //
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
6 // the license.
7 //-----------------------------------------------------------------------------
8 // PCSC functions to use alternative Smartcard Readers
9 //-----------------------------------------------------------------------------
10
11 #include "pcsc.h"
12
13 #include <stdlib.h>
14 #include <stdbool.h>
15 #include <stdio.h>
16 #include <string.h>
17
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)
25 #include <winscard.h>
26 #else
27 #include <winscard.h>
28 #include <reader.h>
29 #endif
30
31 #include "ui.h"
32 #include "util.h"
33 #include "cmdhw.h"
34
35 static SCARDCONTEXT SC_Context;
36 static SCARDHANDLE SC_Card;
37 static DWORD SC_Protocol;
38 static char* AlternativeSmartcardReader = NULL;
39
40
41 char *getAlternativeSmartcardReader(void)
42 {
43 return AlternativeSmartcardReader;
44 }
45
46
47 bool pcscCheckForCardReaders(void)
48 {
49 LONG res = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &SC_Context);
50 if (res != SCARD_S_SUCCESS) {
51 return false;
52 }
53
54 DWORD pcchReaders;
55 res = SCardListReaders(SC_Context, NULL, NULL, &pcchReaders);
56 if (res != SCARD_S_SUCCESS) {
57 SCardReleaseContext(SC_Context);
58 return false;
59 }
60
61 if (res == SCARD_E_NO_READERS_AVAILABLE || res == SCARD_E_NO_SERVICE) {
62 SCardReleaseContext(SC_Context);
63 return false;
64 }
65
66 return true;
67 }
68
69
70 static char *pickReader(LPTSTR readerlist)
71 {
72 PrintAndLogEx(NORMAL, "Please select one of these:");
73 PrintAndLogEx(NORMAL, " [0] PM3 RDV40 Smartcard Slot %s", PM3hasSmartcardSlot() ? "(default)" : "(default, not available)");
74
75 int num = 1;
76 for (LPTSTR p = readerlist; *p != '\0'; ) {
77 PrintAndLogEx(NORMAL, " [%1d] %s", num++, p);
78 while (*p++ != '\0') ; // advance to next entry
79 }
80
81 num--;
82
83 if (num == 1) {
84 printf("Your choice (0 or 1)?");
85 } else {
86 printf("Your choice (0...%d)? ", num);
87 }
88 int selection = getch() - '0';
89 printf("\n");
90
91 if (selection == 0) {
92 PrintAndLogEx(INFO, "Selected RDV40 Smartcard Slot");
93 return NULL;
94 }
95
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
100 }
101 PrintAndLogEx(INFO, "Selected %s", p);
102 return p;
103 }
104
105 PrintAndLogEx(INFO, "Invalid selection. Using RDV40 Smartcard Slot");
106 return NULL;
107
108 }
109
110
111 char *matchString(LPTSTR readerlist, const char *readername)
112 {
113 return pickReader(readerlist);
114 }
115
116
117 bool pcscSelectAlternativeCardReader(const char *readername)
118 {
119 DWORD readerlist_len;
120 LONG res = SCardListReaders(SC_Context, NULL, NULL, &readerlist_len);
121 if (res != SCARD_S_SUCCESS) {
122 return false;
123 }
124
125 LPTSTR readerlist = calloc(readerlist_len, sizeof(char));
126 res = SCardListReaders(SC_Context, NULL, readerlist, &readerlist_len);
127 if (res != SCARD_S_SUCCESS) {
128 free(readerlist);
129 return false;
130 }
131
132 char *selected_readername = NULL;
133 if (readername) {
134 selected_readername = matchString(readerlist, readername);
135 } else {
136 selected_readername = pickReader(readerlist);
137 }
138
139 if (selected_readername == NULL) {
140 free(readerlist);
141 return false;
142 }
143
144 free(AlternativeSmartcardReader);
145 AlternativeSmartcardReader = malloc((strlen(selected_readername) + 1) * sizeof(char));
146 strcpy(AlternativeSmartcardReader, selected_readername);
147
148 return true;
149 }
150
151
152 bool pcscGetATR(smart_card_atr_t *card)
153 {
154 if (!card) {
155 return false;
156 }
157
158 card->atr_len = 0;
159 memset(card->atr, 0, sizeof(card->atr));
160
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) {
164 return false;
165 }
166
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) {
170 return false;
171 }
172 card->atr_len = atr_len;
173
174 // TODO: LogTrace without device
175
176 return true;
177 }
178
179
180 void pcscTransmit(uint8_t *data, uint32_t data_len, uint32_t flags, uint8_t *response, int *response_len)
181 {
182 LPCSCARD_IO_REQUEST protocol;
183 if (flags & SC_RAW_T0) {
184 protocol = SCARD_PCI_T0;
185 } else {
186 protocol = SCARD_PCI_RAW;
187 }
188
189 // TODO: tracing
190 // if ((flags & SC_CONNECT))
191 // clear_trace();
192
193 // set_tracing(true);
194
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) {
199 *response_len = -1;
200 return;
201 }
202 }
203
204 if ((flags & SC_RAW) || (flags & SC_RAW_T0)) {
205 // TODO: tracing
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) {
210 *response_len = -1;
211 } else {
212 *response_len = len;
213 }
214 }
215 }
Impressum, Datenschutz