pcsc-lite 1.9.5
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 do
207 {
208 char input[80];
209 char *r;
210
211 printf("Enter the reader number\t\t: ");
212 r = fgets(input, sizeof(input), stdin);
213 if (NULL == r)
214 iReader = -1;
215 else
216 iReader = atoi(input);
217
218 if (iReader > p || iReader <= 0)
219 printf("Invalid Value - try again\n");
220 }
221 while (iReader > p || iReader <= 0);
222 else
223 iReader = 1;
224
225 rgReaderStates[0].szReader = &mszReaders[iList[iReader]];
226 rgReaderStates[0].dwCurrentState = SCARD_STATE_EMPTY;
227
228 printf("Waiting for card insertion\t: ");
229 (void)fflush(stdout);
230 rv = SCardGetStatusChange(hContext, INFINITE, rgReaderStates, 1);
231 test_rv(rv, hContext, PANIC);
232 if (rgReaderStates[0].dwEventState & SCARD_STATE_UNKNOWN)
233 {
234 printf("\nA reader has been connected/disconnected\n");
235 goto wait_for_card_again;
236 }
237
238 printf("Testing SCardConnect\t\t: ");
239 rv = SCardConnect(hContext, &mszReaders[iList[iReader]],
241 &hCard, &dwPref);
242 test_rv(rv, hContext, PANIC);
243
244 switch(dwPref)
245 {
247 pioSendPci = SCARD_PCI_T0;
248 break;
250 pioSendPci = SCARD_PCI_T1;
251 break;
253 pioSendPci = SCARD_PCI_RAW;
254 break;
255 default:
256 printf("Unknown protocol\n");
257 return -1;
258 }
259
260 /* APDU select file */
261 printf("Select file:");
262 send_length = 7;
263 memcpy(bSendBuffer, "\x00\xA4\x00\x00\x02\x3F\x00", send_length);
264 for (i=0; i<send_length; i++)
265 printf(" %02X", bSendBuffer[i]);
266 printf("\n");
267 length = sizeof(bRecvBuffer);
268
269 printf("Testing SCardTransmit\t\t: ");
270 rv = SCardTransmit(hCard, pioSendPci, bSendBuffer, send_length,
271 &ioRecvPci, bRecvBuffer, &length);
272 test_rv(rv, hContext, PANIC);
273 printf(" card response:" GREEN);
274 for (i=0; i<length; i++)
275 printf(" %02X", bRecvBuffer[i]);
276 printf("\n" NORMAL);
277
278 printf("Testing SCardControl\t\t: ");
279#ifdef PCSC_PRE_120
280 {
281 char buffer[1024] = "Foobar";
282 DWORD cbRecvLength = sizeof(buffer);
283
284 rv = SCardControl(hCard, buffer, 7, buffer, &cbRecvLength);
285 }
286#else
287 {
288 char buffer[1024] = { 0x02 };
289 DWORD cbRecvLength = sizeof(buffer);
290
291 rv = SCardControl(hCard, SCARD_CTL_CODE(1), buffer, 1, buffer,
292 sizeof(buffer), &cbRecvLength);
293 if (cbRecvLength && (SCARD_S_SUCCESS == rv))
294 {
295 for (i=0; i<cbRecvLength; i++)
296 printf("%c", buffer[i]);
297 printf(" ");
298 }
299 }
300#endif
301 test_rv(rv, hContext, DONT_PANIC);
302
303 printf("Testing SCardGetAttrib\t\t: ");
304#ifdef USE_AUTOALLOCATE
305 pcbAttrLen = SCARD_AUTOALLOCATE;
306 rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, (unsigned char *)&pbAttr,
307 &pcbAttrLen);
308#else
309 rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, NULL, &pcbAttrLen);
310 test_rv(rv, hContext, DONT_PANIC);
311 if (rv == SCARD_S_SUCCESS)
312 {
313 printf("SCARD_ATTR_DEVICE_FRIENDLY_NAME length: " GREEN "%ld\n" NORMAL, pcbAttrLen);
314 pbAttr = malloc(pcbAttrLen);
315 }
316
317 printf("Testing SCardGetAttrib\t\t: ");
318 rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, pbAttr, &pcbAttrLen);
319#endif
320 test_rv(rv, hContext, DONT_PANIC);
321 if (rv == SCARD_S_SUCCESS)
322 printf("SCARD_ATTR_DEVICE_FRIENDLY_NAME: " GREEN "%s\n" NORMAL, pbAttr);
323
324#ifdef USE_AUTOALLOCATE
325 printf("Testing SCardFreeMemory\t\t: ");
326 rv = SCardFreeMemory(hContext, pbAttr);
327 test_rv(rv, hContext, PANIC);
328#else
329 if (pbAttr)
330 free(pbAttr);
331#endif
332
333 printf("Testing SCardGetAttrib\t\t: ");
334#ifdef USE_AUTOALLOCATE
335 pcbAttrLen = SCARD_AUTOALLOCATE;
336 rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, (unsigned char *)&pbAttr,
337 &pcbAttrLen);
338#else
339 rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, NULL, &pcbAttrLen);
340 test_rv(rv, hContext, DONT_PANIC);
341 if (rv == SCARD_S_SUCCESS)
342 {
343 printf("SCARD_ATTR_ATR_STRING length: " GREEN "%ld\n" NORMAL, pcbAttrLen);
344 pbAttr = malloc(pcbAttrLen);
345 }
346
347 printf("Testing SCardGetAttrib\t\t: ");
348 rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, pbAttr, &pcbAttrLen);
349#endif
350 test_rv(rv, hContext, DONT_PANIC);
351 if (rv == SCARD_S_SUCCESS)
352 {
353 printf("SCARD_ATTR_ATR_STRING length: " GREEN "%ld\n" NORMAL, pcbAttrLen);
354 printf("SCARD_ATTR_ATR_STRING: " GREEN);
355 for (i = 0; i < pcbAttrLen; i++)
356 printf("%02X ", pbAttr[i]);
357 printf("\n" NORMAL);
358 }
359
360#ifdef USE_AUTOALLOCATE
361 printf("Testing SCardFreeMemory\t\t: ");
362 rv = SCardFreeMemory(hContext, pbAttr);
363 test_rv(rv, hContext, PANIC);
364#else
365 if (pbAttr)
366 free(pbAttr);
367#endif
368
369 printf("Testing SCardGetAttrib\t\t: ");
370 dwBufLen = sizeof(buf);
371 rv = SCardGetAttrib(hCard, SCARD_ATTR_VENDOR_IFD_VERSION, buf.as_char, &dwBufLen);
372 test_rv(rv, hContext, DONT_PANIC);
373 if (rv == SCARD_S_SUCCESS)
374 {
375 int valid = 1; /* valid value by default */
376 long value;
377 printf("Vendor IFD version\t\t: ");
378 if (dwBufLen == sizeof(DWORD))
379 value = buf.as_DWORD;
380 else
381 {
382 if (dwBufLen == sizeof(uint32_t))
383 value = buf.as_uint32_t;
384 else
385 {
386 printf(RED "Unsupported size\n" NORMAL);
387 valid = 0; /* invalid value */
388 }
389 }
390
391 if (valid)
392 {
393 int M = (value & 0xFF000000) >> 24; /* Major */
394 int m = (value & 0x00FF0000) >> 16; /* Minor */
395 int b = (value & 0x0000FFFF); /* build */
396 printf(GREEN "%d.%d.%d\n" NORMAL, M, m, b);
397 }
398 }
399
400 printf("Testing SCardGetAttrib\t\t: ");
401 dwBufLen = sizeof(buf);
402 rv = SCardGetAttrib(hCard, SCARD_ATTR_MAXINPUT, buf.as_char, &dwBufLen);
403 test_rv(rv, hContext, DONT_PANIC);
404 if (rv == SCARD_S_SUCCESS)
405 {
406 if (dwBufLen == sizeof(uint32_t))
407 printf("Max message length\t\t: " GREEN "%d\n" NORMAL,
408 buf.as_uint32_t);
409 else
410 printf(RED "Wrong size" NORMAL);
411 }
412
413 printf("Testing SCardGetAttrib\t\t: ");
414 dwBufLen = sizeof(buf);
415 rv = SCardGetAttrib(hCard, SCARD_ATTR_VENDOR_NAME, buf.as_char, &dwBufLen);
416 test_rv(rv, hContext, DONT_PANIC);
417 if (rv == SCARD_S_SUCCESS)
418 printf("Vendor name\t\t\t: " GREEN "%s\n" NORMAL, buf.as_char);
419
420 printf("Testing SCardSetAttrib\t\t: ");
421 rv = SCardSetAttrib(hCard, SCARD_ATTR_ATR_STRING, (LPCBYTE)"", 1);
422 test_rv(rv, hContext, DONT_PANIC);
423
424 printf("Testing SCardStatus\t\t: ");
425
426#ifdef USE_AUTOALLOCATE
427 dwReaderLen = SCARD_AUTOALLOCATE;
428 dwAtrLen = SCARD_AUTOALLOCATE;
429 rv = SCardStatus(hCard, (LPSTR)&pcReader, &dwReaderLen, &dwState, &dwProt,
430 (LPBYTE)&pbAtr, &dwAtrLen);
431#else
432 dwReaderLen = 100;
433 pcReader = malloc(sizeof(char) * 100);
434 dwAtrLen = MAX_ATR_SIZE;
435
436 rv = SCardStatus(hCard, pcReader, &dwReaderLen, &dwState, &dwProt,
437 pbAtr, &dwAtrLen);
438#endif
439 test_rv(rv, hContext, PANIC);
440
441 printf("Current Reader Name\t\t: " GREEN "%s\n" NORMAL, pcReader);
442 printf("Current Reader State\t\t: " GREEN "0x%.4lx\n" NORMAL, dwState);
443 printf("Current Reader Protocol\t\t: T=" GREEN "%ld\n" NORMAL, dwProt - 1);
444 printf("Current Reader ATR Size\t\t: " GREEN "%ld" NORMAL " bytes\n",
445 dwAtrLen);
446 printf("Current Reader ATR Value\t: " GREEN);
447
448 for (i = 0; i < dwAtrLen; i++)
449 {
450 printf("%02X ", pbAtr[i]);
451 }
452 printf(NORMAL "\n");
453
454#ifdef USE_AUTOALLOCATE
455 printf("Testing SCardFreeMemory\t\t: ");
456 rv = SCardFreeMemory(hContext, pcReader);
457 test_rv(rv, hContext, PANIC);
458 printf("Testing SCardFreeMemory\t\t: ");
459 rv = SCardFreeMemory(hContext, pbAtr);
460 test_rv(rv, hContext, PANIC);
461#else
462 if (pcReader)
463 free(pcReader);
464#endif
465
466 printf("Press enter: ");
467 (void)getchar();
468 printf("Testing SCardReconnect\t\t: ");
469 rv = SCardReconnect(hCard, SCARD_SHARE_SHARED,
471 test_rv(rv, hContext, PANIC);
472
473 printf("Testing SCardDisconnect\t\t: ");
474 rv = SCardDisconnect(hCard, SCARD_UNPOWER_CARD);
475 test_rv(rv, hContext, PANIC);
476
477#ifdef USE_AUTOALLOCATE
478 printf("Testing SCardFreeMemory\t\t: ");
479 rv = SCardFreeMemory(hContext, mszReaders);
480 test_rv(rv, hContext, PANIC);
481#else
482 free(mszReaders);
483#endif
484
485 printf("Testing SCardReleaseContext\t: ");
486 rv = SCardReleaseContext(hContext);
487 test_rv(rv, hContext, PANIC);
488
489 printf("\n");
490 printf("PC/SC Test Completed Successfully !\n");
491
492 return 0;
493}
#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.