static int testStatus(SCARDCONTEXT ctx, const char *readerName, const char *readerList) { SCARDHANDLE hCard; DWORD pcchReaderLen = 2048; //can this be calculated beforehand!? DWORD pdwState; DWORD pdwProtocol; BYTE pbAtr[32]; DWORD pcbAtrLen = 32; char readerName2[2048]; int returnValue = 0; long ret = SCardConnectA(ctx, readerName, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &hCard, &pdwProtocol); CHECK_PCSC_RET("SCardConnect", ret); if (SCARD_S_SUCCESS == ret) { delayMS(200); // Normal case: fail position ----1 ret = SCardStatusA(hCard, readerName2, &pcchReaderLen, &pdwState, &pdwProtocol, (LPBYTE) &pbAtr, &pcbAtrLen); if (ret != SCARD_S_SUCCESS) returnValue |= 1; // ReaderLen = 0: fail position ---1- pcchReaderLen = NULL; readerName2[0] = '\0'; //make sure refreshed with new values ret = SCardStatusA(hCard, (LPSTR) readerName2, &pcchReaderLen, &pdwState, &pdwProtocol, (LPBYTE) &pbAtr, &pcbAtrLen); if (ret != SCARD_S_SUCCESS) returnValue |= 2; // ReaderLen = 1: fail position ---1-- pcchReaderLen = 1; readerName2[0] = '\0'; //make sure refreshed with new values ret = SCardStatusA(hCard, (LPSTR) readerName2, &pcchReaderLen, &pdwState, &pdwProtocol, (LPBYTE) &pbAtr, &pcbAtrLen); CHECK_PCSC_RET_PASS(0x4) //AtrLen = 0: fail position --1--- pcchReaderLen = 2048; pcbAtrLen = 0; ret = SCardStatusA(hCard, (LPSTR) readerName2, &pcchReaderLen, &pdwState, &pdwProtocol, (LPBYTE) &pbAtr, &pcbAtrLen); if (ret != SCARD_S_SUCCESS) returnValue |= 8; //AtrLen = 1: fail position -1---- pcbAtrLen = 1; ret = SCardStatusA(hCard, (LPSTR) readerName2, &pcchReaderLen, &pdwState, &pdwProtocol, (LPBYTE) &pbAtr, &pcbAtrLen); if (ret != SCARD_S_SUCCESS) returnValue |= 16; //AtrLen = 33 (bigger than returned): fail position 1----- pcbAtrLen = 33; ret = SCardStatusA(hCard, (LPSTR) readerName2, &pcchReaderLen, &pdwState, &pdwProtocol, (LPBYTE) &pbAtr, &pcbAtrLen); if (ret != SCARD_S_SUCCESS) returnValue |= 32; } return returnValue; }
static int testMisc(SCARDCONTEXT hCard) { int ret = 0; int errCount = 0; unsigned char recvBuf[258]; DWORD recvBufLen = sizeof(recvBuf); ret = sendAPDU(hCard, "80:E4:00:00:1C", recvBuf, &recvBufLen); CHECK_PCSC_RET("sendAPDU(Get Card Data)", ret); if (recvBufLen != 0x1E || recvBuf[recvBufLen - 2] != 0x90 || recvBuf[recvBufLen - 1] != 0x00) { printf("ERR: Get Card Data didn't return 90 00\n"); errCount++; } ret = sendAPDU(hCard, "80:E4:00:00:1B", recvBuf, &recvBufLen); CHECK_PCSC_RET("sendAPDU(Get Card Data)", ret); if (recvBufLen != 0x1D || recvBuf[recvBufLen - 2] != 0x61 || recvBuf[recvBufLen - 1] != 0x01) { printf("ERR: Get Card Data didn't return 61 01\n"); errCount++; } return errCount; }
static int testSCardGetAttrib(SCARDCONTEXT hContext, SCARDCONTEXT hCard) { int errCount = 0; BYTE *attrib = NULL; DWORD attribLen = SCARD_AUTOALLOCATE; int ret = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, (LPBYTE)&attrib, &attribLen); CHECK_PCSC_RET("SCardGetAttrib()", ret); if (attribLen < 8) { printf("ERR: SCardGetAttrib(): ATR length looks too small (%d) for a BE eID card\n", (int) attribLen); errCount++; } else if (attrib[0] != 0x3B) { printf("ERR: SCardGetAttrib(): ATR should start with 0x3B (instead of 0x%0x) for a BE eID card\n", attrib[0]); errCount++; } ret = SCardFreeMemory(hContext, attrib); CHECK_PCSC_RET("SCardFreeMemory()", ret); return errCount; }
static long sendAPDUS(SCARDCONTEXT ctx, const char *readerName, int apduCount, const char **apdus) { SCARDHANDLE hCard; DWORD protocol; char debugString[2048]; printf("Using reader \"%s\"\n\n", readerName); sprintf_s(debugString, 2047, "Using reader \"%s\"\n\n", readerName); DebugMessage(debugString); long ret = SCardConnectA(ctx, readerName, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &hCard, &protocol); CHECK_PCSC_RET("SCardConnect", ret); if (SCARD_S_SUCCESS == ret) { unsigned char recvBuf[258]; DWORD recvBufLen; for (int i = 0; i < apduCount; i++) { recvBufLen = (DWORD) sizeof(recvBuf); sendAPDU(hCard, apdus[i], recvBuf, &recvBufLen, NULL, 0, true); } ret = SCardDisconnect(hCard, SCARD_LEAVE_CARD); CHECK_PCSC_RET("SCardDisconnect", ret); } return 0; }
static const char *listReaders(SCARDCONTEXT ctx, char *readerList, size_t readerListSize, bool printList, int readerNr) { DWORD dwLen = (DWORD) readerListSize; const char *readerName = NULL; long ret = SCardListReadersA(ctx, NULL, readerList, &dwLen); CHECK_PCSC_RET("SCardListReaders", ret); if (SCARD_S_SUCCESS == ret) { if (dwLen < 2) printf("No reader found, exiting\n"); else { if (printList) printf("Reader list:\n"); int readerCount = 0; while (readerList[0] != '\0') { if (printList) printf(" %d : %s\n", readerCount, readerList); if (readerCount == readerNr) readerName = readerList; readerList += strlen(readerList) + 1; readerCount++; } } } if (readerNr > 0 && NULL == readerName) printf("ERR: readernr (%d) too high, not enough readers present\n", readerNr); return readerName; }
static int testListReadersA(SCARDCONTEXT hContext) { int errCount = 0; char staticBuf[2000]; DWORD staticLen = (DWORD) sizeof(staticBuf); long ret = SCardListReadersA(hContext, NULL, staticBuf, &staticLen); CHECK_PCSC_RET("SCardListReadersA(1)", ret); char *dynBuf = NULL; DWORD dynLen = 0; ret = SCardListReadersA(hContext, NULL, dynBuf, &dynLen); CHECK_PCSC_RET("SCardListReadersA(2)", ret); dynBuf = (char *) malloc(dynLen); ret = SCardListReadersA(hContext, NULL, dynBuf, &dynLen); CHECK_PCSC_RET("SCardListReadersA(1)", ret); #ifndef MAC_OS_X char *autoBuf = NULL; DWORD autoLen = SCARD_AUTOALLOCATE; ret = SCardListReadersA(hContext, NULL, (char*) &autoBuf, &autoLen); CHECK_PCSC_RET("SCardListReadersA(3)", ret); if (staticLen != dynLen || dynLen != autoLen) { printf("ERR: SCardListReadersA() returned buffers lengths of different size\n"); errCount++; } else if (memcmp(staticBuf, dynBuf, dynLen) != 0 || memcmp(dynBuf, autoBuf, dynLen) != 0) { printf("ERR: SCardListReadersA() returned different data\n"); errCount++; } ret = SCardFreeMemory(hContext, autoBuf); CHECK_PCSC_RET("SCardFreeMemory()", ret); #endif free(dynBuf); return errCount; }
static long sendAPDU(SCARDHANDLE hCard, const char *apdu, unsigned char *recvBuf, DWORD *recvBufLen, const char *chipNr, int idx, bool doDump) { unsigned char sendBuf[280]; size_t sendBufLen = sizeof(sendBuf); // Hex string -> byte array if (0 == hex2bin(apdu, sendBuf, &sendBufLen)) { // Check the APDU if (sendBufLen < 4) { printf("ERR: APDU should be at least 4 bytes\n"); DebugMessage("ERR: APDU should be at least 4 bytes\n"); } else if (sendBufLen > 5 && (5 + sendBuf[4] != sendBufLen)) { printf("ERR: wrong P3 byte in case 3 APDU\n"); DebugMessage("ERR: wrong P3 byte in case 3 APDU\n"); } else { if (doDump) dumphex2(" - sending ", sendBuf, sendBufLen); #if TRANSMIT_DEBUG long ret = SCardTransmit2(hCard, &g_rgSCardT0Pci, sendBuf, (DWORD) sendBufLen, NULL, recvBuf, recvBufLen); #else long ret = SCardTransmit(hCard, &g_rgSCardT0Pci, sendBuf, (DWORD) sendBufLen, NULL, recvBuf, recvBufLen); #endif CHECK_PCSC_RET("SCardTransmit", ret); if (SCARD_S_SUCCESS == ret) { if (doDump) { dumphex2(" received ", recvBuf, *recvBufLen); printf("\n"); DebugMessage("\n"); } if (NULL != chipNr) StoreAPDUs(chipNr, idx, sendBuf, sendBufLen, recvBuf, *recvBufLen); return 0; // success } } } return -1; // failed }
static void getStatusChange(SCARDCONTEXT ctx, const char *readerList, DWORD timeout) { SCARD_READERSTATEA readerStates[MAX_READER_STATES]; int readerCount = 0; while (readerList[0] != '\0' && readerCount < MAX_READER_STATES) { readerStates[readerCount].szReader = readerList; readerStates[readerCount].dwCurrentState = SCARD_STATE_UNAWARE; readerList += strlen(readerList) + 1; readerCount++; } if (timeout == (DWORD) -1) { timeout = INFINITE; printf("Remove insert card(s) (or not) and hit ENTER\n"); printf("Or type 'q' stop\n\n"); } else printf("Remove insert card(s) or type Ctrl-C to stop\n\n"); char keybd = 0; while (keybd != 'q' && keybd != 'Q') { long ret = SCardGetStatusChangeA(ctx, timeout, readerStates, (DWORD) readerCount); if ((long) SCARD_S_SUCCESS != ret && (long) SCARD_E_TIMEOUT != ret) { CHECK_PCSC_RET("SCardGetStatusChange", ret); break; } if ((long) SCARD_E_TIMEOUT == ret) printf(" - timeout (nothing changed)\n"); else { for (int i = 0; i < readerCount; i++) { printState(&readerStates[i]); readerStates[i].dwCurrentState = readerStates[i].dwEventState & ~SCARD_STATE_CHANGED & ~SCARD_STATE_UNKNOWN; } } // Wait until the user hits a key if (timeout != (DWORD) -1) keybd = getchar(); } }
static std:: vector<BYTE> sendAPDU2(SCARDHANDLE hCard, const char *apdu, unsigned char *recvBuf, DWORD *recvBufLen, const char *chipNr, int idx, bool doDump) { unsigned char sendBuf[280]; size_t sendBufLen = sizeof(sendBuf); std:: vector<BYTE> result; // Hex string -> byte array if (0 == hex2bin(apdu, sendBuf, &sendBufLen)) { // Check the APDU if (sendBufLen < 4) { printf("ERR: APDU should be at least 4 bytes\n"); DebugMessage("ERR: APDU should be at least 4 bytes\n"); } else if (sendBufLen > 5 && (size_t) (5 + sendBuf[4]) != sendBufLen) { printf("ERR: wrong P3 byte in case 3 APDU\n"); DebugMessage("ERR: wrong P3 byte in case 3 APDU\n"); } else { if (doDump) dumphex2(" - sending ", sendBuf, sendBufLen); //long ret = SCardTransmit(hCard,&g_rgSCardT0Pci, sendBuf, (DWORD) sendBufLen,NULL, recvBuf, recvBufLen); long ret = SCardTransmit2(hCard, &g_rgSCardT0Pci, sendBuf, (DWORD) sendBufLen, NULL, recvBuf, recvBufLen); CHECK_PCSC_RET("SCardTransmit", ret); if (SCARD_S_SUCCESS == ret) { for (int i = 0; i < (int) *recvBufLen; i++) { result.push_back(recvBuf[i]); } dumphex2(" - received ", recvBuf, (int) *recvBufLen); return result; // success } } } return result; // failed }
static int testListReadersW(SCARDCONTEXT hContext) { int errCount = 0; wchar_t staticBuf[2000]; DWORD staticLen = (DWORD) (sizeof(staticBuf) / sizeof(wchar_t)); long ret = SCardListReadersW(hContext, NULL, staticBuf, &staticLen); CHECK_PCSC_RET("SCardListReadersW(1)", ret); wchar_t *dynBuf = NULL; DWORD dynLen = 0; ret = SCardListReadersW(hContext, NULL, dynBuf, &dynLen); CHECK_PCSC_RET("SCardListReadersW(2)", ret); dynBuf = (wchar_t *) malloc(dynLen * sizeof(wchar_t)); ret = SCardListReadersW(hContext, NULL, dynBuf, &dynLen); CHECK_PCSC_RET("SCardListReadersW(3)", ret); wchar_t *autoBuf = NULL; DWORD autoLen = SCARD_AUTOALLOCATE; ret = SCardListReadersW(hContext, NULL, (wchar_t*) &autoBuf, &autoLen); CHECK_PCSC_RET("SCardListReadersW(4)", ret); wchar_t *auto2Buf = NULL; DWORD auto2Len = SCARD_AUTOALLOCATE; ret = SCardListReadersW(hContext, NULL, (wchar_t*) &auto2Buf, &auto2Len); CHECK_PCSC_RET("SCardListReadersW(5)", ret); if (staticLen != dynLen || dynLen != autoLen || dynLen != auto2Len) { printf("ERR: SCardListReadersW() returned buffers lengths of different size\n"); printf(" (staticLen = %d, dynLen = %d, autoLen = %d, auto2Len = %d\n", staticLen, dynLen, autoLen, auto2Len); errCount++; } else if (memcmp(staticBuf, dynBuf, dynLen) != 0 || memcmp(dynBuf, autoBuf, dynLen) != 0 || memcmp(dynBuf, auto2Buf, dynLen) != 0) { printf("ERR: SCardListReadersW() returned different data\n"); dump(" staticBuf = '%S'\n", staticBuf, dynLen); dump(" dynBuf = '%S'\n", dynBuf, dynLen); dump(" autoBuf = '%S'\n", autoBuf, dynLen); dump(" auto2Buf = '%S'\n", auto2Buf, dynLen); errCount++; } free(dynBuf); ret = SCardFreeMemory(hContext, autoBuf); CHECK_PCSC_RET("SCardFreeMemory()", ret); return errCount; }
static int testCardFunctionality(SCARDCONTEXT ctx, const char *readerName) { SCARDHANDLE hCard; DWORD protocol; int errCount = 0; printf("Using reader \"%s\"\n\n", readerName); long ret = SCardConnectA(ctx, readerName, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &hCard, &protocol); CHECK_PCSC_RET("SCardConnect", ret); if (SCARD_S_SUCCESS == ret) { delayMS(200); printf("--- Get Response tests ---\n"); errCount += testGetResponse(hCard); printf("\n--- Get Response tests within a transaction ---\n"); ret = SCardBeginTransaction(hCard); CHECK_PCSC_RET("SCardBeginTransaction", ret); errCount += testGetResponse(hCard); ret = SCardEndTransaction(hCard, SCARD_LEAVE_CARD); CHECK_PCSC_RET("SCardBeginTransaction", ret); printf("\n--- Test reading a long file ---\n"); errCount += testLongFileRead(hCard); printf("\n--- Test reading a long file within a transaction ---\n"); ret = SCardBeginTransaction(hCard); CHECK_PCSC_RET("SCardBeginTransaction", ret); errCount += testLongFileRead(hCard); ret = SCardEndTransaction(hCard, SCARD_LEAVE_CARD); CHECK_PCSC_RET("SCardBeginTransaction", ret); printf("\n--- Misc tests ---\n"); errCount += testMisc(hCard); ret = SCardDisconnect(hCard, SCARD_LEAVE_CARD); CHECK_PCSC_RET("SCardDisconnect", ret); } if (errCount == 0) printf("\nFunctional tests done, no errors\n"); else printf("\nFunctional tests done, %d errors\n", errCount); return 0; }
static int testScardReconnect(SCARDCONTEXT hCard, DWORD dwShareMode, DWORD dwPreferredProtocols) { int ret = 0; int errCount = 0; DWORD dwAP = 0; for (int i = 0; i < 2; i++) { ret = SCardReconnect(hCard, dwShareMode, dwPreferredProtocols, SCARD_RESET_CARD, &dwAP); if (SCARD_S_SUCCESS != ret) { printf("ERR: SCardReconnect(RESET) failed: 0x%0x (%d)\n", ret, ret); errCount++; } ret = SCardReconnect(hCard, dwShareMode, dwPreferredProtocols, SCARD_UNPOWER_CARD, &dwAP); if (SCARD_S_SUCCESS != ret) { printf("ERR: SCardReconnect(UNPOWER) failed: 0x%0x (%d)\n", ret, ret); errCount++; } ret = SCardReconnect(hCard, dwShareMode, dwPreferredProtocols, SCARD_LEAVE_CARD, &dwAP); if (SCARD_S_SUCCESS != ret) { printf("ERR: SCardReconnect(LEAVE) failed: 0x%0x (%d)\n", ret, ret); errCount++; } unsigned char recvBuf[2]; DWORD recvBufLen = (DWORD) sizeof(recvBuf); ret = sendAPDU(hCard, "00:A4:04:0C:0C:A0:00:00:01:77:50:4B:43:53:2D:31:35", recvBuf, &recvBufLen); CHECK_PCSC_RET("sendAPDU(Get Card Data)", ret); } return errCount; }
static int testSCardState(SCARDCONTEXT hCard) { int errCount = 0; DWORD dwState = 0; DWORD dwProt = 0; BYTE tucAtr[32]; DWORD dwAtrLen = (DWORD) sizeof(tucAtr); int ret = SCardState(hCard, &dwState, &dwProt, tucAtr, &dwAtrLen); CHECK_PCSC_RET("SCardState()", ret); if (dwState == 0) { printf("ERR: SCardState(): dwState not filled in\n"); errCount++; } if (dwProt != SCARD_PROTOCOL_T0) { printf("ERR: SCardState(): dwProtocol should be SCARD_PROTOCOL_T0 (as least for a BE eID test)\n"); errCount++; } if (dwAtrLen < 8) { printf("ERR: SCardState(): ATR length looks too small (%d) for a BE eID card\n", dwAtrLen); errCount++; } else if (tucAtr[0] != 0x3B) { printf("ERR: SCardState(): ATR should start with 0x3B (instead of 0x%0x) for a BE eID card\n", tucAtr[0]); errCount++; } return errCount; }
static int testAPDUS(SCARDCONTEXT ctx, const char *readerName, const char *chipnrForCompare) { SCARDHANDLE hCard; DWORD protocol; int err = 0; int errCount = 0; printf("Using reader \"%s\"\n\n", readerName); long ret = SCardConnectA(ctx, readerName, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &hCard, &protocol); CHECK_PCSC_RET("SCardConnect", ret); if (SCARD_S_SUCCESS == ret) { delayMS(200); unsigned char recvBuf[258]; DWORD recvBufLen = sizeof(recvBuf); // If chipnrForCompare == NULL then we retrieve the chip number // of this card to store all APDUs const char *thisChipNr = NULL; char chipNrBuf[2 * CHIP_NR_LEN + 1]; if (NULL == chipnrForCompare) { thisChipNr = GetChipNrFromCard(hCard, chipNrBuf); if (NULL == thisChipNr) { SCardDisconnect(hCard, SCARD_LEAVE_CARD); return -1; } } // Send all APDUs for (int i = 0; fixedTestAPDUS[i] != NULL; i++) { recvBufLen = (DWORD) sizeof(recvBuf); ret = sendAPDU(hCard, fixedTestAPDUS[i], recvBuf, &recvBufLen, thisChipNr, i, NULL == chipnrForCompare); if (0 == ret && NULL != chipnrForCompare) { err = compareAPDUS(fixedTestAPDUS[i], recvBuf, recvBufLen, chipnrForCompare, i); if (err < 0) break; errCount += err; } } ret = SCardDisconnect(hCard, SCARD_LEAVE_CARD); CHECK_PCSC_RET("SCardDisconnect", ret); if (NULL == chipnrForCompare) printf("Done, stored APDUs to files who's names start with %s\n", thisChipNr); else if (err >= 0) printf("APDU Tests done, %d differences with chip %s)\n", errCount, chipnrForCompare); } return 0; }
static std:: vector<BYTE> sendAPDU(const char *apdu) { SCARDHANDLE hCard; unsigned char *recvBuf; //char debugString[2048]; unsigned char sendBuf[280]; size_t sendBufLen = sizeof(sendBuf); std:: vector<BYTE> result; SCARDCONTEXT ctx; const char *readerName; long ret = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &ctx); CHECK_PCSC_RET("SCardEstablishContext", ret); if (SCARD_S_SUCCESS == ret) { char readerList[2000]; readerName = listReaders(ctx, readerList, sizeof(readerList), true, -1); DWORD protocol; char *chipnrForCompare = NULL; long ret = SCardConnectA(ctx, readerName, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &hCard, &protocol); CHECK_PCSC_RET("SCardConnect", ret); if (SCARD_S_SUCCESS == ret) { DWORD recvBufLen = sizeof(recvBuf); unsigned char recvBuf[258]; // If chipnrForCompare == NULL then we retrieve the chip number // of this card to store all APDUs const char *thisChipNr = NULL; char chipNrBuf[2 * CHIP_NR_LEN + 1]; if (NULL == chipnrForCompare) { thisChipNr = GetChipNrFromCard(hCard, chipNrBuf); if (NULL == thisChipNr) { SCardDisconnect(hCard, SCARD_LEAVE_CARD); //return -1; } } //if (NULL == chipnrForCompare) recvBufLen = (DWORD) sizeof(recvBuf); //0x00000102 if (0 == hex2bin(apdu, sendBuf, &sendBufLen)) { // Check the APDU if (sendBufLen < 4) { printf("ERR: APDU should be at least 4 bytes\n"); DebugMessage("ERR: APDU should be at least 4 bytes\n"); } else if (sendBufLen > 5 && (size_t) (5 + sendBuf[4]) != sendBufLen) { printf("ERR: wrong P3 byte in case 3 APDU\n"); DebugMessage("ERR: wrong P3 byte in case 3 APDU\n"); } else { long ret = SCardTransmit2(hCard, &g_rgSCardT0Pci, sendBuf, (DWORD) sendBufLen, NULL, recvBuf, &recvBufLen); if (SCARD_S_SUCCESS == ret) { for (int i = 0; i < (int) recvBufLen; i++) { result.push_back(recvBuf[i]); } return result; // success } } } } } return result; // failed }
static int testCardFunctionality(SCARDCONTEXT ctx, const char *readerName) { SCARDHANDLE hCard; DWORD protocol; int errCount = 0; printf("Using reader \"%s\"\n\n", readerName); printf("NOTE: make sure no-one else is accessing the card!\n\n"); long ret = SCardConnectA(ctx, readerName, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &hCard, &protocol); CHECK_PCSC_RET("SCardConnect", ret); if (SCARD_S_SUCCESS == ret) { delayMS(200); printf("--- SCardReconnect tests ---\n"); errCount += testScardReconnect(hCard, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0); #ifdef _WIN32 printf("\n--- SCardState tests ---\n"); errCount += testSCardState(hCard); #endif printf("\n--- SCardStatus tests ---\n"); errCount += testSCardStatus(hCard); #ifndef MAC_OS_X printf("\n--- SCardGetAttrib tests ---\n"); errCount += testSCardGetAttrib(ctx, hCard); #endif printf("\n--- Get Response tests ---\n"); errCount += testGetResponse(hCard); printf("\n--- Get Response tests within a transaction ---\n"); ret = SCardBeginTransaction(hCard); CHECK_PCSC_RET("SCardBeginTransaction", ret); errCount += testGetResponse(hCard); ret = SCardEndTransaction(hCard, SCARD_LEAVE_CARD); CHECK_PCSC_RET("SCardBeginTransaction", ret); printf("\n--- Test reading a long file ---\n"); errCount += testLongFileRead(hCard); printf("\n--- Test reading a long file within a transaction ---\n"); ret = SCardBeginTransaction(hCard); CHECK_PCSC_RET("SCardBeginTransaction", ret); errCount += testLongFileRead(hCard); ret = SCardEndTransaction(hCard, SCARD_LEAVE_CARD); CHECK_PCSC_RET("SCardBeginTransaction", ret); printf("\n--- Misc tests ---\n"); errCount += testMisc(hCard); printf("\n--- Test ListReaders ---\n"); errCount += testListReaders(ctx); ret = SCardDisconnect(hCard, SCARD_LEAVE_CARD); CHECK_PCSC_RET("SCardDisconnect", ret); } if (errCount == 0) printf("\nFunctional tests done, no errors\n"); else printf("\nFunctional tests done, %d errors\n", errCount); return 0; }
int main(int argc, const char **argv) { Params params; SCARDCONTEXT ctx; int returnValue = 0; if (0 != parseCommandLine(argc, argv, ¶ms)) return -1; long ret = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &ctx); CHECK_PCSC_RET("SCardEstablishContext", ret); if (SCARD_S_SUCCESS == ret) { char readerList[2000]; #ifdef LOOP_LIST_READERS again: #endif const char *readerName = listReaders(ctx, readerList, sizeof(readerList), 'l' == params.command, params.readerNr); #ifdef LOOP_LIST_READERS if (params.command == 'l') { getchar(); goto again; } #endif if (NULL != readerName) { switch (params.command) { case 's': getStatusChange(ctx, readerList, params.timeout); break; case 'l': // already done in listReaders() break; case 'a': sendAPDUS(ctx, readerName, params.apduCount, params.apdus); break; case 'f': testCardFunctionality(ctx, readerName); break; case 't': testAPDUS(ctx, readerName, params.chipnr); break; case 'x': switch (params.test) { case 1: returnValue = testStatus(ctx, readerName, readerList); break; case 2: returnValue = testConnect(ctx, readerName); break; case 3: returnValue = testTransaction(ctx, readerName); break; case 4: returnValue = testTransmit(ctx, readerName, params.apdus); break; default: printf("Unknown -x parameter '%d', exiting\n", params.test); } break; default: printf("Unknown command '%c', exiting\n", params.command); } } } ret = SCardReleaseContext(ctx); return returnValue; }
static int testLongFileRead(SCARDCONTEXT hCard) { int ret = 0; int errCount = 0; unsigned char recvBuf[258]; DWORD recvBufLen = sizeof(recvBuf); // Select the file ret = sendAPDU(hCard, "00:A4:04:0C:0C:A0:00:00:01:77:50:4B:43:53:2D:31:35", recvBuf, &recvBufLen); CHECK_PCSC_RET("sendAPDU(select MF)", ret); ret = sendAPDU(hCard, "00:A4:02:0C:02:50:38", recvBuf, &recvBufLen); CHECK_PCSC_RET("sendAPDU(select 5038)", ret); // Get the file size char apdu[20]; int offs = 0; int fileLen = 0; for (; offs < 5000; offs += 0xfc) { sprintf(apdu, "00B0%02X%02XFC", offs / 256, offs % 256); recvBufLen = sizeof(recvBuf); ret = sendAPDU(hCard, apdu, recvBuf, &recvBufLen); CHECK_PCSC_RET("sendAPDU(Read Binary)", ret); if (recvBufLen == 2 && recvBuf[0] == 0x6c) { fileLen = offs + recvBuf[1]; break; } } // Read 1 byte at filesize - 1 sprintf(apdu, "00B0%02X%02X01", (fileLen - 1) / 256, (fileLen - 1) % 256); recvBufLen = sizeof(recvBuf); ret = sendAPDU(hCard, apdu, recvBuf, &recvBufLen); CHECK_PCSC_RET("sendAPDU(Read Binary)", ret); if (recvBufLen != 3 || recvBuf[1] != 0x90 || recvBuf[2] != 0x00) { printf("ERR: ReadBinary(offset = filesize-1, len = 1) didn't return 1 byte\n"); errCount++; } // Read 1 byte at filesize sprintf(apdu, "00B0%02X%02X01", (fileLen) / 256, (fileLen) % 256); recvBufLen = sizeof(recvBuf); ret = sendAPDU(hCard, apdu, recvBuf, &recvBufLen); CHECK_PCSC_RET("sendAPDU(Read Binary)", ret); if (recvBufLen != 2 || recvBuf[0] != 0x6B || recvBuf[1] != 0x00) { printf("ERR: ReadBinary(offset = filesize, len = 1) didn't return 6B 00\n"); errCount++; } // Read 1 byte at filesize + 1 sprintf(apdu, "00B0%02X%02X01", (fileLen + 1) / 256, (fileLen + 1) % 256); recvBufLen = sizeof(recvBuf); ret = sendAPDU(hCard, apdu, recvBuf, &recvBufLen); CHECK_PCSC_RET("sendAPDU(Read Binary)", ret); if (recvBufLen != 2 || recvBuf[0] != 0x6B || recvBuf[1] != 0x00) { printf("ERR: ReadBinary(offset = filesize+1, len = 1) didn't return 6B 00\n"); errCount++; } return errCount; }
static int testGetResponse(SCARDCONTEXT hCard) { int ret = 0; int errCount = 0; unsigned char recvBuf[258]; DWORD recvBufLen = sizeof(recvBuf); ////////////////////// Tests on the virtual card //////////////////// // If the 1st command is a "Get Card Data", it's no possible to // do a "Get Response" to it. So we first do a "Select". ret = sendAPDU(hCard, "00:A4:04:0C:0C:A0:00:00:01:77:50:4B:43:53:2D:31:35", recvBuf, &recvBufLen); CHECK_PCSC_RET("sendAPDU(Get Card Data)", ret); // Get Card Data, only 16 bytes out of the 28 recvBufLen = sizeof(recvBuf); ret = sendAPDU(hCard, "80:E4:00:00:10", recvBuf, &recvBufLen); CHECK_PCSC_RET("sendAPDU(Get Card Data)", ret); if (recvBufLen != 18 || recvBuf[recvBufLen - 2] != 0x61 || recvBuf[recvBufLen - 1] != 0x0C) { printf("ERR: Get Response didn't return 61 0C\n"); errCount++; } // Get Response, 11 bytes (so 1 byte left afterwards) ret = sendAPDU(hCard, "00:C0:00:00:0B", recvBuf, &recvBufLen); CHECK_PCSC_RET("sendAPDU(Get Card Data)", ret); if (recvBufLen != 13 || recvBuf[recvBufLen - 2] != 0x61 || recvBuf[recvBufLen - 1] != 0x01) { printf("ERR: Get Response didn't return 61 01\n"); errCount++; } // Get Response, 1 byte (so no byte left afterwards) ret = sendAPDU(hCard, "00:C0:00:00:01", recvBuf, &recvBufLen); CHECK_PCSC_RET("sendAPDU(Get Card Data)", ret); if (recvBufLen != 3 || recvBuf[recvBufLen - 2] != 0x90 || recvBuf[recvBufLen - 1] != 0x00) { printf("ERR: Get Response didn't return 90 00\n"); errCount++; } // Get Response, 1 byte (but no bytes left) ret = sendAPDU(hCard, "00:C0:00:00:01", recvBuf, &recvBufLen); CHECK_PCSC_RET("sendAPDU(Get Card Data)", ret); if (recvBufLen != 2 || recvBuf[0] != 0x6D || recvBuf[1] != 0x00) { printf("ERR: Get Response didn't return 6D 00\n"); errCount++; } /////////////////////// Tests on the real card ///////////////////// ret = sendAPDU(hCard, "00:20:00:01:08:24:12:34:FF:FF:FF:FF:FF", recvBuf, &recvBufLen); CHECK_PCSC_RET("sendAPDU(Verify PIN)", ret); ret = sendAPDU(hCard, "00:22:41:B6:05:04:80:01:84:82", recvBuf, &recvBufLen); CHECK_PCSC_RET("sendAPDU(MSE SET)", ret); ret = sendAPDU(hCard, "00:2A:9E:9A:08:11:22:33:44:55:66:77:88", recvBuf, &recvBufLen); CHECK_PCSC_RET("sendAPDU(Sign)", ret); // Get Response recvBufLen = sizeof(recvBuf); ret = sendAPDU(hCard, "00:C0:00:00:80", recvBuf, &recvBufLen); CHECK_PCSC_RET("sendAPDU(Get Card Data)", ret); if (recvBufLen != 0x82 || recvBuf[recvBufLen - 2] != 0x90 || recvBuf[recvBufLen - 1] != 0x00) { printf("ERR: Get Response didn't return 6D 00\n"); errCount++; } return errCount; }
static int testSCardStatusA(SCARDCONTEXT hCard) { int errCount = 0; DWORD dwState; DWORD dwProt; char staticReader[250]; DWORD staticReaderLen = (DWORD) sizeof(staticReader); BYTE staticAtr[32]; DWORD staticAtrLen = (DWORD) sizeof(staticAtr); long ret = SCardStatusA(hCard, (char *) &staticReader, &staticReaderLen, &dwState, &dwProt, staticAtr, &staticAtrLen); CHECK_PCSC_RET("SCardStatusA(1)", ret); char *dynReader = NULL; DWORD dynReaderLen = 0; BYTE *dynAtr = NULL; DWORD dynAtrLen = 0; ret = SCardStatusA(hCard, dynReader, &dynReaderLen, &dwState, &dwProt, dynAtr, &dynAtrLen); CHECK_PCSC_RET("SCardStatusA(2)", ret); dynReader = new char[staticReaderLen]; dynAtr = new BYTE[dynAtrLen]; ret = SCardStatusA(hCard, dynReader, &dynReaderLen, &dwState, &dwProt, dynAtr, &dynAtrLen); CHECK_PCSC_RET("SCardStatusA(3)", ret); #ifndef MAC_OS_X char *autoReader = NULL; DWORD autoReaderLen = SCARD_AUTOALLOCATE; BYTE *autoAtr = NULL; DWORD autoAtrLen = SCARD_AUTOALLOCATE; ret = SCardStatusA(hCard, (char *) &autoReader, &autoReaderLen, &dwState, &dwProt, (BYTE *) &autoAtr, &autoAtrLen); CHECK_PCSC_RET("SCardStatusA(4)", ret); if (staticReaderLen != dynReaderLen || dynReaderLen != autoReaderLen) { printf("ERR: SCardStatusA() returned buffers lengths of different reader size\n"); printf(" (staticLen = %d, dynLen = %d, autoLen = %d\n", (int) staticReaderLen, (int) dynReaderLen, (int) autoReaderLen); errCount++; } else if (memcmp(staticReader, dynReader, dynReaderLen) != 0 || memcmp(dynReader, autoReader, dynReaderLen) != 0) { printf("ERR: SCardStatusA() returned different reader names\n"); dump(" staticReader = '%s' (%d bytes)\n", staticReader, dynReaderLen); dump(" dynReader = '%s' (%d bytes)\n", dynReader, dynReaderLen); dump(" autoReader = '%s' (%d bytes)\n", autoReader, dynReaderLen); errCount++; } if (staticAtrLen != dynAtrLen || dynAtrLen != autoAtrLen) { printf("ERR: SCardStatusA() returned buffers lengths of different ATR size\n"); printf(" (staticLen = %d, dynLen = %d, autoLen = %d\n", (int) staticAtrLen, (int) dynAtrLen, (int) autoAtrLen); errCount++; } else if (memcmp(staticAtr, dynAtr, dynAtrLen) != 0 || memcmp(dynAtr, autoAtr, dynAtrLen) != 0) { printf("ERR: SCardStatusA() returned different ATRs\n"); errCount++; } #endif return errCount; }
static int testSCardStatusW(SCARDCONTEXT hCard) { int errCount = 0; DWORD dwState; DWORD dwProt; wchar_t staticReader[250]; DWORD staticReaderLen = (DWORD) (sizeof(staticReader) / sizeof(wchar_t)); BYTE staticAtr[32]; DWORD staticAtrLen = (DWORD) sizeof(staticAtr); long ret = SCardStatusW(hCard, staticReader, &staticReaderLen, &dwState, &dwProt, staticAtr, &staticAtrLen); CHECK_PCSC_RET("SCardStatusW(1)", ret); wchar_t *dynReader = NULL; DWORD dynReaderLen = 0; BYTE *dynAtr = NULL; DWORD dynAtrLen = 0; ret = SCardStatusW(hCard, dynReader, &dynReaderLen, &dwState, &dwProt, dynAtr, &dynAtrLen); CHECK_PCSC_RET("SCardStatusW(2)", ret); dynReader = new wchar_t[staticReaderLen]; dynAtr = new BYTE[dynAtrLen]; ret = SCardStatusW(hCard, dynReader, &dynReaderLen, &dwState, &dwProt, dynAtr, &dynAtrLen); CHECK_PCSC_RET("SCardStatusW(3)", ret); wchar_t *autoReader = NULL; DWORD autoReaderLen = SCARD_AUTOALLOCATE; BYTE *autoAtr = NULL; DWORD autoAtrLen = SCARD_AUTOALLOCATE; ret = SCardStatusW(hCard, (wchar_t *) &autoReader, &autoReaderLen, &dwState, &dwProt, (BYTE *) &autoAtr, &autoAtrLen); CHECK_PCSC_RET("SCardStatusW(4)", ret); wchar_t *auto2Reader = (wchar_t *) 1; DWORD auto2ReaderLen = SCARD_AUTOALLOCATE; BYTE *auto2Atr = (BYTE *) 2; DWORD auto2AtrLen = SCARD_AUTOALLOCATE; ret = SCardStatusW(hCard, (wchar_t *) &auto2Reader, &auto2ReaderLen, &dwState, &dwProt, (BYTE *) &auto2Atr, &auto2AtrLen); CHECK_PCSC_RET("SCardStatusW(5)", ret); if (staticReaderLen != dynReaderLen || dynReaderLen != autoReaderLen || auto2ReaderLen != autoReaderLen) { printf("ERR: SCardStatusW() returned buffers lengths of different reader size\n"); printf(" (staticLen = %d, dynLen = %d, autoLen = %d, autoLen = %d\n", (int) staticReaderLen, (int) dynReaderLen, (int) autoReaderLen, (int) auto2ReaderLen); errCount++; } else if (memcmp(staticReader, dynReader, dynReaderLen) != 0 || memcmp(dynReader, autoReader, dynReaderLen) != 0 || memcmp(dynReader, auto2Reader, dynReaderLen) != 0) { printf("ERR: SCardStatusW() returned different reader names\n"); dump(" staticReader = '%S'\n", staticReader, dynReaderLen); dump(" dynReader = '%S'\n", dynReader, dynReaderLen); dump(" autoReader = '%S'\n", autoReader, dynReaderLen); dump(" auto2Reader = '%S'\n", auto2Reader, dynReaderLen); errCount++; } if (staticAtrLen != dynAtrLen || dynAtrLen != autoAtrLen || dynAtrLen != auto2AtrLen) { printf("ERR: SCardStatusA() returned buffers lengths of different ATR size\n"); printf(" (staticLen = %d, dynLen = %d, autoLen = %d, auto2Len = %d\n", (int) staticAtrLen, (int) dynAtrLen, (int) autoAtrLen, (int) auto2AtrLen); errCount++; } else if (memcmp(staticAtr, dynAtr, dynAtrLen) != 0 || memcmp(dynAtr, autoAtr, dynAtrLen) != 0 || memcmp(dynAtr, auto2Atr, dynAtrLen) != 0) { printf("ERR: SCardStatusA() returned different ATRs\n"); errCount++; } return errCount; }