Skip to content

Instantly share code, notes, and snippets.

@leifj
Created October 17, 2016 19:24
Show Gist options
  • Save leifj/140f9c79d99af078c5167f587cd81b69 to your computer and use it in GitHub Desktop.
Save leifj/140f9c79d99af078c5167f587cd81b69 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#include <winscard.h>
#define CHECK(f, rv) \
if (SCARD_S_SUCCESS != rv) \
{ \
fprintf(stderr, f ": %s\n", pcsc_stringify_error(rv)); \
return -1; \
}
#define CHECK_RESPONSE(buffer, bufferLength) \
if(buffer[bufferLength-2] != 0x90 || buffer[bufferLength-1] != 0x00) { \
fprintf(stderr, "Invalid response!\n"); \
return -2; \
}
int main(int argc, char *argv[]) {
LONG rv;
SCARDCONTEXT hContext;
SCARDHANDLE hCard;
DWORD dwReaders, dwActiveProtocol, dwRecvLength;
LPTSTR mszReaders;
SCARD_IO_REQUEST pioSendPci;
BYTE pbRecvBuffer[266];
unsigned int i;
fprintf(stderr, "Smart Card reader - terciofilho - hashtips.wordpress.com\n");
BYTE cmdDefineCardType[] = { 0xFF, 0xA4, 0x00, 0x00, 0x01, 0x06 };
BYTE cmdReadCard[] = { 0xFF, 0xB0, 0x00, 0x20, 0xC0 };
if(argc != 3)
{
fprintf(stderr, "Usage: %s FIRST_ADDRESS READ_LENGTH\nNo parameters provided, default values:\nFIRST_ADDRESS = 0x%X\
nREAD_LENGTH = 0x%X\n", argv[0], cmdReadCard[3], cmdReadCard[4]);
}
else
{
if(strtol(argv[2], NULL, 16) > 256)
{
fprintf(stderr, "Invalid READ_LENGTH. Must be < 256.\n");
return -3;
}
cmdReadCard[3] = strtol(argv[1], NULL, 16);
cmdReadCard[4] = strtol(argv[2], NULL, 16);
fprintf(stderr, "FIRST_ADDRESS = 0x%02x\nREAD_LENGTH = 0x%02x\n", cmdReadCard[3], cmdReadCard[4]);
}
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
CHECK("SCardEstablishContext", rv);
dwReaders = SCARD_AUTOALLOCATE;
rv = SCardListReaders(hContext, NULL, (LPTSTR)&mszReaders, &dwReaders);
CHECK("SCardListReaders", rv)
fprintf(stderr, "Reader name: %s\n", mszReaders);
rv = SCardConnect(hContext, mszReaders, SCARD_SHARE_DIRECT, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol);
//rv = SCardConnect(hContext, mszReaders, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1 | SCARD_PROTOCOL_RAW, &hCard, &dwActiveProtocol);
CHECK("SCardConnect", rv)
switch(dwActiveProtocol)
{
case SCARD_PROTOCOL_T0:
fprintf(stderr, "T0\n");
pioSendPci = *SCARD_PCI_T0;
break;
case SCARD_PROTOCOL_T1:
fprintf(stderr, "T1\n");
pioSendPci = *SCARD_PCI_T1;
break;
case SCARD_PROTOCOL_RAW:
fprintf(stderr, "RAW\n");
pioSendPci = *SCARD_PCI_RAW;
break;
default:
fprintf(stderr, "active protocol: %lu", dwActiveProtocol);
break;
}
dwRecvLength = sizeof(pbRecvBuffer);
rv = SCardTransmit(hCard, &pioSendPci, cmdDefineCardType, sizeof(cmdDefineCardType), NULL, pbRecvBuffer, &dwRecvLength);
CHECK("SCardTransmit (define card type)", rv)
CHECK_RESPONSE(pbRecvBuffer, dwRecvLength);
dwRecvLength = sizeof(pbRecvBuffer);
rv = SCardTransmit(hCard, &pioSendPci, cmdReadCard, sizeof(cmdReadCard), NULL, pbRecvBuffer, &dwRecvLength);
CHECK("SCardTransmit (read card)", rv)
CHECK_RESPONSE(pbRecvBuffer, dwRecvLength);
for(i=0; i<dwRecvLength-2; i++)
printf("%c", pbRecvBuffer[i]);
rv = SCardDisconnect(hCard, SCARD_LEAVE_CARD);
CHECK("SCardDisconnect", rv);
rv = SCardFreeMemory(hContext, mszReaders);
CHECK("SCardFreeMemory", rv);
rv = SCardReleaseContext(hContext);
CHECK("SCardReleaseContext", rv);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment