pcsc-lite  1.8.7
testpcsc.c
Go to the documentation of this file.
1 /*
2  * MUSCLE SmartCard Development ( http://www.linuxnet.com )
3  *
4  * Copyright (C) 1999
5  * David Corcoran <corcoran@linuxnet.com>
6  * Copyright (C) 2004-2010
7  * Ludovic Rousseau <ludovic.rousseau@free.fr>
8  *
9  * $Id: testpcsc.c 5885 2011-08-09 07:49:14Z rousseau $
10  */
11 
17 #include "config.h"
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 
22 #include "pcsclite.h"
23 #include "winscard.h"
24 #include "reader.h"
25 
26 #define PANIC 0
27 #define DONT_PANIC 1
28 
29 #define USE_AUTOALLOCATE
30 
31 #define BLUE "\33[34m"
32 #define RED "\33[31m"
33 #define BRIGHT_RED "\33[01;31m"
34 #define GREEN "\33[32m"
35 #define NORMAL "\33[0m"
36 #define MAGENTA "\33[35m"
37 
38 static void test_rv(LONG rv, SCARDCONTEXT hContext, int dont_panic)
39 {
40  if (rv != SCARD_S_SUCCESS)
41  {
42  if (dont_panic)
43  printf(BLUE "%s (don't panic)\n" NORMAL, pcsc_stringify_error(rv));
44  else
45  {
46  printf(RED "%s\n" NORMAL, pcsc_stringify_error(rv));
47  (void)SCardReleaseContext(hContext);
48  exit(-1);
49  }
50  }
51  else
52  (void)puts(pcsc_stringify_error(rv));
53 }
54 
55 int main(/*@unused@*/ int argc, /*@unused@*/ char **argv)
56 {
57  SCARDHANDLE hCard;
58  SCARDCONTEXT hContext;
59  SCARD_READERSTATE rgReaderStates[1];
60  DWORD dwReaderLen, dwState, dwProt, dwAtrLen;
61  DWORD dwPref, dwReaders = 0;
62  char *pcReaders = NULL, *mszReaders;
63 #ifdef USE_AUTOALLOCATE
64  unsigned char *pbAtr = NULL;
65 #else
66  unsigned char pbAtr[MAX_ATR_SIZE];
67 #endif
68  union {
69  unsigned char as_char[100];
70  DWORD as_DWORD;
71  uint32_t as_uint32_t;
72  } buf;
73  DWORD dwBufLen;
74  unsigned char *pbAttr = NULL;
75  DWORD pcbAttrLen;
76  char *mszGroups;
77  DWORD dwGroups = 0;
78  long rv;
79  DWORD i;
80  int p, iReader;
81  int iList[16];
82  SCARD_IO_REQUEST ioRecvPci = *SCARD_PCI_T0; /* use a default value */
83  const SCARD_IO_REQUEST *pioSendPci;
84  unsigned char bSendBuffer[MAX_BUFFER_SIZE];
85  unsigned char bRecvBuffer[MAX_BUFFER_SIZE];
86  DWORD send_length, length;
87 
88  (void)argc;
89  (void)argv;
90 
91  printf("\nMUSCLE PC/SC Lite unitary test Program\n\n");
92 
93  printf(MAGENTA "THIS PROGRAM IS NOT DESIGNED AS A TESTING TOOL FOR END USERS!\n");
94  printf("Do NOT use it unless you really know what you do.\n\n" NORMAL);
95 
96  printf("Testing SCardEstablishContext\t: ");
97  rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
98  test_rv(rv, hContext, PANIC);
99 
100  printf("Testing SCardIsValidContext\t: ");
101  rv = SCardIsValidContext(hContext);
102  test_rv(rv, hContext, PANIC);
103 
104  printf("Testing SCardIsValidContext\t: ");
105  rv = SCardIsValidContext(hContext+1);
106  test_rv(rv, hContext, DONT_PANIC);
107 
108  printf("Testing SCardListReaderGroups\t: ");
109 #ifdef USE_AUTOALLOCATE
110  dwGroups = SCARD_AUTOALLOCATE;
111  rv = SCardListReaderGroups(hContext, (LPSTR)&mszGroups, &dwGroups);
112 #else
113  rv = SCardListReaderGroups(hContext, NULL, &dwGroups);
114  test_rv(rv, hContext, PANIC);
115 
116  printf("Testing SCardListReaderGroups\t: ");
117  mszGroups = calloc(dwGroups, sizeof(char));
118  rv = SCardListReaderGroups(hContext, mszGroups, &dwGroups);
119 #endif
120  test_rv(rv, hContext, PANIC);
121 
122  /*
123  * Have to understand the multi-string here
124  */
125  p = 0;
126  for (i = 0; i+1 < dwGroups; i++)
127  {
128  ++p;
129  printf(GREEN "Group %02d: %s\n" NORMAL, p, &mszGroups[i]);
130  while (mszGroups[++i] != 0) ;
131  }
132 
133 #ifdef USE_AUTOALLOCATE
134  printf("Testing SCardFreeMemory\t\t: ");
135  rv = SCardFreeMemory(hContext, mszGroups);
136  test_rv(rv, hContext, PANIC);
137 #else
138  free(mszGroups);
139 #endif
140 
141 wait_for_card_again:
142  mszGroups = NULL;
143  printf("Testing SCardListReaders\t: ");
144  rv = SCardListReaders(hContext, mszGroups, NULL, &dwReaders);
145  test_rv(rv, hContext, DONT_PANIC);
147  {
148  printf("Testing SCardGetStatusChange \n");
149  printf("Please insert a working reader\t: ");
150  (void)fflush(stdout);
151  rgReaderStates[0].szReader = "\\\\?PnP?\\Notification";
152  rgReaderStates[0].dwCurrentState = SCARD_STATE_EMPTY;
153 
154  rv = SCardGetStatusChange(hContext, INFINITE, rgReaderStates, 1);
155  test_rv(rv, hContext, PANIC);
156  }
157 
158  printf("Testing SCardListReaders\t: ");
159 #ifdef USE_AUTOALLOCATE
160  dwReaders = SCARD_AUTOALLOCATE;
161  rv = SCardListReaders(hContext, mszGroups, (LPSTR)&mszReaders, &dwReaders);
162 #else
163  rv = SCardListReaders(hContext, mszGroups, NULL, &dwReaders);
164  test_rv(rv, hContext, PANIC);
165 
166  printf("Testing SCardListReaders\t: ");
167  mszReaders = calloc(dwReaders, sizeof(char));
168  rv = SCardListReaders(hContext, mszGroups, mszReaders, &dwReaders);
169 #endif
170  test_rv(rv, hContext, DONT_PANIC);
171 
172  /*
173  * Have to understand the multi-string here
174  */
175  p = 0;
176  for (i = 0; i+1 < dwReaders; i++)
177  {
178  ++p;
179  printf(GREEN "Reader %02d: %s\n" NORMAL, p, &mszReaders[i]);
180  iList[p] = i;
181  while (mszReaders[++i] != 0) ;
182  }
183 
184  if (p > 1)
185  do
186  {
187  char input[80];
188 
189  printf("Enter the reader number\t\t: ");
190  (void)fgets(input, sizeof(input), stdin);
191  iReader = atoi(input);
192 
193  if (iReader > p || iReader <= 0)
194  printf("Invalid Value - try again\n");
195  }
196  while (iReader > p || iReader <= 0);
197  else
198  iReader = 1;
199 
200  rgReaderStates[0].szReader = &mszReaders[iList[iReader]];
201  rgReaderStates[0].dwCurrentState = SCARD_STATE_EMPTY;
202 
203  printf("Waiting for card insertion\t: ");
204  (void)fflush(stdout);
205  rv = SCardGetStatusChange(hContext, INFINITE, rgReaderStates, 1);
206  test_rv(rv, hContext, PANIC);
207  if (rgReaderStates[0].dwEventState & SCARD_STATE_UNKNOWN)
208  {
209  printf("\nA reader has been connected/disconnected\n");
210  goto wait_for_card_again;
211  }
212 
213  printf("Testing SCardConnect\t\t: ");
214  rv = SCardConnect(hContext, &mszReaders[iList[iReader]],
216  &hCard, &dwPref);
217  test_rv(rv, hContext, PANIC);
218 
219  switch(dwPref)
220  {
221  case SCARD_PROTOCOL_T0:
222  pioSendPci = SCARD_PCI_T0;
223  break;
224  case SCARD_PROTOCOL_T1:
225  pioSendPci = SCARD_PCI_T1;
226  break;
227  case SCARD_PROTOCOL_RAW:
228  pioSendPci = SCARD_PCI_RAW;
229  break;
230  default:
231  printf("Unknown protocol\n");
232  return -1;
233  }
234 
235  /* APDU select file */
236  printf("Select file:");
237  send_length = 7;
238  memcpy(bSendBuffer, "\x00\xA4\x00\x00\x02\x3F\x00", send_length);
239  for (i=0; i<send_length; i++)
240  printf(" %02X", bSendBuffer[i]);
241  printf("\n");
242  length = sizeof(bRecvBuffer);
243 
244  printf("Testing SCardTransmit\t\t: ");
245  rv = SCardTransmit(hCard, pioSendPci, bSendBuffer, send_length,
246  &ioRecvPci, bRecvBuffer, &length);
247  test_rv(rv, hContext, PANIC);
248  printf(" card response:" GREEN);
249  for (i=0; i<length; i++)
250  printf(" %02X", bRecvBuffer[i]);
251  printf("\n" NORMAL);
252 
253  printf("Testing SCardControl\t\t: ");
254 #ifdef PCSC_PRE_120
255  {
256  char buffer[1024] = "Foobar";
257  DWORD cbRecvLength = sizeof(buffer);
258 
259  rv = SCardControl(hCard, buffer, 7, buffer, &cbRecvLength);
260  }
261 #else
262  {
263  char buffer[1024] = { 0x02 };
264  DWORD cbRecvLength = sizeof(buffer);
265 
266  rv = SCardControl(hCard, SCARD_CTL_CODE(1), buffer, 1, buffer,
267  sizeof(buffer), &cbRecvLength);
268  if (cbRecvLength && (SCARD_S_SUCCESS == rv))
269  {
270  for (i=0; i<cbRecvLength; i++)
271  printf("%c", buffer[i]);
272  printf(" ");
273  }
274  }
275 #endif
276  test_rv(rv, hContext, DONT_PANIC);
277 
278  printf("Testing SCardGetAttrib\t\t: ");
279 #ifdef USE_AUTOALLOCATE
280  pcbAttrLen = SCARD_AUTOALLOCATE;
281  rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, (unsigned char *)&pbAttr,
282  &pcbAttrLen);
283 #else
284  rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, NULL, &pcbAttrLen);
285  test_rv(rv, hContext, DONT_PANIC);
286  if (rv == SCARD_S_SUCCESS)
287  {
288  printf("SCARD_ATTR_DEVICE_FRIENDLY_NAME length: " GREEN "%ld\n" NORMAL, pcbAttrLen);
289  pbAttr = malloc(pcbAttrLen);
290  }
291 
292  printf("Testing SCardGetAttrib\t\t: ");
293  rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, pbAttr, &pcbAttrLen);
294 #endif
295  test_rv(rv, hContext, DONT_PANIC);
296  if (rv == SCARD_S_SUCCESS)
297  printf("SCARD_ATTR_DEVICE_FRIENDLY_NAME: " GREEN "%s\n" NORMAL, pbAttr);
298 
299 #ifdef USE_AUTOALLOCATE
300  printf("Testing SCardFreeMemory\t\t: ");
301  rv = SCardFreeMemory(hContext, pbAttr);
302  test_rv(rv, hContext, PANIC);
303 #else
304  if (pbAttr)
305  free(pbAttr);
306 #endif
307 
308  printf("Testing SCardGetAttrib\t\t: ");
309 #ifdef USE_AUTOALLOCATE
310  pcbAttrLen = SCARD_AUTOALLOCATE;
311  rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, (unsigned char *)&pbAttr,
312  &pcbAttrLen);
313 #else
314  rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, NULL, &pcbAttrLen);
315  test_rv(rv, hContext, DONT_PANIC);
316  if (rv == SCARD_S_SUCCESS)
317  {
318  printf("SCARD_ATTR_ATR_STRING length: " GREEN "%ld\n" NORMAL, pcbAttrLen);
319  pbAttr = malloc(pcbAttrLen);
320  }
321 
322  printf("Testing SCardGetAttrib\t\t: ");
323  rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, pbAttr, &pcbAttrLen);
324 #endif
325  test_rv(rv, hContext, DONT_PANIC);
326  if (rv == SCARD_S_SUCCESS)
327  {
328  printf("SCARD_ATTR_ATR_STRING length: " GREEN "%ld\n" NORMAL, pcbAttrLen);
329  printf("SCARD_ATTR_ATR_STRING: " GREEN);
330  for (i = 0; i < pcbAttrLen; i++)
331  printf("%02X ", pbAttr[i]);
332  printf("\n" NORMAL);
333  }
334 
335 #ifdef USE_AUTOALLOCATE
336  printf("Testing SCardFreeMemory\t\t: ");
337  rv = SCardFreeMemory(hContext, pbAttr);
338  test_rv(rv, hContext, PANIC);
339 #else
340  if (pbAttr)
341  free(pbAttr);
342 #endif
343 
344  printf("Testing SCardGetAttrib\t\t: ");
345  dwBufLen = sizeof(buf);
346  rv = SCardGetAttrib(hCard, SCARD_ATTR_VENDOR_IFD_VERSION, buf.as_char, &dwBufLen);
347  test_rv(rv, hContext, DONT_PANIC);
348  if (rv == SCARD_S_SUCCESS)
349  printf("Vendor IFD version\t\t: " GREEN "0x%08lX\n" NORMAL,
350  buf.as_DWORD);
351 
352  printf("Testing SCardGetAttrib\t\t: ");
353  dwBufLen = sizeof(buf);
354  rv = SCardGetAttrib(hCard, SCARD_ATTR_MAXINPUT, buf.as_char, &dwBufLen);
355  test_rv(rv, hContext, DONT_PANIC);
356  if (rv == SCARD_S_SUCCESS)
357  {
358  if (dwBufLen == sizeof(uint32_t))
359  printf("Max message length\t\t: " GREEN "%d\n" NORMAL,
360  buf.as_uint32_t);
361  else
362  printf(RED "Wrong size" NORMAL);
363  }
364 
365  printf("Testing SCardGetAttrib\t\t: ");
366  dwBufLen = sizeof(buf);
367  rv = SCardGetAttrib(hCard, SCARD_ATTR_VENDOR_NAME, buf.as_char, &dwBufLen);
368  test_rv(rv, hContext, DONT_PANIC);
369  if (rv == SCARD_S_SUCCESS)
370  printf("Vendor name\t\t\t: " GREEN "%s\n" NORMAL, buf.as_char);
371 
372  printf("Testing SCardSetAttrib\t\t: ");
373  rv = SCardSetAttrib(hCard, SCARD_ATTR_ATR_STRING, (LPCBYTE)"", 1);
374  test_rv(rv, hContext, DONT_PANIC);
375 
376  printf("Testing SCardStatus\t\t: ");
377 
378 #ifdef USE_AUTOALLOCATE
379  dwReaderLen = SCARD_AUTOALLOCATE;
380  dwAtrLen = SCARD_AUTOALLOCATE;
381  rv = SCardStatus(hCard, (LPSTR)&pcReaders, &dwReaderLen, &dwState, &dwProt,
382  (LPBYTE)&pbAtr, &dwAtrLen);
383 #else
384  dwReaderLen = 100;
385  pcReaders = malloc(sizeof(char) * 100);
386  dwAtrLen = MAX_ATR_SIZE;
387 
388  rv = SCardStatus(hCard, pcReaders, &dwReaderLen, &dwState, &dwProt,
389  pbAtr, &dwAtrLen);
390 #endif
391  test_rv(rv, hContext, PANIC);
392 
393  printf("Current Reader Name\t\t: " GREEN "%s\n" NORMAL, pcReaders);
394  printf("Current Reader State\t\t: " GREEN "0x%.4lx\n" NORMAL, dwState);
395  printf("Current Reader Protocol\t\t: T=" GREEN "%ld\n" NORMAL, dwProt - 1);
396  printf("Current Reader ATR Size\t\t: " GREEN "%ld" NORMAL " bytes\n",
397  dwAtrLen);
398  printf("Current Reader ATR Value\t: " GREEN);
399 
400  for (i = 0; i < dwAtrLen; i++)
401  {
402  printf("%02X ", pbAtr[i]);
403  }
404  printf(NORMAL "\n");
405 
406 #ifdef USE_AUTOALLOCATE
407  printf("Testing SCardFreeMemory\t\t: ");
408  rv = SCardFreeMemory(hContext, pcReaders);
409  test_rv(rv, hContext, PANIC);
410  printf("Testing SCardFreeMemory\t\t: ");
411  rv = SCardFreeMemory(hContext, pbAtr);
412  test_rv(rv, hContext, PANIC);
413 #else
414  if (pcReaders)
415  free(pcReaders);
416 #endif
417 
418  if (rv != SCARD_S_SUCCESS)
419  {
420  (void)SCardDisconnect(hCard, SCARD_RESET_CARD);
421  (void)SCardReleaseContext(hContext);
422  }
423 
424  printf("Press enter: ");
425  (void)getchar();
426  printf("Testing SCardReconnect\t\t: ");
429  test_rv(rv, hContext, PANIC);
430 
431  printf("Testing SCardDisconnect\t\t: ");
432  rv = SCardDisconnect(hCard, SCARD_UNPOWER_CARD);
433  test_rv(rv, hContext, PANIC);
434 
435 #ifdef USE_AUTOALLOCATE
436  printf("Testing SCardFreeMemory\t\t: ");
437  rv = SCardFreeMemory(hContext, mszReaders);
438  test_rv(rv, hContext, PANIC);
439 #else
440  free(mszReaders);
441 #endif
442 
443  printf("Testing SCardReleaseContext\t: ");
444  rv = SCardReleaseContext(hContext);
445  test_rv(rv, hContext, PANIC);
446 
447  printf("\n");
448  printf("PC/SC Test Completed Successfully !\n");
449 
450  return 0;
451 }