pcsc-lite 1.9.9
testpcsc.c
Go to the documentation of this file.
1/*
2 * MUSCLE SmartCard Development ( https://pcsclite.apdu.fr/ )
3 *
4 * Copyright (C) 1999
5 * David Corcoran <corcoran@musclecard.com>
6 * Copyright (C) 2004-2010
7 * Ludovic Rousseau <ludovic.rousseau@free.fr>
8 *
9Redistribution and use in source and binary forms, with or without
10modification, are permitted provided that the following conditions
11are met:
12
131. Redistributions of source code must retain the above copyright
14 notice, this list of conditions and the following disclaimer.
152. Redistributions in binary form must reproduce the above copyright
16 notice, this list of conditions and the following disclaimer in the
17 documentation and/or other materials provided with the distribution.
183. The name of the author may not be used to endorse or promote products
19 derived from this software without specific prior written permission.
20
21THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
38#include "config.h"
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42
43#include "pcsclite.h"
44#include "winscard.h"
45#include "reader.h"
46
47#define PANIC 0
48#define DONT_PANIC 1
49
50#define USE_AUTOALLOCATE
51
52#define BLUE "\33[34m"
53#define RED "\33[31m"
54#define BRIGHT_RED "\33[01;31m"
55#define GREEN "\33[32m"
56#define NORMAL "\33[0m"
57#define MAGENTA "\33[35m"
58
59static void test_rv(LONG rv, SCARDCONTEXT hContext, int dont_panic)
60{
61 if (rv != SCARD_S_SUCCESS)
62 {
63 if (dont_panic)
64 printf(BLUE "%s (don't panic)\n" NORMAL, pcsc_stringify_error(rv));
65 else
66 {
67 printf(RED "%s\n" NORMAL, pcsc_stringify_error(rv));
68 (void)SCardReleaseContext(hContext);
69 exit(-1);
70 }
71 }
72 else
73 (void)puts(pcsc_stringify_error(rv));
74}
75
76int main(/*@unused@*/ int argc, /*@unused@*/ char **argv)
77{
78 SCARDHANDLE hCard;
79 SCARDCONTEXT hContext;
80 SCARD_READERSTATE rgReaderStates[1];
81 DWORD dwReaderLen, dwState, dwProt, dwAtrLen;
82 DWORD dwPref, dwReaders = 0;
83 char *pcReader = NULL, *mszReaders;
84#ifdef USE_AUTOALLOCATE
85 unsigned char *pbAtr = NULL;
86#else
87 unsigned char pbAtr[MAX_ATR_SIZE];
88#endif
89 union {
90 unsigned char as_char[100];
91 DWORD as_DWORD;
92 uint32_t as_uint32_t;
93 } buf;
94 DWORD dwBufLen;
95 unsigned char *pbAttr = NULL;
96 DWORD pcbAttrLen;
97 char *mszGroups;
98 DWORD dwGroups = 0;
99 long rv;
100 DWORD i;
101 int p, iReader;
102 int iList[16] = {0};
103 SCARD_IO_REQUEST ioRecvPci = *SCARD_PCI_T0; /* use a default value */
104 const SCARD_IO_REQUEST *pioSendPci;
105 unsigned char bSendBuffer[MAX_BUFFER_SIZE];
106 unsigned char bRecvBuffer[MAX_BUFFER_SIZE];
107 DWORD send_length, length;
108
109 (void)argc;
110 (void)argv;
111
112 printf("\nMUSCLE PC/SC Lite unitary test Program\n\n");
113
114 printf(MAGENTA "THIS PROGRAM IS NOT DESIGNED AS A TESTING TOOL FOR END USERS!\n");
115 printf("Do NOT use it unless you really know what you do.\n\n" NORMAL);
116
117 printf("Testing SCardEstablishContext\t: ");
118 rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
119 test_rv(rv, hContext, PANIC);
120
121 printf("Testing SCardIsValidContext\t: ");
122 rv = SCardIsValidContext(hContext);
123 test_rv(rv, hContext, PANIC);
124
125 printf("Testing SCardIsValidContext\t: ");
126 rv = SCardIsValidContext(hContext+1);
127 test_rv(rv, hContext, DONT_PANIC);
128
129 printf("Testing SCardListReaderGroups\t: ");
130#ifdef USE_AUTOALLOCATE
131 dwGroups = SCARD_AUTOALLOCATE;
132 rv = SCardListReaderGroups(hContext, (LPSTR)&mszGroups, &dwGroups);
133#else
134 rv = SCardListReaderGroups(hContext, NULL, &dwGroups);
135 test_rv(rv, hContext, PANIC);
136
137 printf("Testing SCardListReaderGroups\t: ");
138 mszGroups = calloc(dwGroups, sizeof(char));
139 rv = SCardListReaderGroups(hContext, mszGroups, &dwGroups);
140#endif
141 test_rv(rv, hContext, PANIC);
142
143 /*
144 * Have to understand the multi-string here
145 */
146 p = 0;
147 for (i = 0; i+1 < dwGroups; i++)
148 {
149 ++p;
150 printf(GREEN "Group %02d: %s\n" NORMAL, p, &mszGroups[i]);
151 while (mszGroups[++i] != 0) ;
152 }
153
154#ifdef USE_AUTOALLOCATE
155 printf("Testing SCardFreeMemory\t\t: ");
156 rv = SCardFreeMemory(hContext, mszGroups);
157 test_rv(rv, hContext, PANIC);
158#else
159 free(mszGroups);
160#endif
161
162wait_for_card_again:
163 mszGroups = NULL;
164 printf("Testing SCardListReaders\t: ");
165 rv = SCardListReaders(hContext, mszGroups, NULL, &dwReaders);
166 test_rv(rv, hContext, DONT_PANIC);
168 {
169 printf("Testing SCardGetStatusChange \n");
170 printf("Please insert a working reader\t: ");
171 (void)fflush(stdout);
172 rgReaderStates[0].szReader = "\\\\?PnP?\\Notification";
173 rgReaderStates[0].dwCurrentState = SCARD_STATE_EMPTY;
174
175 rv = SCardGetStatusChange(hContext, INFINITE, rgReaderStates, 1);
176 test_rv(rv, hContext, PANIC);
177 }
178
179 printf("Testing SCardListReaders\t: ");
180#ifdef USE_AUTOALLOCATE
181 dwReaders = SCARD_AUTOALLOCATE;
182 rv = SCardListReaders(hContext, mszGroups, (LPSTR)&mszReaders, &dwReaders);
183#else
184 rv = SCardListReaders(hContext, mszGroups, NULL, &dwReaders);
185 test_rv(rv, hContext, PANIC);
186
187 printf("Testing SCardListReaders\t: ");
188 mszReaders = calloc(dwReaders, sizeof(char));
189 rv = SCardListReaders(hContext, mszGroups, mszReaders, &dwReaders);
190#endif
191 test_rv(rv, hContext, DONT_PANIC);
192
193 /*
194 * Have to understand the multi-string here
195 */
196 p = 0;
197 for (i = 0; i+1 < dwReaders; i++)
198 {
199 ++p;
200 printf(GREEN "Reader %02d: %s\n" NORMAL, p, &mszReaders[i]);
201 iList[p] = i;
202 while (mszReaders[++i] != 0) ;
203 }
204
205 if (p > 1)
206 {
207 int again = 0;
208
209 do
210 {
211 char input[80];
212 char *r;
213
214 printf("Enter the reader number\t\t: ");
215 r = fgets(input, sizeof(input), stdin);
216 if (NULL == r)
217 iReader = -1;
218 else
219 iReader = atoi(input);
220
221 if (iReader > p || iReader <= 0)
222 {
223 printf("Invalid Value - try again\n");
224 again = 1;
225 }
226 }
227 while (again);
228 }
229 else
230 iReader = 1;
231
232 rgReaderStates[0].szReader = &mszReaders[iList[iReader]];
233 rgReaderStates[0].dwCurrentState = SCARD_STATE_EMPTY;
234
235 printf("Waiting for card insertion\t: ");
236 (void)fflush(stdout);
237 rv = SCardGetStatusChange(hContext, INFINITE, rgReaderStates, 1);
238 test_rv(rv, hContext, PANIC);
239 if (rgReaderStates[0].dwEventState & SCARD_STATE_UNKNOWN)
240 {
241 printf("\nA reader has been connected/disconnected\n");
242 goto wait_for_card_again;
243 }
244
245 printf("Testing SCardConnect\t\t: ");
246 rv = SCardConnect(hContext, &mszReaders[iList[iReader]],
248 &hCard, &dwPref);
249 test_rv(rv, hContext, PANIC);
250
251 switch(dwPref)
252 {
254 pioSendPci = SCARD_PCI_T0;
255 break;
257 pioSendPci = SCARD_PCI_T1;
258 break;
260 pioSendPci = SCARD_PCI_RAW;
261 break;
262 default:
263 printf("Unknown protocol\n");
264 return -1;
265 }
266
267 /* APDU select file */
268 printf("Select file:");
269 send_length = 7;
270 memcpy(bSendBuffer, "\x00\xA4\x00\x00\x02\x3F\x00", send_length);
271 for (i=0; i<send_length; i++)
272 printf(" %02X", bSendBuffer[i]);
273 printf("\n");
274 length = sizeof(bRecvBuffer);
275
276 printf("Testing SCardTransmit\t\t: ");
277 rv = SCardTransmit(hCard, pioSendPci, bSendBuffer, send_length,
278 &ioRecvPci, bRecvBuffer, &length);
279 test_rv(rv, hContext, PANIC);
280 printf(" card response:" GREEN);
281 for (i=0; i<length; i++)
282 printf(" %02X", bRecvBuffer[i]);
283 printf("\n" NORMAL);
284
285 printf("Testing SCardControl\t\t: ");
286#ifdef PCSC_PRE_120
287 {
288 char buffer[1024] = "Foobar";
289 DWORD cbRecvLength = sizeof(buffer);
290
291 rv = SCardControl(hCard, buffer, 7, buffer, &cbRecvLength);
292 }
293#else
294 {
295 char buffer[1024] = { 0x02 };
296 DWORD cbRecvLength = sizeof(buffer);
297
298 rv = SCardControl(hCard, SCARD_CTL_CODE(1), buffer, 1, buffer,
299 sizeof(buffer), &cbRecvLength);
300 if (cbRecvLength && (SCARD_S_SUCCESS == rv))
301 {
302 for (i=0; i<cbRecvLength; i++)
303 printf("%c", buffer[i]);
304 printf(" ");
305 }
306 }
307#endif
308 test_rv(rv, hContext, DONT_PANIC);
309
310 printf("Testing SCardGetAttrib\t\t: ");
311#ifdef USE_AUTOALLOCATE
312 pcbAttrLen = SCARD_AUTOALLOCATE;
313 rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, (unsigned char *)&pbAttr,
314 &pcbAttrLen);
315#else
316 rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, NULL, &pcbAttrLen);
317 test_rv(rv, hContext, DONT_PANIC);
318 if (rv == SCARD_S_SUCCESS)
319 {
320 printf("SCARD_ATTR_DEVICE_FRIENDLY_NAME length: " GREEN "%ld\n" NORMAL, pcbAttrLen);
321 pbAttr = malloc(pcbAttrLen);
322 }
323
324 printf("Testing SCardGetAttrib\t\t: ");
325 rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, pbAttr, &pcbAttrLen);
326#endif
327 test_rv(rv, hContext, DONT_PANIC);
328 if (rv == SCARD_S_SUCCESS)
329 printf("SCARD_ATTR_DEVICE_FRIENDLY_NAME: " GREEN "%s\n" NORMAL, pbAttr);
330
331#ifdef USE_AUTOALLOCATE
332 printf("Testing SCardFreeMemory\t\t: ");
333 rv = SCardFreeMemory(hContext, pbAttr);
334 test_rv(rv, hContext, PANIC);
335#else
336 if (pbAttr)
337 free(pbAttr);
338#endif
339
340 printf("Testing SCardGetAttrib\t\t: ");
341#ifdef USE_AUTOALLOCATE
342 pcbAttrLen = SCARD_AUTOALLOCATE;
343 rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, (unsigned char *)&pbAttr,
344 &pcbAttrLen);
345#else
346 rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, NULL, &pcbAttrLen);
347 test_rv(rv, hContext, DONT_PANIC);
348 if (rv == SCARD_S_SUCCESS)
349 {
350 printf("SCARD_ATTR_ATR_STRING length: " GREEN "%ld\n" NORMAL, pcbAttrLen);
351 pbAttr = malloc(pcbAttrLen);
352 }
353
354 printf("Testing SCardGetAttrib\t\t: ");
355 rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, pbAttr, &pcbAttrLen);
356#endif
357 test_rv(rv, hContext, DONT_PANIC);
358 if (rv == SCARD_S_SUCCESS)
359 {
360 printf("SCARD_ATTR_ATR_STRING length: " GREEN "%ld\n" NORMAL, pcbAttrLen);
361 printf("SCARD_ATTR_ATR_STRING: " GREEN);
362 for (i = 0; i < pcbAttrLen; i++)
363 printf("%02X ", pbAttr[i]);
364 printf("\n" NORMAL);
365 }
366
367#ifdef USE_AUTOALLOCATE
368 printf("Testing SCardFreeMemory\t\t: ");
369 rv = SCardFreeMemory(hContext, pbAttr);
370 test_rv(rv, hContext, PANIC);
371#else
372 if (pbAttr)
373 free(pbAttr);
374#endif
375
376 printf("Testing SCardGetAttrib\t\t: ");
377 dwBufLen = sizeof(buf);
378 rv = SCardGetAttrib(hCard, SCARD_ATTR_VENDOR_IFD_VERSION, buf.as_char, &dwBufLen);
379 test_rv(rv, hContext, DONT_PANIC);
380 if (rv == SCARD_S_SUCCESS)
381 {
382 int valid = 1; /* valid value by default */
383 long value;
384 printf("Vendor IFD version\t\t: ");
385 if (dwBufLen == sizeof(DWORD))
386 value = buf.as_DWORD;
387 else
388 {
389 if (dwBufLen == sizeof(uint32_t))
390 value = buf.as_uint32_t;
391 else
392 {
393 printf(RED "Unsupported size\n" NORMAL);
394 valid = 0; /* invalid value */
395 }
396 }
397
398 if (valid)
399 {
400 int M = (value & 0xFF000000) >> 24; /* Major */
401 int m = (value & 0x00FF0000) >> 16; /* Minor */
402 int b = (value & 0x0000FFFF); /* build */
403 printf(GREEN "%d.%d.%d\n" NORMAL, M, m, b);
404 }
405 }
406
407 printf("Testing SCardGetAttrib\t\t: ");
408 dwBufLen = sizeof(buf);
409 rv = SCardGetAttrib(hCard, SCARD_ATTR_MAXINPUT, buf.as_char, &dwBufLen);
410 test_rv(rv, hContext, DONT_PANIC);
411 if (rv == SCARD_S_SUCCESS)
412 {
413 if (dwBufLen == sizeof(uint32_t))
414 printf("Max message length\t\t: " GREEN "%d\n" NORMAL,
415 buf.as_uint32_t);
416 else
417 printf(RED "Wrong size" NORMAL);
418 }
419
420 printf("Testing SCardGetAttrib\t\t: ");
421 dwBufLen = sizeof(buf);
422 rv = SCardGetAttrib(hCard, SCARD_ATTR_VENDOR_NAME, buf.as_char, &dwBufLen);
423 test_rv(rv, hContext, DONT_PANIC);
424 if (rv == SCARD_S_SUCCESS)
425 printf("Vendor name\t\t\t: " GREEN "%s\n" NORMAL, buf.as_char);
426
427 printf("Testing SCardSetAttrib\t\t: ");
428 rv = SCardSetAttrib(hCard, SCARD_ATTR_ATR_STRING, (LPCBYTE)"", 1);
429 test_rv(rv, hContext, DONT_PANIC);
430
431 printf("Testing SCardStatus\t\t: ");
432
433#ifdef USE_AUTOALLOCATE
434 dwReaderLen = SCARD_AUTOALLOCATE;
435 dwAtrLen = SCARD_AUTOALLOCATE;
436 rv = SCardStatus(hCard, (LPSTR)&pcReader, &dwReaderLen, &dwState, &dwProt,
437 (LPBYTE)&pbAtr, &dwAtrLen);
438#else
439 dwReaderLen = 100;
440 pcReader = malloc(sizeof(char) * 100);
441 dwAtrLen = MAX_ATR_SIZE;
442
443 rv = SCardStatus(hCard, pcReader, &dwReaderLen, &dwState, &dwProt,
444 pbAtr, &dwAtrLen);
445#endif
446 test_rv(rv, hContext, PANIC);
447
448 printf("Current Reader Name\t\t: " GREEN "%s\n" NORMAL, pcReader);
449 printf("Current Reader State\t\t: " GREEN "0x%.4lx\n" NORMAL, dwState);
450 printf("Current Reader Protocol\t\t: T=" GREEN "%ld\n" NORMAL, dwProt - 1);
451 printf("Current Reader ATR Size\t\t: " GREEN "%ld" NORMAL " bytes\n",
452 dwAtrLen);
453 printf("Current Reader ATR Value\t: " GREEN);
454
455 for (i = 0; i < dwAtrLen; i++)
456 {
457 printf("%02X ", pbAtr[i]);
458 }
459 printf(NORMAL "\n");
460
461#ifdef USE_AUTOALLOCATE
462 printf("Testing SCardFreeMemory\t\t: ");
463 rv = SCardFreeMemory(hContext, pcReader);
464 test_rv(rv, hContext, PANIC);
465 printf("Testing SCardFreeMemory\t\t: ");
466 rv = SCardFreeMemory(hContext, pbAtr);
467 test_rv(rv, hContext, PANIC);
468#else
469 if (pcReader)
470 free(pcReader);
471#endif
472
473 printf("Press enter: ");
474 (void)getchar();
475 printf("Testing SCardReconnect\t\t: ");
476 rv = SCardReconnect(hCard, SCARD_SHARE_SHARED,
478 test_rv(rv, hContext, PANIC);
479
480 printf("Testing SCardDisconnect\t\t: ");
481 rv = SCardDisconnect(hCard, SCARD_UNPOWER_CARD);
482 test_rv(rv, hContext, PANIC);
483
484#ifdef USE_AUTOALLOCATE
485 printf("Testing SCardFreeMemory\t\t: ");
486 rv = SCardFreeMemory(hContext, mszReaders);
487 test_rv(rv, hContext, PANIC);
488#else
489 free(mszReaders);
490#endif
491
492 printf("Testing SCardReleaseContext\t: ");
493 rv = SCardReleaseContext(hContext);
494 test_rv(rv, hContext, PANIC);
495
496 printf("\n");
497 printf("PC/SC Test Completed Successfully !\n");
498
499 return 0;
500}
#define SCARD_S_SUCCESS
No error was encountered.
Definition pcsclite.h:107
#define SCARD_E_NO_READERS_AVAILABLE
Cannot find a smart card reader.
Definition pcsclite.h:201
This keeps a list of defines for pcsc-lite.
#define SCARD_SCOPE_SYSTEM
Scope in system.
Definition pcsclite.h:236
LONG SCARDCONTEXT
hContext returned by SCardEstablishContext()
Definition pcsclite.h:52
#define SCARD_PROTOCOL_T1
T=1 active protocol.
Definition pcsclite.h:242
#define SCARD_PROTOCOL_T0
T=0 active protocol.
Definition pcsclite.h:241
#define SCARD_AUTOALLOCATE
see SCardFreeMemory()
Definition pcsclite.h:233
#define SCARD_UNPOWER_CARD
Power down on close.
Definition pcsclite.h:254
#define SCARD_SHARE_SHARED
Shared mode only.
Definition pcsclite.h:249
#define MAX_ATR_SIZE
Maximum ATR size.
Definition pcsclite.h:59
#define SCARD_PCI_RAW
protocol control information (PCI) for RAW protocol
Definition pcsclite.h:97
#define SCARD_STATE_UNKNOWN
Reader unknown.
Definition pcsclite.h:268
#define INFINITE
Infinite timeout.
Definition pcsclite.h:279
#define SCARD_STATE_EMPTY
Card removed.
Definition pcsclite.h:270
#define SCARD_PROTOCOL_RAW
Raw active protocol.
Definition pcsclite.h:243
#define MAX_BUFFER_SIZE
Maximum Tx/Rx Buffer for short APDU.
Definition pcsclite.h:297
#define SCARD_PCI_T1
protocol control information (PCI) for T=1
Definition pcsclite.h:96
LONG SCARDHANDLE
hCard returned by SCardConnect()
Definition pcsclite.h:55
#define SCARD_PCI_T0
protocol control information (PCI) for T=0
Definition pcsclite.h:95
This keeps a list of defines shared between the driver and the application.
#define SCARD_ATTR_VENDOR_IFD_VERSION
Vendor-supplied interface device version (DWORD in the form 0xMMmmbbbb where MM = major version,...
Definition reader.h:60
#define SCARD_ATTR_DEVICE_FRIENDLY_NAME
Reader's display name.
Definition reader.h:111
#define SCARD_ATTR_MAXINPUT
FIXME.
Definition reader.h:97
#define SCARD_CTL_CODE(code)
Provide source compatibility on different platforms.
Definition reader.h:118
#define SCARD_ATTR_VENDOR_NAME
Vendor name.
Definition reader.h:58
#define SCARD_ATTR_ATR_STRING
Answer to reset (ATR) string.
Definition reader.h:91
Protocol Control Information (PCI)
Definition pcsclite.h:80
This handles smart card reader communications.