From 26f171873cd33a3c0b0c3a250199f9ba14ccf29e Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Mon, 3 Feb 2014 13:10:43 +0100 Subject: [PATCH] some working code for selecting applet --- cmdline.ggo | 1 + yubico-piv-tool.c | 158 ++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 148 insertions(+), 11 deletions(-) diff --git a/cmdline.ggo b/cmdline.ggo index a5ab464..ab10a26 100644 --- a/cmdline.ggo +++ b/cmdline.ggo @@ -25,3 +25,4 @@ # for the parts of OpenSSL used as well as that of the covered work. option "verbose" v "Print more information" flag off +option "reader" r "Only use a matching reader" string optional diff --git a/yubico-piv-tool.c b/yubico-piv-tool.c index b519a67..2f6577f 100644 --- a/yubico-piv-tool.c +++ b/yubico-piv-tool.c @@ -29,6 +29,8 @@ #include #include +#include +#include #ifdef __APPLE__ #include @@ -43,19 +45,145 @@ unsigned const char default_key[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; +#define KEY_LEN 24 -typedef struct { - unsigned char cla; - unsigned char ins; - unsigned char p1; - unsigned char p2; - unsigned char lc; +unsigned const char aid[] = { + 0xa0, 0x00, 0x00, 0x03, 0x08 +}; +#define AID_LEN 5 + +union u_APDU { + struct { + unsigned char cla; + unsigned char ins; + unsigned char p1; + unsigned char p2; + unsigned char lc; + unsigned char data[0xff]; + } st; + unsigned char raw[0xff + 5]; +}; + +typedef union u_APDU APDU; + +void dump_hex(unsigned const char*, unsigned int); +int send_data(SCARDHANDLE*, APDU, unsigned int, unsigned char*, unsigned long*, int); + +static bool connect_reader(SCARDHANDLE *card, SCARDCONTEXT *context, const char *wanted, int verbose) { + unsigned long num_readers; + unsigned long active_protocol; + char reader_buf[1024]; + long rc; + char *reader_ptr; + + rc = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, context); + if (rc != SCARD_S_SUCCESS) { + fprintf (stderr, "error: SCardEstablishContext failed, rc=%08lx\n", rc); + return false; + } + + rc = SCardListReaders(*context, NULL, NULL, &num_readers); + if (rc != SCARD_S_SUCCESS) { + fprintf (stderr, "error: SCardListReaders failed, rc=%08lx\n", rc); + SCardReleaseContext(*context); + return false; + } + + if (num_readers > sizeof(reader_buf)) { + num_readers = sizeof(reader_buf); + } + + rc = SCardListReaders(*context, NULL, reader_buf, &num_readers); + if (rc != SCARD_S_SUCCESS) + { + fprintf (stderr, "error: SCardListReaders failed, rc=%08lx\n", rc); + SCardReleaseContext(*context); + return false; + } + + reader_ptr = reader_buf; + if(wanted) { + while(*reader_ptr != '\0') { + if(strstr(reader_ptr, wanted)) { + if(verbose) { + printf("using reader '%s' matching '%s'.\n", reader_ptr, wanted); + } + break; + } else { + if(verbose) { + printf("skipping reader '%s' since it doesn't match.\n", reader_ptr); + } + reader_ptr += strlen(reader_ptr) + 1; + } + } + } + if(*reader_ptr == '\0') { + fprintf (stderr, "error: no useable reader found.\n"); + SCardReleaseContext(*context); + return false; + } + + rc = SCardConnect(*context, reader_ptr, SCARD_SHARE_SHARED, + SCARD_PROTOCOL_T1, card, &active_protocol); + if(rc != SCARD_S_SUCCESS) + { + fprintf (stderr, "error: SCardConnect failed, rc=%08lx\n", rc); + SCardReleaseContext(*context); + return false; + } + + return true; +} + +static bool select_applet(SCARDHANDLE *card, int verbose) { + APDU apdu; unsigned char data[0xff]; -} APDU; + unsigned long recv_len = sizeof(data); + int sw; -static void dump_hex(const unsigned char *buf, int len) { - int i; - printf("length: %d\n", len); + apdu.st.cla = 0x00; + apdu.st.ins = 0xa4; + apdu.st.p1 = 0x04; + apdu.st.p2 = 0x00; + apdu.st.lc = AID_LEN; + memcpy(apdu.st.data, aid, AID_LEN); + + sw = send_data(card, apdu, AID_LEN + 5, data, &recv_len, verbose); + if(sw == 0x9000) { + return true; + } + + return false; +} + +int send_data(SCARDHANDLE *card, APDU apdu, unsigned int send_len, unsigned char *data, unsigned long *recv_len, int verbose) { + long rc; + int sw; + + if(verbose) { + printf("sending data: (%d bytes)\n", send_len); + dump_hex(apdu.raw, send_len); + } + rc = SCardTransmit(*card, SCARD_PCI_T1, apdu.raw, send_len, NULL, data, recv_len); + if(rc != SCARD_S_SUCCESS) { + fprintf (stderr, "error: SCardTransmit failed, rc=%08lx\n", rc); + return 0; + } + + if(verbose) { + printf("received data: (%ld bytes)\n", *recv_len); + dump_hex(data, *recv_len); + } + if(*recv_len >= 2) { + sw = (data[*recv_len - 2] << 8) | data[*recv_len - 1]; + } else { + sw = 0; + } + return sw; +} + +void dump_hex(const unsigned char *buf, unsigned int len) { + unsigned int i; for (i = 0; i < len; i++) { printf("0x%02x ", buf[i]); if (i % 8 == 7) { @@ -67,12 +195,20 @@ static void dump_hex(const unsigned char *buf, int len) { int main(int argc, char *argv[]) { struct gengetopt_args_info args_info; + SCARDHANDLE card; + SCARDCONTEXT context; if (cmdline_parser(argc, argv, &args_info) != 0) { return EXIT_FAILURE; } - dump_hex(default_key, 24); + if (connect_reader(&card, &context, args_info.reader_arg, args_info.verbose_flag) == false) { + return EXIT_FAILURE; + } + + if (select_applet(&card, args_info.verbose_flag) == false) { + return EXIT_FAILURE; + } return EXIT_SUCCESS; }