testpcsc.c

Go to the documentation of this file.
00001 /*
00002  * MUSCLE SmartCard Development ( http://www.linuxnet.com )
00003  *
00004  * Copyright (C) 1999
00005  *  David Corcoran <corcoran@linuxnet.com>
00006  * Copyright (C) 2004-2008
00007  *  Ludovic Rousseau <ludovic.rousseau@free.fr>
00008  *
00009  * $Id: testpcsc.c 4703 2010-02-02 10:34:18Z rousseau $
00010  */
00011 
00017 #include "config.h"
00018 #include <stdio.h>
00019 #include <stdlib.h>
00020 #include <string.h>
00021 
00022 #include "pcsclite.h"
00023 #include "winscard.h"
00024 #include "reader.h"
00025 
00026 #define PANIC 0
00027 #define DONT_PANIC 1
00028 
00029 #define USE_AUTOALLOCATE
00030 
00031 #define BLUE "\33[34m"
00032 #define RED "\33[31m"
00033 #define BRIGHT_RED "\33[01;31m"
00034 #define GREEN "\33[32m"
00035 #define NORMAL "\33[0m"
00036 #define MAGENTA "\33[35m"
00037 
00038 static void test_rv(LONG rv, SCARDCONTEXT hContext, int dont_panic)
00039 {
00040     if (rv != SCARD_S_SUCCESS)
00041     {
00042         if (dont_panic)
00043             printf(BLUE "%s (don't panic)\n" NORMAL, pcsc_stringify_error(rv));
00044         else
00045         {
00046             printf(RED "%s\n" NORMAL, pcsc_stringify_error(rv));
00047             (void)SCardReleaseContext(hContext);
00048             exit(-1);
00049         }
00050     }
00051     else
00052         (void)puts(pcsc_stringify_error(rv));
00053 }
00054 
00055 int main(/*@unused@*/ int argc, /*@unused@*/ char **argv)
00056 {
00057     SCARDHANDLE hCard;
00058     SCARDCONTEXT hContext;
00059     SCARD_READERSTATE_A rgReaderStates[1];
00060     DWORD dwReaderLen, dwState, dwProt, dwAtrLen;
00061     DWORD dwPref, dwReaders = 0;
00062     char *pcReaders = NULL, *mszReaders;
00063 #ifdef USE_AUTOALLOCATE
00064     unsigned char *pbAtr = NULL;
00065 #else
00066     unsigned char pbAtr[MAX_ATR_SIZE];
00067 #endif
00068     union {
00069         unsigned char as_char[100];
00070         DWORD as_DWORD;
00071         uint32_t as_uint32_t;
00072     } buf;
00073     DWORD dwBufLen;
00074     unsigned char *pbAttr = NULL;
00075     DWORD pcbAttrLen;
00076     char *mszGroups;
00077     DWORD dwGroups = 0;
00078     long rv;
00079     DWORD i;
00080     int p, iReader;
00081     int iList[16];
00082     SCARD_IO_REQUEST pioRecvPci;
00083     SCARD_IO_REQUEST pioSendPci;
00084     unsigned char bSendBuffer[MAX_BUFFER_SIZE];
00085     unsigned char bRecvBuffer[MAX_BUFFER_SIZE];
00086     DWORD send_length, length;
00087 
00088     (void)argc;
00089     (void)argv;
00090 
00091     printf("\nMUSCLE PC/SC Lite unitary test Program\n\n");
00092 
00093     printf(MAGENTA "THIS PROGRAM IS NOT DESIGNED AS A TESTING TOOL FOR END USERS!\n");
00094     printf("Do NOT use it unless you really know what you do.\n\n" NORMAL);
00095 
00096     printf("Testing SCardEstablishContext\t: ");
00097     rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
00098     test_rv(rv, hContext, PANIC);
00099 
00100     printf("Testing SCardIsValidContext\t: ");
00101     rv = SCardIsValidContext(hContext);
00102     test_rv(rv, hContext, PANIC);
00103 
00104     printf("Testing SCardIsValidContext\t: ");
00105     rv = SCardIsValidContext(hContext+1);
00106     test_rv(rv, hContext, DONT_PANIC);
00107 
00108     printf("Testing SCardListReaderGroups\t: ");
00109 #ifdef USE_AUTOALLOCATE
00110     dwGroups = SCARD_AUTOALLOCATE;
00111     rv = SCardListReaderGroups(hContext, (LPSTR)&mszGroups, &dwGroups);
00112 #else
00113     rv = SCardListReaderGroups(hContext, NULL, &dwGroups);
00114     test_rv(rv, hContext, PANIC);
00115 
00116     printf("Testing SCardListReaderGroups\t: ");
00117     mszGroups = calloc(dwGroups, sizeof(char));
00118     rv = SCardListReaderGroups(hContext, mszGroups, &dwGroups);
00119 #endif
00120     test_rv(rv, hContext, PANIC);
00121 
00122     /*
00123      * Have to understand the multi-string here
00124      */
00125     p = 0;
00126     for (i = 0; i+1 < dwGroups; i++)
00127     {
00128         ++p;
00129         printf(GREEN "Group %02d: %s\n" NORMAL, p, &mszGroups[i]);
00130         while (mszGroups[++i] != 0) ;
00131     }
00132 
00133 #ifdef USE_AUTOALLOCATE
00134     printf("Testing SCardFreeMemory\t\t: ");
00135     rv = SCardFreeMemory(hContext, mszGroups);
00136     test_rv(rv, hContext, PANIC);
00137 #else
00138     free(mszGroups);
00139 #endif
00140 
00141 wait_for_card_again:
00142     mszGroups = NULL;
00143     printf("Testing SCardListReaders\t: ");
00144     rv = SCardListReaders(hContext, mszGroups, NULL, &dwReaders);
00145     test_rv(rv, hContext, DONT_PANIC);
00146     if (SCARD_E_NO_READERS_AVAILABLE == rv)
00147     {
00148         printf("Testing SCardGetStatusChange \n");
00149         printf("Please insert a working reader\t: ");
00150         (void)fflush(stdout);
00151         rgReaderStates[0].szReader = "\\\\?PnP?\\Notification";
00152         rgReaderStates[0].dwCurrentState = SCARD_STATE_EMPTY;
00153 
00154         rv = SCardGetStatusChange(hContext, INFINITE, rgReaderStates, 1);
00155         test_rv(rv, hContext, PANIC);
00156     }
00157 
00158     printf("Testing SCardListReaders\t: ");
00159 #ifdef USE_AUTOALLOCATE
00160     dwReaders = SCARD_AUTOALLOCATE;
00161     rv = SCardListReaders(hContext, mszGroups, (LPSTR)&mszReaders, &dwReaders);
00162 #else
00163     rv = SCardListReaders(hContext, mszGroups, NULL, &dwReaders);
00164     test_rv(rv, hContext, PANIC);
00165 
00166     printf("Testing SCardListReaders\t: ");
00167     mszReaders = calloc(dwReaders, sizeof(char));
00168     rv = SCardListReaders(hContext, mszGroups, mszReaders, &dwReaders);
00169 #endif
00170     test_rv(rv, hContext, DONT_PANIC);
00171 
00172     /*
00173      * Have to understand the multi-string here
00174      */
00175     p = 0;
00176     for (i = 0; i+1 < dwReaders; i++)
00177     {
00178         ++p;
00179         printf(GREEN "Reader %02d: %s\n" NORMAL, p, &mszReaders[i]);
00180         iList[p] = i;
00181         while (mszReaders[++i] != 0) ;
00182     }
00183 
00184     if (p > 1)
00185         do
00186         {
00187             char input[80];
00188 
00189             printf("Enter the reader number\t\t: ");
00190             (void)fgets(input, sizeof(input), stdin);
00191             (void)sscanf(input, "%d", &iReader);
00192 
00193             if (iReader > p || iReader <= 0)
00194                 printf("Invalid Value - try again\n");
00195         }
00196         while (iReader > p || iReader <= 0);
00197     else
00198         iReader = 1;
00199 
00200     rgReaderStates[0].szReader = &mszReaders[iList[iReader]];
00201     rgReaderStates[0].dwCurrentState = SCARD_STATE_EMPTY;
00202 
00203     printf("Waiting for card insertion\t: ");
00204     (void)fflush(stdout);
00205     rv = SCardGetStatusChange(hContext, INFINITE, rgReaderStates, 1);
00206     test_rv(rv, hContext, PANIC);
00207     if (rgReaderStates[0].dwEventState & SCARD_STATE_UNKNOWN)
00208     {
00209         printf("\nA reader has been connected/disconnected\n");
00210         goto wait_for_card_again;
00211     }
00212 
00213     printf("Testing SCardConnect\t\t: ");
00214     rv = SCardConnect(hContext, &mszReaders[iList[iReader]],
00215         SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1,
00216         &hCard, &dwPref);
00217     test_rv(rv, hContext, PANIC);
00218 
00219     switch(dwPref)
00220     {
00221         case SCARD_PROTOCOL_T0:
00222             pioSendPci = *SCARD_PCI_T0;
00223             break;
00224         case SCARD_PROTOCOL_T1:
00225             pioSendPci = *SCARD_PCI_T1;
00226             break;
00227         case SCARD_PROTOCOL_RAW:
00228             pioSendPci = *SCARD_PCI_RAW;
00229             break;
00230         default:
00231             printf("Unknown protocol\n");
00232             return -1;
00233     }
00234 
00235     /* APDU select file */
00236     printf("Select file:");
00237     send_length = 7;
00238     memcpy(bSendBuffer, "\x00\xA4\x00\x00\x02\x3F\x00", send_length);
00239     for (i=0; i<send_length; i++)
00240         printf(" %02X", bSendBuffer[i]);
00241     printf("\n");
00242     length = sizeof(bRecvBuffer);
00243 
00244     printf("Testing SCardTransmit\t\t: ");
00245     rv = SCardTransmit(hCard, &pioSendPci, bSendBuffer, send_length,
00246         &pioRecvPci, bRecvBuffer, &length);
00247     test_rv(rv, hContext, PANIC);
00248     printf(" card response:" GREEN);
00249     for (i=0; i<length; i++)
00250         printf(" %02X", bRecvBuffer[i]);
00251     printf("\n" NORMAL);
00252 
00253     printf("Testing SCardControl\t\t: ");
00254 #ifdef PCSC_PRE_120
00255     {
00256         char buffer[1024] = "Foobar";
00257         DWORD cbRecvLength = sizeof(buffer);
00258 
00259         rv = SCardControl(hCard, buffer, 7, buffer, &cbRecvLength);
00260     }
00261 #else
00262     {
00263         char buffer[1024] = { 0x02 };
00264         DWORD cbRecvLength = sizeof(buffer);
00265 
00266         rv = SCardControl(hCard, SCARD_CTL_CODE(1), buffer, 1, buffer,
00267             sizeof(buffer), &cbRecvLength);
00268         if (cbRecvLength && (SCARD_S_SUCCESS == rv))
00269         {
00270             for (i=0; i<cbRecvLength; i++)
00271                 printf("%c", buffer[i]);
00272             printf(" ");
00273         }
00274     }
00275 #endif
00276     test_rv(rv, hContext, DONT_PANIC);
00277 
00278     printf("Testing SCardGetAttrib\t\t: ");
00279 #ifdef USE_AUTOALLOCATE
00280     pcbAttrLen = SCARD_AUTOALLOCATE;
00281     rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, (unsigned char *)&pbAttr,
00282         &pcbAttrLen);
00283 #else
00284     rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, NULL, &pcbAttrLen);
00285     test_rv(rv, hContext, DONT_PANIC);
00286     if (rv == SCARD_S_SUCCESS)
00287     {
00288         printf("SCARD_ATTR_DEVICE_FRIENDLY_NAME length: " GREEN "%ld\n" NORMAL, pcbAttrLen);
00289         pbAttr = malloc(pcbAttrLen);
00290     }
00291 
00292     printf("Testing SCardGetAttrib\t\t: ");
00293     rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, pbAttr, &pcbAttrLen);
00294 #endif
00295     test_rv(rv, hContext, DONT_PANIC);
00296     if (rv == SCARD_S_SUCCESS)
00297         printf("SCARD_ATTR_DEVICE_FRIENDLY_NAME: " GREEN "%s\n" NORMAL, pbAttr);
00298 
00299 #ifdef USE_AUTOALLOCATE
00300     printf("Testing SCardFreeMemory\t\t: ");
00301     rv = SCardFreeMemory(hContext, pbAttr);
00302     test_rv(rv, hContext, PANIC);
00303 #else
00304     if (pbAttr)
00305         free(pbAttr);
00306 #endif
00307 
00308     printf("Testing SCardGetAttrib\t\t: ");
00309 #ifdef USE_AUTOALLOCATE
00310     pcbAttrLen = SCARD_AUTOALLOCATE;
00311     rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, (unsigned char *)&pbAttr,
00312         &pcbAttrLen);
00313 #else
00314     rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, NULL, &pcbAttrLen);
00315     test_rv(rv, hContext, DONT_PANIC);
00316     if (rv == SCARD_S_SUCCESS)
00317     {
00318         printf("SCARD_ATTR_ATR_STRING length: " GREEN "%ld\n" NORMAL, pcbAttrLen);
00319         pbAttr = malloc(pcbAttrLen);
00320     }
00321 
00322     printf("Testing SCardGetAttrib\t\t: ");
00323     rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, pbAttr, &pcbAttrLen);
00324 #endif
00325     test_rv(rv, hContext, DONT_PANIC);
00326     if (rv == SCARD_S_SUCCESS)
00327     {
00328         printf("SCARD_ATTR_ATR_STRING length: " GREEN "%ld\n" NORMAL, pcbAttrLen);
00329         printf("SCARD_ATTR_ATR_STRING: " GREEN);
00330         for (i = 0; i < pcbAttrLen; i++)
00331             printf("%02X ", pbAttr[i]);
00332         printf("\n" NORMAL);
00333     }
00334 
00335 #ifdef USE_AUTOALLOCATE
00336     printf("Testing SCardFreeMemory\t\t: ");
00337     rv = SCardFreeMemory(hContext, pbAttr);
00338     test_rv(rv, hContext, PANIC);
00339 #else
00340     if (pbAttr)
00341         free(pbAttr);
00342 #endif
00343 
00344     printf("Testing SCardGetAttrib\t\t: ");
00345     dwBufLen = sizeof(buf);
00346     rv = SCardGetAttrib(hCard, SCARD_ATTR_VENDOR_IFD_VERSION, buf.as_char, &dwBufLen);
00347     test_rv(rv, hContext, DONT_PANIC);
00348     if (rv == SCARD_S_SUCCESS)
00349         printf("Vendor IFD version\t\t: " GREEN "0x%08lX\n" NORMAL,
00350             buf.as_DWORD);
00351 
00352     printf("Testing SCardGetAttrib\t\t: ");
00353     dwBufLen = sizeof(buf);
00354     rv = SCardGetAttrib(hCard, SCARD_ATTR_MAXINPUT, buf.as_char, &dwBufLen);
00355     test_rv(rv, hContext, DONT_PANIC);
00356     if (rv == SCARD_S_SUCCESS)
00357     {
00358         if (dwBufLen == sizeof(uint32_t))
00359             printf("Max message length\t\t: " GREEN "%d\n" NORMAL,
00360                 buf.as_uint32_t);
00361         else
00362             printf(RED "Wrong size" NORMAL);
00363     }
00364 
00365     printf("Testing SCardGetAttrib\t\t: ");
00366     dwBufLen = sizeof(buf);
00367     rv = SCardGetAttrib(hCard, SCARD_ATTR_VENDOR_NAME, buf.as_char, &dwBufLen);
00368     test_rv(rv, hContext, DONT_PANIC);
00369     if (rv == SCARD_S_SUCCESS)
00370         printf("Vendor name\t\t\t: " GREEN "%s\n" NORMAL, buf.as_char);
00371 
00372     printf("Testing SCardSetAttrib\t\t: ");
00373     rv = SCardSetAttrib(hCard, SCARD_ATTR_ATR_STRING, (LPCBYTE)"", 1);
00374     test_rv(rv, hContext, DONT_PANIC);
00375 
00376     printf("Testing SCardStatus\t\t: ");
00377 
00378 #ifdef USE_AUTOALLOCATE
00379     dwReaderLen = SCARD_AUTOALLOCATE;
00380     dwAtrLen = SCARD_AUTOALLOCATE;
00381     rv = SCardStatus(hCard, (LPSTR)&pcReaders, &dwReaderLen, &dwState, &dwProt,
00382         (LPBYTE)&pbAtr, &dwAtrLen);
00383 #else
00384     dwReaderLen = 100;
00385     pcReaders   = malloc(sizeof(char) * 100);
00386     dwAtrLen    = MAX_ATR_SIZE;
00387 
00388     rv = SCardStatus(hCard, pcReaders, &dwReaderLen, &dwState, &dwProt,
00389         pbAtr, &dwAtrLen);
00390 #endif
00391     test_rv(rv, hContext, PANIC);
00392 
00393     printf("Current Reader Name\t\t: " GREEN "%s\n" NORMAL, pcReaders);
00394     printf("Current Reader State\t\t: " GREEN "0x%.4lx\n" NORMAL, dwState);
00395     printf("Current Reader Protocol\t\t: T=" GREEN "%ld\n" NORMAL, dwProt - 1);
00396     printf("Current Reader ATR Size\t\t: " GREEN "%ld" NORMAL " bytes\n",
00397         dwAtrLen);
00398     printf("Current Reader ATR Value\t: " GREEN);
00399 
00400     for (i = 0; i < dwAtrLen; i++)
00401     {
00402         printf("%02X ", pbAtr[i]);
00403     }
00404     printf(NORMAL "\n");
00405 
00406 #ifdef USE_AUTOALLOCATE
00407     printf("Testing SCardFreeMemory\t\t: ");
00408     rv = SCardFreeMemory(hContext, pcReaders);
00409     test_rv(rv, hContext, PANIC);
00410     printf("Testing SCardFreeMemory\t\t: ");
00411     rv = SCardFreeMemory(hContext, pbAtr);
00412     test_rv(rv, hContext, PANIC);
00413 #else
00414     if (pcReaders)
00415         free(pcReaders);
00416 #endif
00417 
00418     if (rv != SCARD_S_SUCCESS)
00419     {
00420         (void)SCardDisconnect(hCard, SCARD_RESET_CARD);
00421         (void)SCardReleaseContext(hContext);
00422     }
00423 
00424     printf("Press enter: ");
00425     (void)getchar();
00426     printf("Testing SCardReconnect\t\t: ");
00427     rv = SCardReconnect(hCard, SCARD_SHARE_SHARED,
00428         SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, SCARD_UNPOWER_CARD, &dwPref);
00429     test_rv(rv, hContext, PANIC);
00430 
00431     printf("Testing SCardDisconnect\t\t: ");
00432     rv = SCardDisconnect(hCard, SCARD_UNPOWER_CARD);
00433     test_rv(rv, hContext, PANIC);
00434 
00435 #ifdef USE_AUTOALLOCATE
00436     printf("Testing SCardFreeMemory\t\t: ");
00437     rv = SCardFreeMemory(hContext, mszReaders);
00438     test_rv(rv, hContext, PANIC);
00439 #else
00440     free(mszReaders);
00441 #endif
00442 
00443     printf("Testing SCardReleaseContext\t: ");
00444     rv = SCardReleaseContext(hContext);
00445     test_rv(rv, hContext, PANIC);
00446 
00447     printf("\n");
00448     printf("PC/SC Test Completed Successfully !\n");
00449 
00450     return 0;
00451 }