diff --git a/ccid/configure.ac b/ccid/configure.ac index f482f2e..4a3ca05 100644 --- a/ccid/configure.ac +++ b/ccid/configure.ac @@ -115,7 +115,9 @@ if test "x$enable_ccid_test" != xno ; then CPPFLAGS="$CPPFLAGS $PCSC_CFLAGS" LIBS="$LDFLAGS $PCSC_LIBS" - AC_CHECK_HEADERS(reader.h, [], [ AC_MSG_ERROR([reader.h not found, install OpenPACE or use ./configure PCSC_CFLAGS=...]) ]) + AC_CHECK_HEADERS(winscard.h, [], [ AC_MSG_ERROR([winscard.h not found, install PC/SC Lite or similar or use ./configure PCSC_CFLAGS=...]) ]) + AC_CHECK_HEADERS(reader.h, [AC_DEFINE(HAVE_READER_H, 1, [use reader.h from PC/SC Lite])], []) + AC_CHECK_HEADERS(pcsclite.h, [AC_DEFINE(HAVE_PCSCLITE_H, 1, [use pcsclite.h from PC/SC Lite])], []) AC_CHECK_DECL(FEATURE_EXECUTE_PACE, [], [AC_MSG_ERROR([libpcsclite > 1.4.102 patched with pcsclite_trunk.patch not found, use ./configure PCSC_LIBS=...]) ], [#include ]) diff --git a/ccid/src/ccid-test.c b/ccid/src/ccid-test.c index 8f39818..eddb2da 100644 --- a/ccid/src/ccid-test.c +++ b/ccid/src/ccid-test.c @@ -16,12 +16,20 @@ * You should have received a copy of the GNU General Public License along with * ifdnfc. If not, see . */ -//#include #include #include #include -#include +#include #include +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_PCSCLITE_H +#include +#endif #ifdef HAVE_READER_H #include @@ -34,6 +42,7 @@ typedef struct } PCSC_TLV_STRUCTURE; #endif + #ifndef FEATURE_EXECUTE_PACE #define FEATURE_EXECUTE_PACE 0x20 #endif @@ -44,9 +53,10 @@ typedef struct static void -printb(unsigned char *buf, size_t len) +printb(const char *label, unsigned char *buf, size_t len) { size_t i = 0; + printf(label); while (i < len) { printf("%02X", buf[i]); i++; @@ -58,6 +68,91 @@ printb(unsigned char *buf, size_t len) printf("\n"); } +static LONG parse_EstablishPACEChannel_OutputData( + unsigned char output[], unsigned int output_length) +{ + uint8_t lengthCAR, lengthCARprev; + uint16_t lengthEF_CardAccess, length_IDicc; + size_t parsed = 0; + + if (parsed+2 > output_length) { + fprintf(stderr, "Malformed Establish PACE Channel output data.\n"); + return SCARD_F_INTERNAL_ERROR; + } + printf("MSE:Set AT Statusbytes: %02X %02X\n", + output[parsed+0], output[parsed+1]); + parsed += 2; + + if (parsed+2 > output_length) { + fprintf(stderr, "Malformed Establish PACE Channel output data.\n"); + return SCARD_F_INTERNAL_ERROR; + } + memcpy(&lengthEF_CardAccess, output+parsed, 2); + parsed += 2; + + if (parsed+lengthEF_CardAccess > output_length) { + fprintf(stderr, "Malformed Establish PACE Channel output data.\n"); + return SCARD_F_INTERNAL_ERROR; + } + if (lengthEF_CardAccess) + printb("EF.CardAccess:\n", &output[parsed], lengthEF_CardAccess); + parsed += lengthEF_CardAccess; + + if (parsed+1 > output_length) { + fprintf(stderr, "Malformed Establish PACE Channel output data.\n"); + return SCARD_F_INTERNAL_ERROR; + } + lengthCAR = output[parsed]; + parsed += 1; + + if (parsed+lengthCAR > output_length) { + fprintf(stderr, "Malformed Establish PACE Channel output data.\n"); + return SCARD_F_INTERNAL_ERROR; + } + if (lengthCAR) + printb("Recent Certificate Authority:\n", + &output[parsed], lengthCAR); + parsed += lengthCAR; + + if (parsed+1 > output_length) { + fprintf(stderr, "Malformed Establish PACE Channel output data.\n"); + return SCARD_F_INTERNAL_ERROR; + } + lengthCARprev = output[parsed]; + parsed += 1; + + if (parsed+lengthCARprev > output_length) { + fprintf(stderr, "Malformed Establish PACE Channel output data.\n"); + return SCARD_F_INTERNAL_ERROR; + } + if (lengthCARprev) + printb("Previous Certificate Authority:\n", + &output[parsed], lengthCARprev); + parsed += lengthCARprev; + + if (parsed+2 > output_length) { + fprintf(stderr, "Malformed Establish PACE Channel output data.\n"); + return SCARD_F_INTERNAL_ERROR; + } + memcpy(&length_IDicc , output+parsed, 2); + parsed += 2; + + if (parsed+length_IDicc > output_length) { + fprintf(stderr, "Malformed Establish PACE Channel output data.\n"); + return SCARD_F_INTERNAL_ERROR; + } + if (length_IDicc) + printb("IDicc:\n", &output[parsed], length_IDicc); + parsed += length_IDicc; + + if (parsed != output_length) { + fprintf(stderr, "Overrun by %d bytes", output_length - parsed); + return SCARD_F_INTERNAL_ERROR; + } + + return SCARD_S_SUCCESS; +} + int main(int argc, char *argv[]) { @@ -121,8 +216,7 @@ main(int argc, char *argv[]) goto err; } - for (reader = mszReaders, i = 0; - dwReaders > 0; + for (reader = mszReaders, i = 0; dwReaders > 0; l = strlen(reader) + 1, dwReaders -= l, reader += l, i++) { if (i == num) @@ -143,11 +237,12 @@ main(int argc, char *argv[]) } printf("Connected to %s\n", reader); + /* does the reader support PACE? */ rv = SCardControl(hCard, CM_IOCTL_GET_FEATURE_REQUEST, NULL, 0, pbRecvBuffer, sizeof(pbRecvBuffer), &dwRecvLength); if (rv != SCARD_S_SUCCESS) { - fprintf(stderr, "Could not request the reader's features\n"); + fprintf(stderr, "Could not get the reader's features\n"); goto err; } @@ -165,6 +260,9 @@ main(int argc, char *argv[]) printf("Reader does not support PACE\n"); goto err; } + /* convert to host byte order to use for SCardControl */ + pace_ioctl = ntohl(pace_ioctl); + rv = SCardControl(hCard, pace_ioctl, pbSendBufferCapabilities, sizeof(pbSendBufferCapabilities), @@ -173,9 +271,8 @@ main(int argc, char *argv[]) fprintf(stderr, "Could not get reader's PACE capabilities\n"); goto err; } - printf("GetReadersPACECapabilities successfull, received %d bytes\n", - dwRecvLength); - printb(pbRecvBuffer, dwRecvLength); + printb("ReadersPACECapabilities ", pbRecvBuffer, dwRecvLength); + dwRecvLength = 0; rv = SCardControl(hCard, pace_ioctl, @@ -187,7 +284,10 @@ main(int argc, char *argv[]) } printf("EstablishPACEChannel successfull, received %d bytes\n", dwRecvLength); - printb(pbRecvBuffer, dwRecvLength); + + rv = parse_EstablishPACEChannel_OutputData(pbRecvBuffer, dwRecvLength); + if (rv != SCARD_S_SUCCESS) + goto err; rv = SCardDisconnect(hCard, SCARD_LEAVE_CARD); @@ -202,7 +302,9 @@ main(int argc, char *argv[]) exit(0); err: - /*puts(pcsc_stringify_error(rv));*/ +#ifdef HAVE_PCSCLITE_H + puts(pcsc_stringify_error(rv)); +#endif if (mszReaders) SCardFreeMemory(hContext, mszReaders);