diff --git a/ccid/src/cats-test.c b/ccid/src/cats-test.c index df7c4e4..783e5d8 100644 --- a/ccid/src/cats-test.c +++ b/ccid/src/cats-test.c @@ -53,22 +53,6 @@ #define PCSC_TLV_ELEMENT_SIZE 6 -static void -printb(const char *label, unsigned char *buf, size_t len) -{ - size_t i = 0; - printf("%s", label); - while (i < len) { - printf("%02X", buf[i]); - i++; - if (i%20) - printf(" "); - else if (i != len) - printf("\n"); - } - printf("\n"); -} - static LONG parse_EstablishPACEChannel_OutputData( unsigned char output[], unsigned int output_length) { @@ -188,7 +172,7 @@ main(int argc, char *argv[]) SCARDHANDLE hCard; LPSTR readers = NULL; BYTE sendbuf[16], recvbuf[1024]; - DWORD ctl, recvlen; + DWORD ctl, recvlen, protocol; time_t t_start, t_end; size_t l, pinlen = 0; char *pin = NULL; @@ -216,15 +200,15 @@ main(int argc, char *argv[]) r = pcsc_connect(readernum, SCARD_SHARE_DIRECT, 0, &hContext, &readers, - &hCard); + &hCard, &protocol); if (r != SCARD_S_SUCCESS) goto err; #define SIMULATE_BUERGERCLIENT 1 #ifdef SIMULATE_BUERGERCLIENT - r = SCardReconnect(hCard, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_T0, - SCARD_LEAVE_CARD, &ctl); + r = SCardReconnect(hCard, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_ANY, + SCARD_LEAVE_CARD, &protocol); if (r != SCARD_S_SUCCESS) { fprintf(stderr, "Could not reconnect\n"); goto err; @@ -250,18 +234,16 @@ main(int argc, char *argv[]) }; LPBYTE buf0 = bufs0; DWORD lens0[] = {4, 4, 4, 4, 7, 14, 7, 20, 7, 7, 5, 5, 5, 5, 5, 7, 20}; - SCARD_IO_REQUEST pioRecvPci; for (l = 0; l < sizeof(lens0)/sizeof(DWORD); l++) { recvlen = sizeof(recvbuf); - r = SCardTransmit(hCard, SCARD_PCI_T0, buf0, lens0[l], &pioRecvPci, - recvbuf, &recvlen); + r = pcsc_transmit(protocol, hCard, buf0, lens0[l], recvbuf, &recvlen); if (r != SCARD_S_SUCCESS) { fprintf(stderr, "Simulation of Buergerclient failed\n"); goto err; } buf0 += lens0[l]; } - r = SCardReconnect(hCard, SCARD_SHARE_DIRECT, 0, SCARD_LEAVE_CARD, &ctl); + r = SCardReconnect(hCard, SCARD_SHARE_DIRECT, 0, SCARD_LEAVE_CARD, &protocol); if (r != SCARD_S_SUCCESS) { fprintf(stderr, "Could not reconnect\n"); goto err; @@ -338,8 +320,8 @@ main(int argc, char *argv[]) #define SIMULATE_TA_CA 1 #ifdef SIMULATE_TA_CA - r = SCardReconnect(hCard, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_T0, - SCARD_LEAVE_CARD, &ctl); + r = SCardReconnect(hCard, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_ANY, + SCARD_LEAVE_CARD, &protocol); if (r != SCARD_S_SUCCESS) { fprintf(stderr, "Could not reconnect\n"); goto err; @@ -376,11 +358,9 @@ main(int argc, char *argv[]) LPBYTE buf1 = bufs1; DWORD lens1[] = {20, 233, 21, 328, 88, 5, 69, 7, 7, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 17, 75}; - SCARD_IO_REQUEST ridpioRecvPci; for (l = 0; l < sizeof(lens1)/sizeof(DWORD); l++) { recvlen = sizeof(recvbuf); - r = SCardTransmit(hCard, SCARD_PCI_T0, buf1, lens1[l], &ridpioRecvPci, - recvbuf, &recvlen); + r = pcsc_transmit(protocol, hCard, buf1, lens1[l], recvbuf, &recvlen); if (r != SCARD_S_SUCCESS) { fprintf(stderr, "Simulation of Terminal and Chip Authentication failed\n"); @@ -388,33 +368,16 @@ main(int argc, char *argv[]) } buf1 += lens1[l]; } - r = SCardReconnect(hCard, SCARD_SHARE_DIRECT, 0, SCARD_LEAVE_CARD, &ctl); + r = SCardReconnect(hCard, SCARD_SHARE_DIRECT, 0, SCARD_LEAVE_CARD, &protocol); if (r != SCARD_S_SUCCESS) { fprintf(stderr, "Could not reconnect\n"); goto err; } #endif - - r = SCardDisconnect(hCard, SCARD_LEAVE_CARD); - if (r != SCARD_S_SUCCESS) - goto err; - - r = SCardFreeMemory(hContext, readers); - if (r != SCARD_S_SUCCESS) - goto err; - - - exit(0); - err: -#ifdef HAVE_PCSCLITE_H - if (r != SCARD_S_SUCCESS) - puts(pcsc_stringify_error(r)); -#endif - if (readers) - SCardFreeMemory(hContext, readers); + stringify_error(r); + pcsc_disconnect(hContext, hCard, readers); - - exit(1); + exit(r == SCARD_S_SUCCESS ? 0 : 1); } diff --git a/ccid/src/pcscutil.c b/ccid/src/pcscutil.c index edccddd..0d21acf 100644 --- a/ccid/src/pcscutil.c +++ b/ccid/src/pcscutil.c @@ -22,8 +22,9 @@ #include "pcscutil.h" LONG -pcsc_connect(unsigned int readernum, DWORD dwShareMode, DWORD dwPreferredProtocol, - SCARDCONTEXT *hContext, LPSTR *readers, LPSCARDHANDLE phCard) +pcsc_connect(unsigned int readernum, DWORD dwShareMode, DWORD dwPreferredProtocols, + SCARDCONTEXT *hContext, LPSTR *readers, LPSCARDHANDLE phCard, + LPDWORD pdwActiveProtocol) { LONG r; DWORD ctl, readerslen; @@ -57,8 +58,8 @@ pcsc_connect(unsigned int readernum, DWORD dwShareMode, DWORD dwPreferredProtoco } - r = SCardConnect(hContext, reader, dwShareMode, dwPreferredProtocol, - phCard, &ctl); + r = SCardConnect(hContext, reader, dwShareMode, dwPreferredProtocols, + phCard, pdwActiveProtocol); if (r != SCARD_S_SUCCESS) { fprintf(stderr, "Could not connect to %s\n", reader); goto err; @@ -68,3 +69,56 @@ pcsc_connect(unsigned int readernum, DWORD dwShareMode, DWORD dwPreferredProtoco err: return r; } + +void +pcsc_disconnect(SCARDCONTEXT hContext, SCARDHANDLE hCard, LPSTR readers) +{ + SCardDisconnect(hCard, SCARD_LEAVE_CARD); + SCardFreeMemory(hContext, readers); + SCardReleaseContext(hContext); +} + +LONG +pcsc_transmit(DWORD dwActiveProtocol, SCARDHANDLE hCard, + LPCBYTE pbSendBuffer, DWORD cbSendLength, + LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength) +{ + LONG r; + SCARD_IO_REQUEST ioRecvPci; + + switch (dwActiveProtocol) { + case SCARD_PROTOCOL_T0: + r = SCardTransmit(hCard, SCARD_PCI_T0, pbSendBuffer, cbSendLength, + &ioRecvPci, pbRecvBuffer, pcbRecvLength); + break; + + case SCARD_PROTOCOL_T1: + r = SCardTransmit(hCard, SCARD_PCI_T1, pbSendBuffer, cbSendLength, + &ioRecvPci, pbRecvBuffer, pcbRecvLength); + break; + + default: + fprintf(stderr, "Could not transmit with unknown protocol %u\n", + (unsigned int) dwActiveProtocol); + r = SCARD_E_PROTO_MISMATCH; + break; + } + + return r; +} + +void +printb(const char *label, unsigned char *buf, size_t len) +{ + size_t i = 0; + printf("%s", label); + while (i < len) { + printf("%02X", buf[i]); + i++; + if (i%20) + printf(" "); + else if (i != len) + printf("\n"); + } + printf("\n"); +} diff --git a/ccid/src/pcscutil.h b/ccid/src/pcscutil.h index 8a1af32..988c76e 100644 --- a/ccid/src/pcscutil.h +++ b/ccid/src/pcscutil.h @@ -23,8 +23,12 @@ #include "config.h" #endif +#include #ifdef HAVE_PCSCLITE_H #include +#define stringify_error(r) { if (r != SCARD_S_SUCCESS) fputs(pcsc_stringify_error(r), stderr); } +#else +#define stringify_error(r) { if (r != SCARD_S_SUCCESS) fprintf(stderr, "PC/SC error code %u\n", (unsigned int) r); } #endif #ifdef HAVE_READER_H @@ -38,7 +42,19 @@ extern "C" { LONG pcsc_connect(unsigned int readernum, DWORD dwShareMode, DWORD dwPreferredProtocol, - SCARDCONTEXT *hContext, LPSTR *readers, LPSCARDHANDLE phCard); + SCARDCONTEXT *hContext, LPSTR *readers, LPSCARDHANDLE phCard, + LPDWORD pdwActiveProtocol); + +void +pcsc_disconnect(SCARDCONTEXT hContext, SCARDHANDLE hCard, LPSTR readers); + +LONG +pcsc_transmit(DWORD dwActiveProtocol, SCARDHANDLE hCard, + LPCBYTE pbSendBuffer, DWORD cbSendLength, + LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength); + +void +printb(const char *label, unsigned char *buf, size_t len); #ifdef __cplusplus } diff --git a/picc_to_pcsc/Makefile b/picc_to_pcsc/Makefile deleted file mode 100644 index b84d520..0000000 --- a/picc_to_pcsc/Makefile +++ /dev/null @@ -1,689 +0,0 @@ -# Makefile.in generated by automake 1.11.1 from Makefile.am. -# Makefile. Generated from Makefile.in by configure. - -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, -# Inc. -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - - - -pkgdatadir = $(datadir)/picc_to_pcsc -pkgincludedir = $(includedir)/picc_to_pcsc -pkglibdir = $(libdir)/picc_to_pcsc -pkglibexecdir = $(libexecdir)/picc_to_pcsc -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -subdir = . -DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \ - $(srcdir)/Makefile.in $(srcdir)/config.h.in \ - $(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \ - compile depcomp install-sh missing -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ - configure.lineno config.status.lineno -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = config.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -SOURCES = -DIST_SOURCES = -RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ - html-recursive info-recursive install-data-recursive \ - install-dvi-recursive install-exec-recursive \ - install-html-recursive install-info-recursive \ - install-pdf-recursive install-ps-recursive install-recursive \ - installcheck-recursive installdirs-recursive pdf-recursive \ - ps-recursive uninstall-recursive -RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ - distclean-recursive maintainer-clean-recursive -AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ - $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ - distdir dist dist-all distcheck -ETAGS = etags -CTAGS = ctags -DIST_SUBDIRS = $(SUBDIRS) -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -distdir = $(PACKAGE)-$(VERSION) -top_distdir = $(distdir) -am__remove_distdir = \ - { test ! -d "$(distdir)" \ - || { find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ - && rm -fr "$(distdir)"; }; } -am__relativize = \ - dir0=`pwd`; \ - sed_first='s,^\([^/]*\)/.*$$,\1,'; \ - sed_rest='s,^[^/]*/*,,'; \ - sed_last='s,^.*/\([^/]*\)$$,\1,'; \ - sed_butlast='s,/*[^/]*$$,,'; \ - while test -n "$$dir1"; do \ - first=`echo "$$dir1" | sed -e "$$sed_first"`; \ - if test "$$first" != "."; then \ - if test "$$first" = ".."; then \ - dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ - dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ - else \ - first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ - if test "$$first2" = "$$first"; then \ - dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ - else \ - dir2="../$$dir2"; \ - fi; \ - dir0="$$dir0"/"$$first"; \ - fi; \ - fi; \ - dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ - done; \ - reldir="$$dir2" -DIST_ARCHIVES = $(distdir).tar.gz -GZIP_ENV = --best -distuninstallcheck_listfiles = find . -type f -print -distcleancheck_listfiles = find . -type f -print -ACLOCAL = ${SHELL} /home/fm/work/vsmartcard/picc_to_pcsc/missing --run aclocal-1.11 -AMTAR = ${SHELL} /home/fm/work/vsmartcard/picc_to_pcsc/missing --run tar -AUTOCONF = ${SHELL} /home/fm/work/vsmartcard/picc_to_pcsc/missing --run autoconf -AUTOHEADER = ${SHELL} /home/fm/work/vsmartcard/picc_to_pcsc/missing --run autoheader -AUTOMAKE = ${SHELL} /home/fm/work/vsmartcard/picc_to_pcsc/missing --run automake-1.11 -AWK = mawk -CC = gcc -CCDEPMODE = depmode=gcc3 -CFLAGS = -g -O2 -CPP = gcc -E -CPPFLAGS = -CYGPATH_W = echo -DEFS = -DHAVE_CONFIG_H -DEPDIR = .deps -ECHO_C = -ECHO_N = -n -ECHO_T = -EGREP = /bin/grep -E -EXEEXT = -GREP = /bin/grep -INSTALL = /usr/bin/install -c -INSTALL_DATA = ${INSTALL} -m 644 -INSTALL_PROGRAM = ${INSTALL} -INSTALL_SCRIPT = ${INSTALL} -INSTALL_STRIP_PROGRAM = $(install_sh) -c -s -LDFLAGS = -LIBOBJS = -LIBS = -LTLIBOBJS = -MAKEINFO = ${SHELL} /home/fm/work/vsmartcard/picc_to_pcsc/missing --run makeinfo -MKDIR_P = /bin/mkdir -p -OBJEXT = o -PACKAGE = picc_to_pcsc -PACKAGE_BUGREPORT = oepen@informatik.hu-berlin.de -PACKAGE_NAME = picc_to_pcsc -PACKAGE_STRING = picc_to_pcsc 0.1 -PACKAGE_TARNAME = picc_to_pcsc -PACKAGE_URL = -PACKAGE_VERSION = 0.1 -PATH_SEPARATOR = : -PCSC_CFLAGS = -I/usr/include/PCSC -PCSC_LIBS = -lpcsclite -PKG_CONFIG = /usr/bin/pkg-config -PKG_CONFIG_LIBDIR = -PKG_CONFIG_PATH = -PYTHON = /usr/bin/python -PYTHON_EXEC_PREFIX = ${exec_prefix} -PYTHON_PLATFORM = linux2 -PYTHON_PREFIX = ${prefix} -PYTHON_VERSION = 2.5 -SET_MAKE = -SHELL = /bin/bash -STRIP = -VERSION = 0.1 -abs_builddir = /home/fm/work/vsmartcard/picc_to_pcsc -abs_srcdir = /home/fm/work/vsmartcard/picc_to_pcsc -abs_top_builddir = /home/fm/work/vsmartcard/picc_to_pcsc -abs_top_srcdir = /home/fm/work/vsmartcard/picc_to_pcsc -ac_ct_CC = gcc -am__include = include -am__leading_dot = . -am__quote = -am__tar = ${AMTAR} chof - "$$tardir" -am__untar = ${AMTAR} xf - -bindir = ${exec_prefix}/bin -build_alias = -builddir = . -datadir = ${datarootdir} -datarootdir = ${prefix}/share -docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} -dvidir = ${docdir} -exec_prefix = ${prefix} -host_alias = -htmldir = ${docdir} -includedir = ${prefix}/include -infodir = ${datarootdir}/info -install_sh = ${SHELL} /home/fm/work/vsmartcard/picc_to_pcsc/install-sh -libdir = ${exec_prefix}/lib -libexecdir = ${exec_prefix}/libexec -localedir = ${datarootdir}/locale -localstatedir = ${prefix}/var -mandir = ${datarootdir}/man -mkdir_p = /bin/mkdir -p -oldincludedir = /usr/include -pdfdir = ${docdir} -pkgpyexecdir = ${pyexecdir}/picc_to_pcsc -pkgpythondir = ${pythondir}/picc_to_pcsc -prefix = /usr/local -program_transform_name = s,x,x, -psdir = ${docdir} -pyexecdir = ${exec_prefix}/lib/python2.5/site-packages -pythondir = ${prefix}/lib/python2.5/site-packages -sbindir = ${exec_prefix}/sbin -sharedstatedir = ${prefix}/com -srcdir = . -sysconfdir = ${prefix}/etc -target_alias = -top_build_prefix = -top_builddir = . -top_srcdir = . -SUBDIRS = src -all: config.h - $(MAKE) $(AM_MAKEFLAGS) all-recursive - -.SUFFIXES: -am--refresh: - @: -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \ - $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \ - && exit 0; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - echo ' $(SHELL) ./config.status'; \ - $(SHELL) ./config.status;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - $(SHELL) ./config.status --recheck - -$(top_srcdir)/configure: $(am__configure_deps) - $(am__cd) $(srcdir) && $(AUTOCONF) -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) -$(am__aclocal_m4_deps): - -config.h: stamp-h1 - @if test ! -f $@; then \ - rm -f stamp-h1; \ - $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \ - else :; fi - -stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status - @rm -f stamp-h1 - cd $(top_builddir) && $(SHELL) ./config.status config.h -$(srcdir)/config.h.in: $(am__configure_deps) - ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) - rm -f stamp-h1 - touch $@ - -distclean-hdr: - -rm -f config.h stamp-h1 - -# This directory's subdirectories are mostly independent; you can cd -# into them and run `make' without going through this Makefile. -# To change the values of `make' variables: instead of editing Makefiles, -# (1) if the variable is set in `config.status', edit `config.status' -# (which will cause the Makefiles to be regenerated when you run `make'); -# (2) otherwise, pass the desired values on the `make' command line. -$(RECURSIVE_TARGETS): - @fail= failcom='exit 1'; \ - for f in x $$MAKEFLAGS; do \ - case $$f in \ - *=* | --[!k]*);; \ - *k*) failcom='fail=yes';; \ - esac; \ - done; \ - dot_seen=no; \ - target=`echo $@ | sed s/-recursive//`; \ - list='$(SUBDIRS)'; for subdir in $$list; do \ - echo "Making $$target in $$subdir"; \ - if test "$$subdir" = "."; then \ - dot_seen=yes; \ - local_target="$$target-am"; \ - else \ - local_target="$$target"; \ - fi; \ - ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ - || eval $$failcom; \ - done; \ - if test "$$dot_seen" = "no"; then \ - $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ - fi; test -z "$$fail" - -$(RECURSIVE_CLEAN_TARGETS): - @fail= failcom='exit 1'; \ - for f in x $$MAKEFLAGS; do \ - case $$f in \ - *=* | --[!k]*);; \ - *k*) failcom='fail=yes';; \ - esac; \ - done; \ - dot_seen=no; \ - case "$@" in \ - distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ - *) list='$(SUBDIRS)' ;; \ - esac; \ - rev=''; for subdir in $$list; do \ - if test "$$subdir" = "."; then :; else \ - rev="$$subdir $$rev"; \ - fi; \ - done; \ - rev="$$rev ."; \ - target=`echo $@ | sed s/-recursive//`; \ - for subdir in $$rev; do \ - echo "Making $$target in $$subdir"; \ - if test "$$subdir" = "."; then \ - local_target="$$target-am"; \ - else \ - local_target="$$target"; \ - fi; \ - ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ - || eval $$failcom; \ - done && test -z "$$fail" -tags-recursive: - list='$(SUBDIRS)'; for subdir in $$list; do \ - test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ - done -ctags-recursive: - list='$(SUBDIRS)'; for subdir in $$list; do \ - test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ - done - -ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - mkid -fID $$unique -tags: TAGS - -TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - set x; \ - here=`pwd`; \ - if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ - include_option=--etags-include; \ - empty_fix=.; \ - else \ - include_option=--include; \ - empty_fix=; \ - fi; \ - list='$(SUBDIRS)'; for subdir in $$list; do \ - if test "$$subdir" = .; then :; else \ - test ! -f $$subdir/TAGS || \ - set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ - fi; \ - done; \ - list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: CTAGS -CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - $(am__remove_distdir) - test -d "$(distdir)" || mkdir "$(distdir)" - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done - @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ - if test "$$subdir" = .; then :; else \ - test -d "$(distdir)/$$subdir" \ - || $(MKDIR_P) "$(distdir)/$$subdir" \ - || exit 1; \ - fi; \ - done - @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ - if test "$$subdir" = .; then :; else \ - dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ - $(am__relativize); \ - new_distdir=$$reldir; \ - dir1=$$subdir; dir2="$(top_distdir)"; \ - $(am__relativize); \ - new_top_distdir=$$reldir; \ - echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ - echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ - ($(am__cd) $$subdir && \ - $(MAKE) $(AM_MAKEFLAGS) \ - top_distdir="$$new_top_distdir" \ - distdir="$$new_distdir" \ - am__remove_distdir=: \ - am__skip_length_check=: \ - am__skip_mode_fix=: \ - distdir) \ - || exit 1; \ - fi; \ - done - -test -n "$(am__skip_mode_fix)" \ - || find "$(distdir)" -type d ! -perm -755 \ - -exec chmod u+rwx,go+rx {} \; -o \ - ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ - ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ - ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ - || chmod -R a+r "$(distdir)" -dist-gzip: distdir - tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz - $(am__remove_distdir) - -dist-bzip2: distdir - tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 - $(am__remove_distdir) - -dist-lzma: distdir - tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma - $(am__remove_distdir) - -dist-xz: distdir - tardir=$(distdir) && $(am__tar) | xz -c >$(distdir).tar.xz - $(am__remove_distdir) - -dist-tarZ: distdir - tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z - $(am__remove_distdir) - -dist-shar: distdir - shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz - $(am__remove_distdir) - -dist-zip: distdir - -rm -f $(distdir).zip - zip -rq $(distdir).zip $(distdir) - $(am__remove_distdir) - -dist dist-all: distdir - tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz - $(am__remove_distdir) - -# This target untars the dist file and tries a VPATH configuration. Then -# it guarantees that the distribution is self-contained by making another -# tarfile. -distcheck: dist - case '$(DIST_ARCHIVES)' in \ - *.tar.gz*) \ - GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ - *.tar.bz2*) \ - bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ - *.tar.lzma*) \ - lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\ - *.tar.xz*) \ - xz -dc $(distdir).tar.xz | $(am__untar) ;;\ - *.tar.Z*) \ - uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ - *.shar.gz*) \ - GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ - *.zip*) \ - unzip $(distdir).zip ;;\ - esac - chmod -R a-w $(distdir); chmod a+w $(distdir) - mkdir $(distdir)/_build - mkdir $(distdir)/_inst - chmod a-w $(distdir) - test -d $(distdir)/_build || exit 0; \ - dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ - && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ - && am__cwd=`pwd` \ - && $(am__cd) $(distdir)/_build \ - && ../configure --srcdir=.. --prefix="$$dc_install_base" \ - $(DISTCHECK_CONFIGURE_FLAGS) \ - && $(MAKE) $(AM_MAKEFLAGS) \ - && $(MAKE) $(AM_MAKEFLAGS) dvi \ - && $(MAKE) $(AM_MAKEFLAGS) check \ - && $(MAKE) $(AM_MAKEFLAGS) install \ - && $(MAKE) $(AM_MAKEFLAGS) installcheck \ - && $(MAKE) $(AM_MAKEFLAGS) uninstall \ - && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ - distuninstallcheck \ - && chmod -R a-w "$$dc_install_base" \ - && ({ \ - (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ - && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ - && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ - && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ - distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ - } || { rm -rf "$$dc_destdir"; exit 1; }) \ - && rm -rf "$$dc_destdir" \ - && $(MAKE) $(AM_MAKEFLAGS) dist \ - && rm -rf $(DIST_ARCHIVES) \ - && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ - && cd "$$am__cwd" \ - || exit 1 - $(am__remove_distdir) - @(echo "$(distdir) archives ready for distribution: "; \ - list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ - sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' -distuninstallcheck: - @$(am__cd) '$(distuninstallcheck_dir)' \ - && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ - || { echo "ERROR: files left after uninstall:" ; \ - if test -n "$(DESTDIR)"; then \ - echo " (check DESTDIR support)"; \ - fi ; \ - $(distuninstallcheck_listfiles) ; \ - exit 1; } >&2 -distcleancheck: distclean - @if test '$(srcdir)' = . ; then \ - echo "ERROR: distcleancheck can only run from a VPATH build" ; \ - exit 1 ; \ - fi - @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ - || { echo "ERROR: files left in build directory after distclean:" ; \ - $(distcleancheck_listfiles) ; \ - exit 1; } >&2 -check-am: all-am -check: check-recursive -all-am: Makefile config.h -installdirs: installdirs-recursive -installdirs-am: -install: install-recursive -install-exec: install-exec-recursive -install-data: install-data-recursive -uninstall: uninstall-recursive - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-recursive -install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-recursive - -clean-am: clean-generic mostlyclean-am - -distclean: distclean-recursive - -rm -f $(am__CONFIG_DISTCLEAN_FILES) - -rm -f Makefile -distclean-am: clean-am distclean-generic distclean-hdr distclean-tags - -dvi: dvi-recursive - -dvi-am: - -html: html-recursive - -html-am: - -info: info-recursive - -info-am: - -install-data-am: - -install-dvi: install-dvi-recursive - -install-dvi-am: - -install-exec-am: - -install-html: install-html-recursive - -install-html-am: - -install-info: install-info-recursive - -install-info-am: - -install-man: - -install-pdf: install-pdf-recursive - -install-pdf-am: - -install-ps: install-ps-recursive - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-recursive - -rm -f $(am__CONFIG_DISTCLEAN_FILES) - -rm -rf $(top_srcdir)/autom4te.cache - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-recursive - -mostlyclean-am: mostlyclean-generic - -pdf: pdf-recursive - -pdf-am: - -ps: ps-recursive - -ps-am: - -uninstall-am: - -.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all \ - ctags-recursive install-am install-strip tags-recursive - -.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ - all all-am am--refresh check check-am clean clean-generic \ - ctags ctags-recursive dist dist-all dist-bzip2 dist-gzip \ - dist-lzma dist-shar dist-tarZ dist-xz dist-zip distcheck \ - distclean distclean-generic distclean-hdr distclean-tags \ - distcleancheck distdir distuninstallcheck dvi dvi-am html \ - html-am info info-am install install-am install-data \ - install-data-am install-dvi install-dvi-am install-exec \ - install-exec-am install-html install-html-am install-info \ - install-info-am install-man install-pdf install-pdf-am \ - install-ps install-ps-am install-strip installcheck \ - installcheck-am installdirs installdirs-am maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ - pdf-am ps ps-am tags tags-recursive uninstall uninstall-am - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/picc_to_pcsc/configure.ac b/picc_to_pcsc/configure.ac index f369ed1..356bfc4 100644 --- a/picc_to_pcsc/configure.ac +++ b/picc_to_pcsc/configure.ac @@ -22,8 +22,9 @@ saved_CPPFLAGS="$CPPFLAGS" saved_LIBS="$LIBS" CPPFLAGS="$CPPFLAGS $PCSC_CFLAGS" LIBS="$LDFLAGS $PCSC_LIBS" -AC_CHECK_HEADERS(winscard.h,, - [ AC_MSG_ERROR([winscard.h not found, install libpcsclite 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_MSG_CHECKING([for SCardEstablishContext]) AC_TRY_LINK_FUNC(SCardEstablishContext, [ AC_MSG_RESULT([yes]) ], [ AC_MSG_ERROR([libpcsclite not found, use ./configure PCSC_LIBS=...]) ]) diff --git a/picc_to_pcsc/src/Makefile.am b/picc_to_pcsc/src/Makefile.am index 0cce54b..68361af 100644 --- a/picc_to_pcsc/src/Makefile.am +++ b/picc_to_pcsc/src/Makefile.am @@ -3,8 +3,8 @@ EXTRA_DIST = picc.py bin_PROGRAMS = picc_to_pcsc bin_SCRIPTS = picc.py -picc_to_pcsc_SOURCES = picc_to_pcsc.c +picc_to_pcsc_SOURCES = picc_to_pcsc.c pcscutil.c picc_to_pcsc_LDADD = $(PCSC_LIBS) picc_to_pcsc_CFLAGS = $(PCSC_CFLAGS) -noinst_HEADERS = picc_to_pcsc.h +noinst_HEADERS = picc_to_pcsc.h pcscutil.h diff --git a/picc_to_pcsc/src/pcscutil.c b/picc_to_pcsc/src/pcscutil.c new file mode 120000 index 0000000..51b2c32 --- /dev/null +++ b/picc_to_pcsc/src/pcscutil.c @@ -0,0 +1 @@ +../../ccid/src/pcscutil.c \ No newline at end of file diff --git a/picc_to_pcsc/src/pcscutil.h b/picc_to_pcsc/src/pcscutil.h new file mode 120000 index 0000000..91d334e --- /dev/null +++ b/picc_to_pcsc/src/pcscutil.h @@ -0,0 +1 @@ +../../ccid/src/pcscutil.h \ No newline at end of file diff --git a/picc_to_pcsc/src/picc_to_pcsc.c b/picc_to_pcsc/src/picc_to_pcsc.c index 756668e..7a203b7 100644 --- a/picc_to_pcsc/src/picc_to_pcsc.c +++ b/picc_to_pcsc/src/picc_to_pcsc.c @@ -10,8 +10,13 @@ #include #include #include +#include #include "picc_to_pcsc.h" +#include "pcscutil.h" + +static FILE *fd; /*filehandle used for PICCDEV*/ + static sighandler_t register_sig(int signo, sighandler_t sighandler) { struct sigaction new_sig, old_sig; @@ -25,179 +30,63 @@ static sighandler_t register_sig(int signo, sighandler_t sighandler) { } -char* perform_initialization(int num) -{ - char *readers, *str; - DWORD size=0; - LONG r; - - r = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hcontext); - if (r != SCARD_S_SUCCESS) { - fprintf(stderr, "pc/sc error: %s\n", pcsc_stringify_error(r)); - SCardReleaseContext(hcontext); - return NULL; - } - r = SCardListReaders(hcontext, NULL, NULL, &size); - if (size == 0) - r = SCARD_E_UNKNOWN_READER; - if (r != SCARD_S_SUCCESS) { - fprintf(stderr, "pc/sc error: %s\n", pcsc_stringify_error(r)); - SCardReleaseContext(hcontext); - return NULL; - } - - /* get all readers */ - readers = (char*)malloc(size); - if (readers == NULL) { - fprintf(stderr, "pc/sc error: %s\n", - pcsc_stringify_error(SCARD_E_NO_MEMORY)); - SCardReleaseContext(hcontext); - return NULL; - } - r = SCardListReaders(hcontext, NULL, readers, &size); - if (r != SCARD_S_SUCCESS) { - free(readers); - fprintf(stderr, "pc/sc error: %s\n", pcsc_stringify_error(r)); - SCardReleaseContext(hcontext); - return NULL; - } - - /* name of reader number num*/ - str = readers; - for (size = 0; size < num; size++) { - /* go to the next name */ - str += strlen(str) + 1; - - /* no more readers available? */ - if (strlen(str) == 0) { - free(readers); - fprintf(stderr, "pc/sc error: %s\n", - pcsc_stringify_error(SCARD_E_UNKNOWN_READER)); - SCardReleaseContext(hcontext); - return NULL; - } - } - strcpy(reader_name, str); - free(readers); - - rstate.dwCurrentState = SCARD_STATE_UNAWARE; - rstate.szReader = reader_name; - - return reader_name; -} - - -void setup(void) { - /*setup environment, open device, set global filehandle*/ - DWORD dwActiveProtocol; - LONG pcsc_result; - - perform_initialization(2); /*Right num for PICC?*/ - printf("Initialised reader: %s\n",reader_name); - pcsc_result = SCardConnect(hcontext, reader_name, - SCARD_SHARE_EXCLUSIVE, (SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1), - &hcard, &dwActiveProtocol); - if (pcsc_result == SCARD_S_SUCCESS) { - pcsc_result = SCardGetStatusChange(hcontext, 1, &rstate, 1); - if (pcsc_result != SCARD_S_SUCCESS) fprintf(stderr,"%s\n",pcsc_stringify_error(pcsc_result)); - } else { - fprintf(stderr,"%s\n",pcsc_stringify_error(pcsc_result)); - } - /*Register our signal handlers*/ - register_sig(SIGINT,checkSig); - /*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"); - -} - void checkSig(int signo){ if (signo == SIGINT) printf("Received SIGINT, exiting.\n"); cleanup(); } -void printHex(char *title, unsigned char *msg, unsigned int length) { - int n = 0; - printf("%s: \t",title); - while (n= length) break; - } - - printf("Have %i bytes, should have %i bytes\n", pos, length); - memcpy(inputBuffer,buf,length); - } +int picc_decode(char *inbuf, size_t inlen, + unsigned char **outbuf, size_t *outlen) +{ + size_t pos; + unsigned char buf[0xffff]; + char *end, *p; + unsigned long int b, length; - if(line != NULL) { - free(line); - } - if(buf != NULL) { - free(buf); - } - return length; -} + if (inbuf == NULL || inlen == 0 || inbuf[0] == '\0') { + //Ignore empty lines and 'RESET' lines + *outlen = 0; + return 0; + } -int transmit_to_pcsc(unsigned char *inputBuffer, unsigned int inputLength, unsigned char *outputBuffer, unsigned int *outputLength) { + errno = 0; + length = strtoul(inbuf, &end, 16); + if (errno) + goto err; - printHex("APDU", inputBuffer, inputLength); - unsigned int dwRecvLength = MAX_BUFFER_SIZE; - int result; - result = SCardTransmit(hcard, SCARD_PCI_T1, inputBuffer, - inputLength, NULL, outputBuffer, (DWORD*) &dwRecvLength); + /* check for ':' right behind the length */ + if (inbuf+inlen < end+1 || end[0] != ':') + goto err; + end++; + + 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; + + (*outbuf)[pos++] = b; + } - /*Check response code */ - if (result != SCARD_S_SUCCESS) { - fprintf(stderr,"SCardTransmit failed.\n"); - fprintf(stderr,"dwRecvLength = %d maximum is:%d\n",dwRecvLength,MAX_BUFFER_SIZE); - fprintf(stderr,"%s\n",pcsc_stringify_error(result)); - return -1; - } else { - printf("Received %d Byte\n",dwRecvLength); - printHex("RAPDU", outputBuffer, dwRecvLength); - *outputLength = dwRecvLength; - } return 0; + +err: + *outlen = 0; + return -1; } void write_to_device(unsigned char *buffer, unsigned int msgLength) { @@ -217,25 +106,89 @@ void write_to_device(unsigned char *buffer, unsigned int msgLength) { free(foo); } -int main (int argv, char **args) { - unsigned char inputBuffer[MAX_BUFFER_SIZE]; - unsigned char outputBuffer[MAX_BUFFER_SIZE]; - unsigned int inputLength, outputLength = MAX_BUFFER_SIZE; - int status; - setup(); +int main (int argc, char **argv) +{ + /*printf("%s:%d\n", __FILE__, __LINE__);*/ + unsigned char *inputBuffer = NULL; + size_t inputLength; + BYTE outputBuffer[MAX_BUFFER_SIZE]; + DWORD outputLength; - while(1) { - inputLength = read_from_device(inputBuffer); - if (inputLength == 0) continue; - fflush(fd); - status = transmit_to_pcsc(inputBuffer,inputLength,outputBuffer,&outputLength); - if (!status) { - write_to_device(outputBuffer, outputLength); - //fprintf(fd,"0002: 90 00\0"); - } else { - printf("Failed\n"); - } - } - cleanup(); - return 0; + LPSTR readers = NULL; + LONG r; + DWORD ctl, protocol; + SCARDCONTEXT hContext; + SCARDHANDLE hCard; + + char *read = NULL; + size_t readlen = 0; + ssize_t linelen; + + unsigned int readernum = 0; + + + if (argc > 1) { + 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); + } + } + + + /*Register signal handlers*/ + register_sig(SIGINT,checkSig); + + /*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"); + + 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); + if (linelen < 0) { + if (linelen < 0) { + fprintf(stderr,"Error reading from %s\n", PICCDEV); + goto err; + } + } + if (linelen == 0) + continue; + fflush(fd); + + printf("%s\n", read); + + if (picc_decode(read, linelen, &inputBuffer, &inputLength) < 0) + continue; + + printb("C-APDU:\n", inputBuffer, inputLength); + + outputLength = MAX_BUFFER_SIZE; + r = pcsc_transmit(protocol, hCard, inputBuffer, inputLength, outputBuffer, &outputLength); + if (r != SCARD_S_SUCCESS) + goto err; + + printb("R-APDU:\n", outputBuffer, outputLength); + + write_to_device(outputBuffer, outputLength); + //fprintf(fd,"0002: 90 00\0"); + } + cleanup(); + +err: + stringify_error(r); + pcsc_disconnect(hContext, hCard, readers); + + exit(r == SCARD_S_SUCCESS ? 0 : 1); } diff --git a/picc_to_pcsc/src/picc_to_pcsc.h b/picc_to_pcsc/src/picc_to_pcsc.h index c71fbbd..9312ed3 100644 --- a/picc_to_pcsc/src/picc_to_pcsc.h +++ b/picc_to_pcsc/src/picc_to_pcsc.h @@ -4,18 +4,10 @@ #define PICCDEV "/dev/ttyACM0" typedef void (*sighandler_t)(int); -/*Global variables*/ -FILE *fd; /*filehandle used for PICCDEV*/ -SCARDCONTEXT hcontext; -SCARDHANDLE hcard; -SCARD_READERSTATE rstate; - -char reader_name[MAX_READERNAME]; static sighandler_t register_sig(int signo, sighandler_t sighandler); void checkSig(int signo); unsigned int read_from_device(unsigned char *inputBuffer); -int transmit_to_pcsc(unsigned char *inputBuffer, unsigned int inputLength, unsigned char *outputBuffer, unsigned int *outputLength); void write_to_device(unsigned char *buffer, unsigned int msglength); void setup(void); void cleanup(void);