]> git.zerfleddert.de Git - proxmark3-svn/blame - client/pcsc.c
Adding support for standard USB Smartcard Readers (#769)
[proxmark3-svn] / client / pcsc.c
CommitLineData
a9104f7e 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
35static SCARDCONTEXT SC_Context;
36static SCARDHANDLE SC_Card;
37static DWORD SC_Protocol;
38static char* AlternativeSmartcardReader = NULL;
39
40
41char *getAlternativeSmartcardReader(void)
42{
43 return AlternativeSmartcardReader;
44}
45
46
47bool 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
70static 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
111char *matchString(LPTSTR readerlist, const char *readername)
112{
113 return pickReader(readerlist);
114}
115
116
117bool 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
152bool 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}
6b5105be 178
179
180void 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