diff --git a/picc_to_pcsc/src/picc_to_pcsc.c b/picc_to_pcsc/src/picc_to_pcsc.c index 7a203b7..95a0a68 100644 --- a/picc_to_pcsc/src/picc_to_pcsc.c +++ b/picc_to_pcsc/src/picc_to_pcsc.c @@ -15,148 +15,166 @@ #include "picc_to_pcsc.h" #include "pcscutil.h" -static FILE *fd; /*filehandle used for PICCDEV*/ +static FILE *picc_fd = 0; /*filehandle used for PICCDEV*/ + +static LPSTR readers = NULL; +static SCARDCONTEXT hContext = 0; +static SCARDHANDLE hCard = 0; static sighandler_t register_sig(int signo, sighandler_t sighandler) { - struct sigaction new_sig, old_sig; - - new_sig.sa_handler = sighandler; - sigemptyset (&new_sig.sa_mask); - new_sig.sa_flags = SA_RESTART; - if (sigaction (signo, &new_sig, &old_sig) < 0) - return SIG_ERR; - return old_sig.sa_handler; } -void checkSig(int signo){ - if (signo == SIGINT) - printf("Received SIGINT, exiting.\n"); - cleanup(); +void cleanup_exit(int signo){ + cleanup(); + exit(0); } void cleanup(void) { - /*Close the device*/ - fclose(fd); - /*Die*/ - exit(0); + fclose(picc_fd); + pcsc_disconnect(hContext, hCard, readers); } -int picc_decode(char *inbuf, size_t inlen, - unsigned char **outbuf, size_t *outlen) +size_t picc_decode_apdu(char *inbuf, size_t inlen, unsigned char **outbuf) { - size_t pos; - unsigned char buf[0xffff]; - char *end, *p; - unsigned long int b, length; + size_t pos, length; + unsigned char buf[0xffff]; + char *end, *p; + unsigned long int b; - if (inbuf == NULL || inlen == 0 || inbuf[0] == '\0') { - //Ignore empty lines and 'RESET' lines - *outlen = 0; - return 0; + if (inbuf == NULL || inlen == 0 || inbuf[0] == '\0') { + //Ignore empty lines and 'RESET' lines + goto noapdu; + } + + length = strtoul(inbuf, &end, 16); + + /* check for ':' right behind the length */ + if (inbuf+inlen < end+1 || end[0] != ':') + goto noapdu; + end++; + + p = realloc(*outbuf, length); + if (!p) { + fprintf(stderr, "Error allocating memory for decoded C-APDU\n"); + goto noapdu; + } + *outbuf = p; + + pos = 0; + while(inbuf+inlen > end && length > pos) { + b = strtoul(end, &end, 16); + if (b > 0xff) { + fprintf(stderr, "%s:%u Error decoding C-APDU\n", __FILE__, __LINE__); + goto noapdu; } - errno = 0; - length = strtoul(inbuf, &end, 16); - if (errno) - goto err; + (*outbuf)[pos++] = b; + } - /* check for ':' right behind the length */ - if (inbuf+inlen < end+1 || end[0] != ':') - goto err; - end++; + return length; - p = realloc(*outbuf, length); - if (!p) - goto err; - *outbuf = p; - *outlen = length; - - pos = 0; - while(inbuf+inlen > end && length > pos) { - b = strtoul(end, &end, 16); - if (errno || b > 0xff) - goto err; +noapdu: + return 0; +} - (*outbuf)[pos++] = b; - } +size_t picc_encode_rapdu(unsigned char *inbuf, size_t inlen, char **outbuf) +{ + char *p; + unsigned char *next; + size_t length; - return 0; + if (!inbuf || inlen > 0xffff) + goto err; + + length = inlen*3+5; + p = realloc(*outbuf, length); + if (!p) { + fprintf(stderr, "Error allocating memory for encoded R-APDU\n"); + goto err; + } + *outbuf = p; + + sprintf(*outbuf, "%04X:", inlen); + + next = inbuf; + /* let p point behind ':' */ + p += 5; + while (inbuf+inlen > next) { + sprintf(p," %02X",*next); + next++; + p += 3; + } + + return length; err: - *outlen = 0; - return -1; -} - -void write_to_device(unsigned char *buffer, unsigned int msgLength) { - char* foo; - foo = (char*) malloc(msgLength*3+5); - //fprintf(fd, "%04X:", msgLength); - sprintf(foo,"%04X:",msgLength); - int i; - for(i=0; i 1) { + readernum = strtoul(argv[1], NULL, 10); if (argc > 2) { - fprintf(stderr, "Usage: " - "%s [reader number] [PIN]\n", argv[0]); - } - if (sscanf(argv[1], "%u", &readernum) != 1) { - fprintf(stderr, "Could not get number of reader\n"); - exit(2); + if (0 != strcmp(argv[2], "verbose") || argc > 3) { + fprintf(stderr, "Usage: " + "%s [reader number] [verbose]\n", argv[0]); + exit(2); + } + verbose++; } } - /*Register signal handlers*/ - register_sig(SIGINT,checkSig); + /* Register signal handlers */ + new_sig.sa_handler = cleanup_exit; + sigemptyset(&new_sig.sa_mask); + new_sig.sa_flags = SA_RESTART; + if (sigaction(SIGINT, &new_sig, &old_sig) < 0) + goto err; - /*Open the device*/ - fd = fopen(PICCDEV, "a+"); /*O_NOCTTY ?*/ - if (fd == NULL) { - fprintf(stderr,"Failed to open %s. Exiting.\n", PICCDEV); - exit(-1); - } else - printf("Initialisation completed\n"); + /* Open the device */ + picc_fd = fopen(PICCDEV, "a+"); /*O_NOCTTY ?*/ + if (!picc_fd) { + fprintf(stderr,"Error opening %s\n", PICCDEV); + goto err; + } + printf("Connected to %s\n", PICCDEV); + + + /* connect to reader and card */ r = pcsc_connect(readernum, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_ANY, &hContext, &readers, &hCard, &protocol); if (r != SCARD_S_SUCCESS) goto err; + while(1) { - linelen = getline(&read, &readlen, fd); + /* read C-APDU */ + linelen = getline(&read, &readlen, picc_fd); if (linelen < 0) { if (linelen < 0) { fprintf(stderr,"Error reading from %s\n", PICCDEV); @@ -165,28 +183,45 @@ int main (int argc, char **argv) } if (linelen == 0) continue; - fflush(fd); + fflush(picc_fd); - printf("%s\n", read); + if (verbose) + printf("%s\n", read); - if (picc_decode(read, linelen, &inputBuffer, &inputLength) < 0) + + /* decode C-APDU */ + buflen = picc_decode_apdu(read, linelen, (unsigned char **) &buf); + if (!buflen) continue; - printb("C-APDU:\n", inputBuffer, inputLength); + if (!verbose) + printb("C-APDU: ===================================================\n", buf, buflen); + + /* transmit APDU to card */ outputLength = MAX_BUFFER_SIZE; - r = pcsc_transmit(protocol, hCard, inputBuffer, inputLength, outputBuffer, &outputLength); + r = pcsc_transmit(protocol, hCard, buf, buflen, outputBuffer, &outputLength); if (r != SCARD_S_SUCCESS) goto err; - printb("R-APDU:\n", outputBuffer, outputLength); + if (!verbose) + printb("R-APDU:\n", outputBuffer, outputLength); - write_to_device(outputBuffer, outputLength); - //fprintf(fd,"0002: 90 00\0"); + + /* encode R-APDU */ + buflen = picc_encode_rapdu(outputBuffer, outputLength, (char **) &buf); + + + /* write R-APDU */ + if (verbose) + printf("INF: Writing R-APDU\n\n%s\n\n", buf); + + fprintf(picc_fd,"%s\r\n", buf); + fflush(picc_fd); } - cleanup(); err: + cleanup(); stringify_error(r); pcsc_disconnect(hContext, hCard, readers);