Skip to content

Instantly share code, notes, and snippets.

@yoe
Last active October 9, 2018 15:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yoe/cefe152fcc560002aefd82f235b486ea to your computer and use it in GitHub Desktop.
Save yoe/cefe152fcc560002aefd82f235b486ea to your computer and use it in GitHub Desktop.
tool to quickly send some APDUs to a smartcard using PC/SC
#include <stdio.h>
#include <PCSC/winscard.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <getopt.h>
const struct option options[] = {
{"reader", required_argument, 0, 'r'},
{"apdu", required_argument, 0, 'a'},
{NULL, 0, 0, 0},
};
static LPCSCARD_IO_REQUEST ioreq;
SCARDHANDLE openReader(SCARDCONTEXT ctx, int which, SCARDHANDLE oldhandle) {
static LPSTR readers = NULL;
LPSTR ptr;
DWORD readerlen = SCARD_AUTOALLOCATE;
int counter = 0;
LONG r;
SCARDHANDLE handle;
DWORD active;
if(!readers) {
SCardListReaders(ctx, NULL, (LPSTR)&readers, &readerlen);
}
if(oldhandle) {
SCardDisconnect(oldhandle, SCARD_LEAVE_CARD);
}
ptr = readers;
while(*ptr) {
if(which < 0 || counter == which) {
r = SCardConnect(ctx, ptr, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &handle, &active);
if(r != SCARD_S_SUCCESS) {
if(counter == which) {
fprintf(stderr, "E: Could not connect to card reader %d %s: %x\n", which, ptr, r);
exit(EXIT_FAILURE);
}
} else {
printf("Connected to smart card reader %s\n", ptr);
ioreq = (active == SCARD_PROTOCOL_T0 ? SCARD_PCI_T0 : SCARD_PCI_T1);
return handle;
}
}
ptr += strlen(ptr) + 1;
counter++;
}
fprintf(stderr, "E: Could not find a suitable reader\n");
exit(EXIT_FAILURE);
}
void performApdu(SCARDHANDLE h, char *apduString) {
size_t len = strlen(apduString);
char apduBytes[(len/2) + 1];
unsigned char recvBytes[300] = {0};
DWORD recvlen = sizeof(recvBytes) - 1;
LONG r;
printf("Attempting to send APDU %s\n", apduString);
apduBytes[len/2] = 0;
for(int i=0; i<len/2; i++) {
char hexbyte[3] = {0};
char *loc;
hexbyte[0] = apduString[i*2];
hexbyte[1] = apduString[i*2+1];
apduBytes[i] = strtol(hexbyte, &loc, 16);
if(loc != &(hexbyte[2])) {
fprintf(stderr, "E: Invalid hexadecimal character found, cannot continue\n");
exit(EXIT_FAILURE);
}
}
r = SCardTransmit(h, ioreq, apduBytes, (len / 2), NULL, recvBytes, &recvlen);
if(r != SCARD_S_SUCCESS) {
fprintf(stderr, "E: Could not transmit %s: %x\n", apduString, r);
exit(EXIT_FAILURE);
}
printf("SW12: %02X %02X\n", recvBytes[recvlen - 2], recvBytes[recvlen - 1]);
if(recvlen > 2) {
int i;
for(i = 0; i <= (recvlen - 2) / 8; i++) {
for(int j = 0; j < 8 && i * 8 + j < (recvlen - 2); j++) {
printf("%02X ", recvBytes[i * 8 + j]);
}
printf(i % 2 ? "\n" : " ");
}
if(i % 2) {
printf("\n");
}
}
}
int main(int argc, char**argv) {
SCARDCONTEXT ctx;
SCARDHANDLE handle = 0;
int c;
SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &ctx);
while((c = getopt_long(argc, argv, "a:r:", options, &optind)) > 0) {
switch(c) {
case 'a':
if(!handle) {
handle = openReader(ctx, -1, 0);
}
performApdu(handle, optarg);
break;
case 'r':
handle = openReader(ctx, strtol(optarg, NULL, 10), handle);
break;
}
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment