diff --git a/.gitignore b/.gitignore index 97696dc..4f4cde0 100644 --- a/.gitignore +++ b/.gitignore @@ -6,5 +6,7 @@ .depend *.o *.so -hexStringTest +*.dylib +hexStringTest* socketTest +Testing* diff --git a/de.persosim.driver.linux/Makefile b/de.persosim.driver.linux/Makefile deleted file mode 100644 index fe47f2c..0000000 --- a/de.persosim.driver.linux/Makefile +++ /dev/null @@ -1,50 +0,0 @@ -CC = cc -CFLAGS = -g -std=gnu99 -fpic -Werror -INCLUDE = -I. -I/usr/include/PCSC -DEPENDFILE = .depend - -#LDFLAGS = -lm -#LDLIBS = -lm - - -OBJ := $(filter-out %test.o %Test.o, $(patsubst %.c,%.o,$(wildcard *.c))) -LIBNAME := ifdhPersoSim.so -PREFIX = /usr/local/pcsc - -DEFS = -DPCSC_DEBUG=1 #-DATR_DEBUG=1 - -all: $(LIBNAME) tests - -# gennerate and pull in dependency info -$(DEPENDFILE): *.c *.h - $(CC) -MM $+ > $(DEPENDFILE) --include $(DEPENDFILE) - -clean: - rm -f *.o $(LIBNAME) $(DEPENDFILE) *Test - -install: $(LIBNAME) - sudo cp reader.conf /etc/reader.conf.d/persoSim - sudo cp $(LIBNAME) /usr/lib/pcsc/drivers/serial/ - -uninstall: - sudo rm -f /etc/reader.conf.d/persoSim - sudo rm -f /usr/lib/pcsc/drivers/serial/$(LIBNAME) - -tests: hexStringTest - -runtests: tests - ./hexStringTest - -%.so: $(OBJ) - $(CC) $(CFLAGS) -shared $(OBJ) -o $@ - -%.o : %.c - $(CC) $(CFLAGS) -c $< $(INCLUDE) $(DEFS) - -% : %.c hexString.o - #TODO remove the hardcoded dependecy above - $(CC) $(CFLAGS) $^ -o $@ $(INCLUDE) - -.PHONY: clean test - diff --git a/de.persosim.driver.linux/README b/de.persosim.driver.linux/README deleted file mode 100644 index bd797b7..0000000 --- a/de.persosim.driver.linux/README +++ /dev/null @@ -1,19 +0,0 @@ -PersoSim - Der Open Source Simulator für den elektronischen Personalausweis - -Stand: 12.01.2015 - - -*Systemvorraussetzungen* -Bisher getestet unter Ubuntu 12.04 LTS -Benötigt werden zusätzlich zur Standardinstallation die folgenden Pakete -pcscd -pcsc-tools -libpcsclite-dev -Diese können per "sudo apt-get install pcscd pcsc-tools libpcsclite-dev" installiert werden. - - - -*Installation* -Das Linux-Treiberpaket liegt im Moment lediglich im Quellcode vor und kann mit der weit verbreiteten Kommandokombination "make && make install" kompiliert und installiert werden. - -Solange kein Simulator läuft, meldet der Treiber "Keine Karte im Leser". Sobald ein Simulator am konfigurierten Port verfügbar ist, ist dieser über den Treiber nutzbar. diff --git a/de.persosim.driver.linux/reader.conf b/de.persosim.driver.linux/reader.conf deleted file mode 100644 index fa91d96..0000000 --- a/de.persosim.driver.linux/reader.conf +++ /dev/null @@ -1,14 +0,0 @@ -FRIENDLYNAME "PersoSimHandshake" -DEVICENAME localhost:5678 -LIBPATH /usr/lib/pcsc/drivers/serial/ifdhPersoSim.so -CHANNELID 0x8C7B - -FRIENDLYNAME "PersoSim1" -DEVICENAME localhost:5678 -LIBPATH /usr/lib/pcsc/drivers/serial/ifdhPersoSim.so -CHANNELID 0x8C7C - -FRIENDLYNAME "PersoSim2" -DEVICENAME localhost:5678 -LIBPATH /usr/lib/pcsc/drivers/serial/ifdhPersoSim.so -CHANNELID 0x8C7D diff --git a/de.persosim.driver.linux/.cproject b/de.persosim.driver.unix/.cproject similarity index 100% rename from de.persosim.driver.linux/.cproject rename to de.persosim.driver.unix/.cproject diff --git a/de.persosim.driver.linux/.project b/de.persosim.driver.unix/.project similarity index 100% rename from de.persosim.driver.linux/.project rename to de.persosim.driver.unix/.project diff --git a/de.persosim.driver.unix/CMakeLists.txt b/de.persosim.driver.unix/CMakeLists.txt new file mode 100644 index 0000000..e3c986d --- /dev/null +++ b/de.persosim.driver.unix/CMakeLists.txt @@ -0,0 +1,62 @@ +cmake_minimum_required(VERSION 3.0) +project("de.persosim.driver.unix" VERSION 0.8.0) + +if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + set(IS_LINUX TRUE) +endif() + +if(!APPLE AND !IS_LINUX) + message(FATAL_ERROR "Currently only OS X and Linux platforms are supported") +endif() + + +if(IS_LINUX) + file(GLOB SRC_FILES *.c) +elseif(APPLE) + file(GLOB SRC_FILES *.c MacOSX/*.c) +endif() +list(REMOVE_ITEM SRC_FILES ${PROJECT_SOURCE_DIR}/hexStringTest.c) + + +# Build the library +set(LIB_NAME ifdhPersoSim) +set(CMAKE_C_FLAGS "-g -std=gnu99 -fpic") +add_definitions(-DPCSC_DEBUG=1) +#add_definitions(-DATR_DEBUG=1) +if(IS_LINUX) + include_directories(${PROJECT_SOURCE_DIR} /usr/include/PCSC) +elseif(APPLE) + include_directories(${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/MacOSX) + add_definitions(-DUSE_SYSLOG -DRESPONSECODE_DEFINED_IN_WINTYPES_H) +endif() +add_library(${LIB_NAME} SHARED ${SRC_FILES}) + + +# Create the installation files +if(IS_LINUX) + set(LIBPATH "/usr/lib/pcsc/drivers/serial/${CMAKE_SHARED_LIBRARY_PREFIX}${LIB_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}") +elseif(APPLE) + set(BUNDLEPATH "/usr/local/libexec/SmartCardServices/drivers/${LIB_NAME}.bundle") + set(LIBPATH ${BUNDLEPATH}) + set(CFBUNDLEEXECUTABLE ${CMAKE_SHARED_LIBRARY_PREFIX}${LIB_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}) + configure_file("${PROJECT_SOURCE_DIR}/MacOSX/Info.plist.in" "${PROJECT_BINARY_DIR}/Info.plist") +endif() +configure_file("${PROJECT_SOURCE_DIR}/reader.conf.in" "${PROJECT_BINARY_DIR}/reader.conf") + + +# Specify installations files and locations +if(IS_LINUX) + install(TARGETS ${LIB_NAME} DESTINATION "/usr/lib/pcsc/drivers/serial/") + install(FILES ${PROJECT_BINARY_DIR}/reader.conf DESTINATION "/etc/reader.conf.d/" RENAME "${LIB_NAME}.conf") +elseif(APPLE) + install(FILES ${PROJECT_BINARY_DIR}/Info.plist DESTINATION "${BUNDLEPATH}/Contents") + install(TARGETS ${LIB_NAME} DESTINATION "${BUNDLEPATH}/Contents/MacOS") + install(FILES ${PROJECT_BINARY_DIR}/reader.conf DESTINATION "/etc/") +endif() + + +# Build the test (you may run the test by invoking make test) +enable_testing() +include(CTest) +add_executable(hexStringTest hexStringTest.c hexString.c) +add_test(NAME hexStringTest COMMAND ${CMAKE_BINARY_DIR}/hexStringTest) diff --git a/de.persosim.driver.unix/MacOSX/.DS_Store b/de.persosim.driver.unix/MacOSX/.DS_Store new file mode 100644 index 0000000..108a47e Binary files /dev/null and b/de.persosim.driver.unix/MacOSX/.DS_Store differ diff --git a/de.persosim.driver.unix/MacOSX/Info.plist.in b/de.persosim.driver.unix/MacOSX/Info.plist.in new file mode 100644 index 0000000..aa82f01 --- /dev/null +++ b/de.persosim.driver.unix/MacOSX/Info.plist.in @@ -0,0 +1,35 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + BNDL + CFBundleSignature + ???? + CFBundleVersion + @PROJECT_VERSION@ + ifdCapabilities + 0x00000000 + ifdProtocolSupport + 0x00000001 + ifdVersionNumber + 0x00000001 + + CFBundleExecutable + @CFBUNDLEEXECUTABLE@ + + ifdManufacturerString + Federal Office for Information Security, Germany + + ifdProductString + Driver for virtual smart card reader PersoSim + + ifdFriendlyName + PersoSim smart card reader + + diff --git a/de.persosim.driver.unix/MacOSX/debug.c b/de.persosim.driver.unix/MacOSX/debug.c new file mode 100644 index 0000000..1302b23 --- /dev/null +++ b/de.persosim.driver.unix/MacOSX/debug.c @@ -0,0 +1,181 @@ +/* + debug.c: log (or not) messages + Copyright (C) 2003-2011 Ludovic Rousseau + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "misc.h" +#include "debug.h" + +#include +#include +#include +#include +#include + +#ifdef USE_SYSLOG +#include +#endif + + +#undef LOG_TO_STDERR + +#ifdef LOG_TO_STDERR +#define LOG_STREAM stderr +#else +#define LOG_STREAM stdout +#endif + +void log_msg(const int priority, const char *fmt, ...) +{ + char debug_buffer[160]; /* up to 2 lines of 80 characters */ + va_list argptr; + static struct timeval last_time = { 0, 0 }; + struct timeval new_time = { 0, 0 }; + struct timeval tmp; + int delta; +#ifdef USE_SYSLOG + int syslog_level; + + switch(priority) + { + case PCSC_LOG_CRITICAL: + syslog_level = LOG_CRIT; + break; + case PCSC_LOG_ERROR: + syslog_level = LOG_ERR; + break; + case PCSC_LOG_INFO: + syslog_level = LOG_INFO; + break; + default: + syslog_level = LOG_DEBUG; + } +#else + const char *color_pfx = "", *color_sfx = ""; + const char *time_pfx = "", *time_sfx = ""; + static int initialized = 0; + static int LogDoColor = 0; + + if (!initialized) + { + char *term; + + initialized = 1; + term = getenv("TERM"); + if (term) + { + const char *terms[] = { "linux", "xterm", "xterm-color", "Eterm", "rxvt", "rxvt-unicode", "xterm-256color" }; + unsigned int i; + + /* for each known color terminal */ + for (i = 0; i < COUNT_OF(terms); i++) + { + /* we found a supported term? */ + if (0 == strcmp(terms[i], term)) + { + LogDoColor = 1; + break; + } + } + } + } + + if (LogDoColor) + { + color_sfx = "\33[0m"; + time_sfx = color_sfx; + time_pfx = "\33[36m"; /* Cyan */ + + switch (priority) + { + case PCSC_LOG_CRITICAL: + color_pfx = "\33[01;31m"; /* bright + Red */ + break; + + case PCSC_LOG_ERROR: + color_pfx = "\33[35m"; /* Magenta */ + break; + + case PCSC_LOG_INFO: + color_pfx = "\33[34m"; /* Blue */ + break; + + case PCSC_LOG_DEBUG: + color_pfx = ""; /* normal (black) */ + color_sfx = ""; + break; + } + } +#endif + + gettimeofday(&new_time, NULL); + if (0 == last_time.tv_sec) + last_time = new_time; + + tmp.tv_sec = new_time.tv_sec - last_time.tv_sec; + tmp.tv_usec = new_time.tv_usec - last_time.tv_usec; + if (tmp.tv_usec < 0) + { + tmp.tv_sec--; + tmp.tv_usec += 1000000; + } + if (tmp.tv_sec < 100) + delta = tmp.tv_sec * 1000000 + tmp.tv_usec; + else + delta = 99999999; + + last_time = new_time; + + va_start(argptr, fmt); + (void)vsnprintf(debug_buffer, sizeof debug_buffer, fmt, argptr); + va_end(argptr); + +#ifdef USE_SYSLOG + syslog(syslog_level, "%.8d %s", delta, debug_buffer); +#else + (void)fprintf(LOG_STREAM, "%s%.8d%s %s%s%s\n", time_pfx, delta, time_sfx, + color_pfx, debug_buffer, color_sfx); + fflush(LOG_STREAM); +#endif +} /* log_msg */ + +void log_xxd(const int priority, const char *msg, const unsigned char *buffer, + const int len) +{ + int i; + char *c, debug_buffer[len*3 + strlen(msg) +1]; + size_t l; + + (void)priority; + + l = strlcpy(debug_buffer, msg, sizeof debug_buffer); + c = debug_buffer + l; + + for (i = 0; i < len; ++i) + { + /* 2 hex characters, 1 space, 1 NUL : total 4 characters */ + (void)snprintf(c, 4, "%02X ", buffer[i]); + c += 3; + } + +#ifdef USE_SYSLOG + syslog(LOG_DEBUG, "%s", debug_buffer); +#else + (void)fprintf(LOG_STREAM, "%s\n", debug_buffer); + fflush(LOG_STREAM); +#endif +} /* log_xxd */ diff --git a/de.persosim.driver.unix/MacOSX/debug.h b/de.persosim.driver.unix/MacOSX/debug.h new file mode 100644 index 0000000..6508196 --- /dev/null +++ b/de.persosim.driver.unix/MacOSX/debug.h @@ -0,0 +1,96 @@ +/* + debug.h: log (or not) messages using syslog + Copyright (C) 2003-2008 Ludovic Rousseau + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +/* + * DEBUG_CRITICAL("text"); + * log "text" if (LogLevel & DEBUG_LEVEL_CRITICAL) is TRUE + * + * DEBUG_CRITICAL2("text: %d", 1234); + * log "text: 1234" if (DEBUG_LEVEL_CRITICAL & DEBUG_LEVEL_CRITICAL) is TRUE + * the format string can be anything printf() can understand + * + * same thing for DEBUG_INFO, DEBUG_COMM and DEBUG_PERIODIC + * + * DEBUG_XXD(msg, buffer, size); + * log a dump of buffer if (LogLevel & DEBUG_LEVEL_COMM) is TRUE + * + */ + +#ifndef _GCDEBUG_H_ +#define _GCDEBUG_H_ + +/* You can't do #ifndef __FUNCTION__ */ +#if !defined(__GNUC__) && !defined(__IBMC__) +#define __FUNCTION__ "" +#endif + +extern int LogLevel; + +#define DEBUG_LEVEL_CRITICAL 1 +#define DEBUG_LEVEL_INFO 2 +#define DEBUG_LEVEL_COMM 4 +#define DEBUG_LEVEL_PERIODIC 8 + +#include /* from pcsc-lite */ + +/* DEBUG_CRITICAL */ +#define DEBUG_CRITICAL(fmt) if (LogLevel & DEBUG_LEVEL_CRITICAL) Log1(PCSC_LOG_CRITICAL, fmt) + +#define DEBUG_CRITICAL2(fmt, data) if (LogLevel & DEBUG_LEVEL_CRITICAL) Log2(PCSC_LOG_CRITICAL, fmt, data) + +#define DEBUG_CRITICAL3(fmt, data1, data2) if (LogLevel & DEBUG_LEVEL_CRITICAL) Log3(PCSC_LOG_CRITICAL, fmt, data1, data2) + +#define DEBUG_CRITICAL4(fmt, data1, data2, data3) if (LogLevel & DEBUG_LEVEL_CRITICAL) Log4(PCSC_LOG_CRITICAL, fmt, data1, data2, data3) + +#define DEBUG_CRITICAL5(fmt, data1, data2, data3, data4) if (LogLevel & DEBUG_LEVEL_CRITICAL) Log5(PCSC_LOG_CRITICAL, fmt, data1, data2, data3, data4) + +/* DEBUG_INFO */ +#define DEBUG_INFO1(fmt) if (LogLevel & DEBUG_LEVEL_INFO) Log1(PCSC_LOG_INFO, fmt) + +#define DEBUG_INFO2(fmt, data) if (LogLevel & DEBUG_LEVEL_INFO) Log2(PCSC_LOG_INFO, fmt, data) + +#define DEBUG_INFO3(fmt, data1, data2) if (LogLevel & DEBUG_LEVEL_INFO) Log3(PCSC_LOG_INFO, fmt, data1, data2) + +#define DEBUG_INFO4(fmt, data1, data2, data3) if (LogLevel & DEBUG_LEVEL_INFO) Log4(PCSC_LOG_INFO, fmt, data1, data2, data3) + +#define DEBUG_INFO5(fmt, data1, data2, data3, data4) if (LogLevel & DEBUG_LEVEL_INFO) Log5(PCSC_LOG_INFO, fmt, data1, data2, data3, data4) + +#define DEBUG_INFO_XXD(msg, buffer, size) if (LogLevel & DEBUG_LEVEL_INFO) LogXxd(PCSC_LOG_INFO, msg, buffer, size) + +/* DEBUG_PERIODIC */ +#define DEBUG_PERIODIC(fmt) if (LogLevel & DEBUG_LEVEL_PERIODIC) Log1(PCSC_LOG_DEBUG, fmt) + +#define DEBUG_PERIODIC2(fmt, data) if (LogLevel & DEBUG_LEVEL_PERIODIC) Log2(PCSC_LOG_DEBUG, fmt, data) + +#define DEBUG_PERIODIC3(fmt, data1, data2) if (LogLevel & DEBUG_LEVEL_PERIODIC) Log3(PCSC_LOG_DEBUG, fmt, data1, data2) + +/* DEBUG_COMM */ +#define DEBUG_COMM(fmt) if (LogLevel & DEBUG_LEVEL_COMM) Log1(PCSC_LOG_DEBUG, fmt) + +#define DEBUG_COMM2(fmt, data) if (LogLevel & DEBUG_LEVEL_COMM) Log2(PCSC_LOG_DEBUG, fmt, data) + +#define DEBUG_COMM3(fmt, data1, data2) if (LogLevel & DEBUG_LEVEL_COMM) Log3(PCSC_LOG_DEBUG, fmt, data1, data2) + +#define DEBUG_COMM4(fmt, data1, data2, data3) if (LogLevel & DEBUG_LEVEL_COMM) Log4(PCSC_LOG_DEBUG, fmt, data1, data2, data3) + +/* DEBUG_XXD */ +#define DEBUG_XXD(msg, buffer, size) if (LogLevel & DEBUG_LEVEL_COMM) LogXxd(PCSC_LOG_DEBUG, msg, buffer, size) + +#endif + diff --git a/de.persosim.driver.unix/MacOSX/debuglog.h b/de.persosim.driver.unix/MacOSX/debuglog.h new file mode 100644 index 0000000..30c45fd --- /dev/null +++ b/de.persosim.driver.unix/MacOSX/debuglog.h @@ -0,0 +1,133 @@ +/* + * MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html ) + * + * Copyright (C) 1999-2004 + * David Corcoran + * Copyright (C) 1999-2011 + * Ludovic Rousseau + * +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief This handles debugging. + * + * @note log message is sent to syslog or stderr depending on --foreground + * command line argument + * + * @code + * Log1(priority, "text"); + * log "text" with priority level priority + * Log2(priority, "text: %d", 1234); + * log "text: 1234" + * the format string can be anything printf() can understand + * Log3(priority, "text: %d %d", 1234, 5678); + * log "text: 1234 5678" + * the format string can be anything printf() can understand + * LogXxd(priority, msg, buffer, size); + * log "msg" + a hex dump of size bytes of buffer[] + * @endcode + */ + +#ifndef __debuglog_h__ +#define __debuglog_h__ + +#ifndef PCSC_API +#define PCSC_API +#endif + +enum { + DEBUGLOG_NO_DEBUG = 0, + DEBUGLOG_SYSLOG_DEBUG, + DEBUGLOG_STDOUT_DEBUG, + DEBUGLOG_STDOUT_COLOR_DEBUG +}; + +#define DEBUG_CATEGORY_NOTHING 0 +#define DEBUG_CATEGORY_APDU 1 +#define DEBUG_CATEGORY_SW 2 + +enum { + PCSC_LOG_DEBUG = 0, + PCSC_LOG_INFO, + PCSC_LOG_ERROR, + PCSC_LOG_CRITICAL +}; + +/* You can't do #ifndef __FUNCTION__ */ +#if !defined(__GNUC__) && !defined(__IBMC__) +#define __FUNCTION__ "" +#endif + +#ifndef __GNUC__ +#define __attribute__(x) /*nothing*/ +#endif + +#ifdef NO_LOG + +#define Log0(priority) do { } while(0) +#define Log1(priority, fmt) do { } while(0) +#define Log2(priority, fmt, data) do { } while(0) +#define Log3(priority, fmt, data1, data2) do { } while(0) +#define Log4(priority, fmt, data1, data2, data3) do { } while(0) +#define Log5(priority, fmt, data1, data2, data3, data4) do { } while(0) +#define Log9(priority, fmt, data1, data2, data3, data4, data5, data6, data7, data8) do { } while(0) +#define LogXxd(priority, msg, buffer, size) do { } while(0) + +#define DebugLogA(a) +#define DebugLogB(a, b) +#define DebugLogC(a, b,c) + +#else + +#define Log0(priority) log_msg(priority, "%s:%d:%s()", __FILE__, __LINE__, __FUNCTION__) +#define Log1(priority, fmt) log_msg(priority, "%s:%d:%s() " fmt, __FILE__, __LINE__, __FUNCTION__) +#define Log2(priority, fmt, data) log_msg(priority, "%s:%d:%s() " fmt, __FILE__, __LINE__, __FUNCTION__, data) +#define Log3(priority, fmt, data1, data2) log_msg(priority, "%s:%d:%s() " fmt, __FILE__, __LINE__, __FUNCTION__, data1, data2) +#define Log4(priority, fmt, data1, data2, data3) log_msg(priority, "%s:%d:%s() " fmt, __FILE__, __LINE__, __FUNCTION__, data1, data2, data3) +#define Log5(priority, fmt, data1, data2, data3, data4) log_msg(priority, "%s:%d:%s() " fmt, __FILE__, __LINE__, __FUNCTION__, data1, data2, data3, data4) +#define Log9(priority, fmt, data1, data2, data3, data4, data5, data6, data7, data8) log_msg(priority, "%s:%d:%s() " fmt, __FILE__, __LINE__, __FUNCTION__, data1, data2, data3, data4, data5, data6, data7, data8) +#define LogXxd(priority, msg, buffer, size) log_xxd(priority, msg, buffer, size) + +#define DebugLogA(a) Log1(PCSC_LOG_INFO, a) +#define DebugLogB(a, b) Log2(PCSC_LOG_INFO, a, b) +#define DebugLogC(a, b,c) Log3(PCSC_LOG_INFO, a, b, c) + +#endif /* NO_LOG */ + +PCSC_API void log_msg(const int priority, const char *fmt, ...) + __attribute__((format(printf, 2, 3))); + +PCSC_API void log_xxd(const int priority, const char *msg, + const unsigned char *buffer, const int size); + +void DebugLogSuppress(const int); +void DebugLogSetLogType(const int); +int DebugLogSetCategory(const int); +void DebugLogCategory(const int, const unsigned char *, const int); +PCSC_API void DebugLogSetLevel(const int level); + +#endif /* __debuglog_h__ */ + diff --git a/de.persosim.driver.unix/MacOSX/ifdhandler.h b/de.persosim.driver.unix/MacOSX/ifdhandler.h new file mode 100644 index 0000000..ffd31a0 --- /dev/null +++ b/de.persosim.driver.unix/MacOSX/ifdhandler.h @@ -0,0 +1,820 @@ +/* + * MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html ) + * + * Copyright (C) 1999-2004 + * David Corcoran + * Copyright (C) 2003-2004 + * Damien Sauveron + * Copyright (C) 2002-2011 + * Ludovic Rousseau + * +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @defgroup IFDHandler IFDHandler + * @brief This provides reader specific low-level calls. + +The routines specified hereafter will allow you to write an IFD handler +for the PC/SC Lite resource manager. Please use the complement +developer's kit complete with headers and Makefile at: +http://www.musclecard.com/drivers.html + +This gives a common API for communication to most readers in a +homogeneous fashion. This document assumes that the driver developer is +experienced with standards such as ISO-7816-(1, 2, 3, 4), EMV and MCT +specifications. For listings of these specifications please access the +above web site. + +@section UsbReaders USB readers + +USB readers use the bundle approach so that the reader can be loaded +and unloaded upon automatic detection of the device. The bundle +approach is simple: the actual library is just embedded in a +directory so additional information can be gathered about the device. + +A bundle looks like the following: + +@verbatim +GenericReader.bundle/ + Contents/ + Info.plist - XML file describing the reader + MacOS/ - Driver directory for OS X + Solaris/ - Driver directory for Solaris + Linux/ - Driver directory for Linux + HPUX/ - Driver directory for HPUX +@endverbatim + +The @c Info.plist file describes the driver and gives the loader +all the necessary information. The following must be contained in the +@c Info.plist file: + +@subsection ifdVendorID + +The vendor ID of the USB device. + +Example: + +@verbatim + ifdVendorID + 0x04E6 +@endverbatim + +You may have an OEM of this reader in which an additional @c +can be used like in the below example: + +@verbatim + ifdVendorID + + 0x04E6 + 0x0973 + +@endverbatim + +If multiples exist all the other parameters must have a second value +also. You may chose not to support this feature but it is useful when +reader vendors OEM products so you only distribute one driver. + + +The CCID driver from Ludovic Rousseau +http://pcsclite.alioth.debian.org/ccid.html uses this feature since the +same driver supports many different readers. + +@subsection ifdProductID + + The product id of the USB device. + +@verbatim + ifdProductID + 0x3437 +@endverbatim + +@subsection ifdFriendlyName + + Example: + +@verbatim + ifdFriendlyName + SCM Microsystems USB Reader +@endverbatim + +The reader name must use the ASCII character set. + +@subsection CFBundleExecutable + + The executable name which exists in the particular platform's directory. + + Example: + +@verbatim + CFBundleExecutable + libccid.so.0.4.2 +@endverbatim + +@subsection ifdCapabilities + + List of capabilities supported by the driver. This is a bit field. Possible values are: + +- 0 + No special capabilities +- 1 IFD_GENERATE_HOTPLUG + The driver supports the hot plug feature. + +Complete sample file: + +@verbatim + + + + + CFBundleDevelopmentRegion + English + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + BNDL + CFBundleSignature + ???? + CFBundleVersion + 0.0.1d1 + ifdCapabilities + 0x00000000 + ifdProtocolSupport + 0x00000001 + ifdVersionNumber + 0x00000001 + + CFBundleExecutable + libfoobar.so.x.y + + ifdManufacturerString + Foo bar inc. + + ifdProductString + Driver for Foobar reader, version x.y + + ifdVendorID + 0x1234 + + ifdProductID + 0x5678 + + ifdFriendlyName + Foobar USB reader + + +@endverbatim + +As indicated in the XML file the DTD is available at +http://www.apple.com/DTDs/PropertyList-1.0.dtd. + +@section SerialReaders Serial readers + +Serial drivers must be configured to operate on a particular port and +respond to a particular name. The @c reader.conf file is used for this +purpose. + +It has the following syntax: + +@verbatim +# Configuration file for pcsc-lite +# David Corcoran + +FRIENDLYNAME Generic Reader +DEVICENAME /dev/ttyS0 +LIBPATH /usr/lib/pcsc/drivers/libgen_ifd.so +CHANNELID 1 +@endverbatim + +The pound sign # denotes a comment. + +@subsection FRIENDLYNAME +The FRIENDLYNAME field is an arbitrary text used to identify the reader. +This text is displayed by commands like @c pcsc_scan +http://ludovic.rousseau.free.fr/softwares/pcsc-tools/ that prints the +names of all the connected and detected readers. + +@subsection DEVICENAME +The DEVICENAME field was not used for old drivers (using the IFD handler +version 2.0 or previous). It is now (IFD handler version 3.0) used to +identify the physical port on which the reader is connected. This is +the device name of this port. It is dependent of the OS kernel. For +example the first serial port device is called @c /dev/ttyS0 under Linux +and @c /dev/cuaa0 under FreeBSD. + +If you want to use IFDHCreateChannel() instead of +IFDHCreateChannelByName() then do not use any DEVICENAME line in the +configuration file. IFDHCreateChannel() will then be called with the +CHANNELID parameter. + +@subsection LIBPATH +The LIBPATH field is the filename of the driver code. The driver is a +dynamically loaded piece of code (generally a @c drivername.so* file). + +@subsection CHANNELID +The CHANNELID is no more used for recent drivers (IFD handler 3.0) and +has been superseded by DEVICENAME. + +If you have an old driver this field is used to indicate the port to +use. You should read your driver documentation to know what information +is needed here. It should be the serial port number for a serial reader. + +CHANNELID was the numeric version of the port in which the reader will +be located. This may be done by a symbolic link where @c /dev/pcsc/1 is +the first device which may be a symbolic link to @c /dev/ttyS0 or +whichever location your reader resides. + + */ + +#ifndef _ifd_handler_h_ +#define _ifd_handler_h_ + +#include + + /* + * List of data structures available to ifdhandler + */ + typedef struct _DEVICE_CAPABILITIES + { + LPSTR Vendor_Name; /**< Tag 0x0100 */ + LPSTR IFD_Type; /**< Tag 0x0101 */ + DWORD IFD_Version; /**< Tag 0x0102 */ + LPSTR IFD_Serial; /**< Tag 0x0103 */ + DWORD IFD_Channel_ID; /**< Tag 0x0110 */ + + DWORD Asynch_Supported; /**< Tag 0x0120 */ + DWORD Default_Clock; /**< Tag 0x0121 */ + DWORD Max_Clock; /**< Tag 0x0122 */ + DWORD Default_Data_Rate; /**< Tag 0x0123 */ + DWORD Max_Data_Rate; /**< Tag 0x0124 */ + DWORD Max_IFSD; /**< Tag 0x0125 */ + DWORD Synch_Supported; /**< Tag 0x0126 */ + DWORD Power_Mgmt; /**< Tag 0x0131 */ + DWORD Card_Auth_Devices; /**< Tag 0x0140 */ + DWORD User_Auth_Device; /**< Tag 0x0142 */ + DWORD Mechanics_Supported; /**< Tag 0x0150 */ + DWORD Vendor_Features; /**< Tag 0x0180 - 0x01F0 User Defined. */ + } + DEVICE_CAPABILITIES, *PDEVICE_CAPABILITIES; + + typedef struct _ICC_STATE + { + UCHAR ICC_Presence; /**< Tag 0x0300 */ + UCHAR ICC_Interface_Status; /**< Tag 0x0301 */ + UCHAR ATR[MAX_ATR_SIZE]; /**< Tag 0x0303 */ + UCHAR ICC_Type; /**< Tag 0x0304 */ + } + ICC_STATE, *PICC_STATE; + + typedef struct _PROTOCOL_OPTIONS + { + DWORD Protocol_Type; /**< Tag 0x0201 */ + DWORD Current_Clock; /**< Tag 0x0202 */ + DWORD Current_F; /**< Tag 0x0203 */ + DWORD Current_D; /**< Tag 0x0204 */ + DWORD Current_N; /**< Tag 0x0205 */ + DWORD Current_W; /**< Tag 0x0206 */ + DWORD Current_IFSC; /**< Tag 0x0207 */ + DWORD Current_IFSD; /**< Tag 0x0208 */ + DWORD Current_BWT; /**< Tag 0x0209 */ + DWORD Current_CWT; /**< Tag 0x020A */ + DWORD Current_EBC; /**< Tag 0x020B */ + } + PROTOCOL_OPTIONS, *PPROTOCOL_OPTIONS; + + /** + * Use by SCardTransmit() + */ + typedef struct _SCARD_IO_HEADER + { + DWORD Protocol; + DWORD Length; + } + SCARD_IO_HEADER, *PSCARD_IO_HEADER; + + /* + * The list of tags should be alot more but this is all I use in the + * meantime + */ +#define TAG_IFD_ATR 0x0303 /**< ATR */ +#define TAG_IFD_SLOTNUM 0x0180 /**< select a slot */ +#define TAG_IFD_SLOT_THREAD_SAFE 0x0FAC /**< support access to different slots of the reader */ +#define TAG_IFD_THREAD_SAFE 0x0FAD /**< driver is thread safe */ +#define TAG_IFD_SLOTS_NUMBER 0x0FAE /**< number of slots of the reader */ +#define TAG_IFD_SIMULTANEOUS_ACCESS 0x0FAF /**< number of reader the driver can manage */ +#define TAG_IFD_POLLING_THREAD 0x0FB0 /**< not used. See TAG_IFD_POLLING_THREAD_WITH_TIMEOUT */ +#define TAG_IFD_POLLING_THREAD_KILLABLE 0x0FB1 /**< the polling thread can be killed */ +#define TAG_IFD_STOP_POLLING_THREAD 0x0FB2 /**< method used to stop the polling thread (instead of just pthread_kill()) */ +#define TAG_IFD_POLLING_THREAD_WITH_TIMEOUT 0x0FB3 /**< driver uses a polling thread with a timeout parameter */ + + /* + * IFD Handler version number enummerations + */ +#define IFD_HVERSION_1_0 0x00010000 +#define IFD_HVERSION_2_0 0x00020000 +#define IFD_HVERSION_3_0 0x00030000 + + /* + * List of defines available to ifdhandler + */ +#define IFD_POWER_UP 500 /**< power up the card */ +#define IFD_POWER_DOWN 501 /**< power down the card */ +#define IFD_RESET 502 /**< warm reset */ + +#define IFD_NEGOTIATE_PTS1 1 /**< negotiate PTS1 */ +#define IFD_NEGOTIATE_PTS2 2 /**< negotiate PTS2 */ +#define IFD_NEGOTIATE_PTS3 4 /**< negotiate PTS3 */ + +#define IFD_SUCCESS 0 /**< no error */ +#define IFD_ERROR_TAG 600 /**< tag unknown */ +#define IFD_ERROR_SET_FAILURE 601 /**< set failed */ +#define IFD_ERROR_VALUE_READ_ONLY 602 /**< value is read only */ +#define IFD_ERROR_PTS_FAILURE 605 /**< failed to negotiate PTS */ +#define IFD_ERROR_NOT_SUPPORTED 606 +#define IFD_PROTOCOL_NOT_SUPPORTED 607 /**< requested protocol not supported */ +#define IFD_ERROR_POWER_ACTION 608 /**< power up failed */ +#define IFD_ERROR_SWALLOW 609 +#define IFD_ERROR_EJECT 610 +#define IFD_ERROR_CONFISCATE 611 +#define IFD_COMMUNICATION_ERROR 612 /**< generic error */ +#define IFD_RESPONSE_TIMEOUT 613 /**< timeout */ +#define IFD_NOT_SUPPORTED 614 /**< request is not supported */ +#define IFD_ICC_PRESENT 615 /**< card is present */ +#define IFD_ICC_NOT_PRESENT 616 /**< card is absent */ +/** + * The \ref IFD_NO_SUCH_DEVICE error must be returned by the driver when + * it detects the reader is no more present. This will tell pcscd to + * remove the reader from the list of available readers. + */ +#define IFD_NO_SUCH_DEVICE 617 +#define IFD_ERROR_INSUFFICIENT_BUFFER 618 /**< buffer is too small */ + +#ifndef RESPONSECODE_DEFINED_IN_WINTYPES_H + typedef long RESPONSECODE; +#endif + + /* + * If you want to compile a V2.0 IFDHandler, define IFDHANDLERv2 + * before you include this file. + * + * By default it is setup for for most recent version of the API (V3.0) + */ + +#ifndef IFDHANDLERv2 + + /* + * List of Defined Functions Available to IFD_Handler 3.0 + * + * All the functions of IFD_Handler 2.0 are available + * IFDHCreateChannelByName() is new + * IFDHControl() API changed + */ + +/** +This function is required to open a communications channel to the port +listed by @p DeviceName. + +Once the channel is opened the reader must be in a state in which it is +possible to query IFDHICCPresence() for card status. + +@ingroup IFDHandler +@param[in] Lun Logical Unit Number\n + Use this for multiple card slots or multiple readers. 0xXXXXYYYY - + XXXX multiple readers, YYYY multiple slots. The resource manager will + set these automatically. By default the resource manager loads a new + instance of the driver so if your reader does not have more than one + smart card slot then ignore the Lun in all the functions.\n + \n + PC/SC supports the loading of multiple readers through one instance of + the driver in which XXXX is important. XXXX identifies the unique + reader in which the driver communicates to. The driver should set up + an array of structures that asociate this XXXX with the underlying + details of the particular reader. + +@param[in] DeviceName Filename to use by the driver.\n + For drivers configured by @p /etc/reader.conf this is the value of the + field \ref DEVICENAME. + \n + For USB drivers the @p DeviceName must start with @p usb:VID/PID. VID + is the Vendor ID and PID is the Product ID. Both are a 4-digits hex + number. + +Typically the string is generated by: + +@code +printf("usb:%04x/%04x", idVendor, idProduct); +@endcode + +The @p DeviceName string may also contain a more specialised +identification string. This additional information is used to +differentiate between two identical readers connected at the same time. +In this case the driver can't differentiate the two readers using VID +and PID and must use some additional information identifying the USB +port used by each reader. + +- libusb + + For USB drivers using libusb-1.0 http://libusb.sourceforge.net/ for USB + abstraction the @p DeviceName the string may be generated by: + + @code + printf("usb:%04x/%04x:libusb-1.0:%d:%d:%d", + idVendor, idProduct, bus_number, device_address, interface) + @endcode + + So it is something like: usb:08e6/3437:libusb-1.0:7:99:0 under + GNU/Linux. + +- libudev + + If pcscd is compiled with libudev support instead of libusb (default + since pcsc-lite 1.6.8) the string will look like: + + @code + printf("usb:%04x/%04x:libudev:%d:%s", idVendor, idProduct, + bInterfaceNumber, devpath); + @endcode + + bInterfaceNumber is the number of the interface on the device. It is + only usefull for devices with more than one CCID interface. + + devpath is the filename of the device on the file system. + + So it is something like: + usb:08e6/3437:libudev:0:/dev/bus/usb/008/047 + under GNU/Linux. + +- other + + If the driver does not understand the :libusb: or + :libudev: scheme or if a new scheme is used, the driver should + ignore the part it does not understand instead of failing. + + The driver shall recognize the usb:VID/PID part and, only if + possible, the remaining of the DeviceName field. + + It is the responsibility of the driver to correctly identify the reader. + +@return Error codes +@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS) +@retval IFD_COMMUNICATION_ERROR Error has occurred (\ref IFD_COMMUNICATION_ERROR) +@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE) + */ +RESPONSECODE IFDHCreateChannelByName(DWORD Lun, LPSTR DeviceName); + +/** +This function performs a data exchange with the reader (not the card) +specified by Lun. It is responsible for abstracting functionality such +as PIN pads, biometrics, LCD panels, etc. You should follow the MCT and +CTBCS specifications for a list of accepted commands to implement. This +function is fully voluntary and does not have to be implemented unless +you want extended functionality. + +@ingroup IFDHandler +@param[in] Lun Logical Unit Number +@param[in] dwControlCode Control code for the operation\n + This value identifies the specific operation to be performed. This + value is driver specific. +@param[in] TxBuffer Transmit data +@param[in] TxLength Length of this buffer +@param[out] RxBuffer Receive data +@param[in] RxLength Length of the response buffer +@param[out] pdwBytesReturned Length of response\n + This function will be passed the length of the buffer RxBuffer in + RxLength and it must set the length of the received data in + pdwBytesReturned. + +@note + @p *pdwBytesReturned should be set to zero on error. + +@return Error codes +@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS) +@retval IFD_COMMUNICATION_ERROR Error has occurred (\ref IFD_COMMUNICATION_ERROR) +@retval IFD_RESPONSE_TIMEOUT The response timed out (\ref IFD_RESPONSE_TIMEOUT) +@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE) + */ +RESPONSECODE IFDHControl(DWORD Lun, DWORD dwControlCode, PUCHAR + TxBuffer, DWORD TxLength, PUCHAR RxBuffer, DWORD RxLength, + LPDWORD pdwBytesReturned); + +#else + +/** + * Available in IFD_Handler 2.0 + * + * @deprecated + * You should use the new form of IFDHControl() + */ +RESPONSECODE IFDHControl(DWORD Lun, PUCHAR TxBuffer, DWORD TxLength, + PUCHAR RxBuffer, PDWORD RxLength); + +#endif + + /* + * common functions in IFD_Handler 2.0 and 3.0 + */ +/** +This function is required to open a communications channel to the port +listed by Channel. For example, the first serial reader on COM1 would +link to @p /dev/pcsc/1 which would be a symbolic link to @p /dev/ttyS0 +on some machines This is used to help with inter-machine independence. + +On machines with no /dev directory the driver writer may choose to map +their Channel to whatever they feel is appropriate. + +Once the channel is opened the reader must be in a state in which it is +possible to query IFDHICCPresence() for card status. + +USB readers can ignore the @p Channel parameter and query the USB bus +for the particular reader by manufacturer and product id. + +@ingroup IFDHandler +@param[in] Lun Logical Unit Number\n + Use this for multiple card slots or multiple readers. 0xXXXXYYYY - + XXXX multiple readers, YYYY multiple slots. The resource manager will + set these automatically. By default the resource manager loads a new + instance of the driver so if your reader does not have more than one + smart card slot then ignore the Lun in all the functions.\n + \n + PC/SC supports the loading of multiple readers through one instance of + the driver in which XXXX is important. XXXX identifies the unique + reader in which the driver communicates to. The driver should set up + an array of structures that associate this XXXX with the underlying + details of the particular reader. +@param[in] Channel Channel ID + This is denoted by the following: + - 0x000001 @p /dev/pcsc/1 + - 0x000002 @p /dev/pcsc/2 + - 0x000003 @p /dev/pcsc/3 + - 0x000004 @p /dev/pcsc/4 + +@return Error codes +@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS) +@retval IFD_COMMUNICATION_ERROR Error has occurred (\ref IFD_COMMUNICATION_ERROR) +@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE) + + */ +RESPONSECODE IFDHCreateChannel(DWORD Lun, DWORD Channel); + +/** +This function should close the reader communication channel for the +particular reader. Prior to closing the communication channel the reader +should make sure the card is powered down and the terminal is also +powered down. + +@ingroup IFDHandler +@param[in] Lun Logical Unit Number + +@return Error codes +@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS) +@retval IFD_COMMUNICATION_ERROR Error has occurred (\ref IFD_COMMUNICATION_ERROR) +@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE) + */ +RESPONSECODE IFDHCloseChannel(DWORD Lun); + +/** +This function should get the slot/card capabilities for a particular +slot/card specified by Lun. Again, if you have only 1 card slot and +don't mind loading a new driver for each reader then ignore Lun. + +@ingroup IFDHandler +@param[in] Lun Logical Unit Number +@param[in] Tag Tag of the desired data value +- \ref TAG_IFD_ATR + Return the ATR and its size (implementation is mandatory). +- \ref TAG_IFD_SLOTNUM + Unused/deprecated +- \ref SCARD_ATTR_ATR_STRING + Same as \ref TAG_IFD_ATR but this one is not mandatory. It is defined + in Microsoft PC/SC SCardGetAttrib(). +- \ref TAG_IFD_SIMULTANEOUS_ACCESS + Return the number of sessions (readers) the driver can handle in + Value[0]. + This is used for multiple readers sharing the same driver. +- \ref TAG_IFD_THREAD_SAFE + If the driver supports more than one reader (see + \ref TAG_IFD_SIMULTANEOUS_ACCESS above) this tag indicates if the + driver supports access to multiple readers at the same time.\n + Value[0] = 1 indicates the driver supports simultaneous accesses. +- \ref TAG_IFD_SLOTS_NUMBER + Return the number of slots in this reader in Value[0]. +- \ref TAG_IFD_SLOT_THREAD_SAFE + If the reader has more than one slot (see \ref TAG_IFD_SLOTS_NUMBER + above) this tag indicates if the driver supports access to multiple + slots of the same reader at the same time.\n + Value[0] = 1 indicates the driver supports simultaneous slot + accesses. +- \ref TAG_IFD_POLLING_THREAD + Unused/deprecated +- \ref TAG_IFD_POLLING_THREAD_WITH_TIMEOUT + If the driver provides a polling thread then @p Value is a pointer to + this function. The function prototype is: +@verbatim + RESPONSECODE foo(DWORD Lun, int timeout); +@endverbatim +- \ref TAG_IFD_POLLING_THREAD_KILLABLE + Tell if the polling thread can be killed (pthread_kill()) by pcscd +- \ref TAG_IFD_STOP_POLLING_THREAD + Returns a pointer in @p Value to the function used to stop the polling + thread returned by \ref TAG_IFD_POLLING_THREAD_WITH_TIMEOUT. The + function prototype is: +@verbatim + RESPONSECODE foo(DWORD Lun); +@endverbatim +@param[in,out] Length Length of the desired data value +@param[out] Value Value of the desired data + +@return Error codes +@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS) +@retval IFD_ERROR_TAG Invalid tag given (\ref IFD_ERROR_TAG) +@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE) + */ +RESPONSECODE IFDHGetCapabilities(DWORD Lun, DWORD Tag, PDWORD Length, + PUCHAR Value); + +/** +This function should set the slot/card capabilities for a particular +slot/card specified by @p Lun. Again, if you have only 1 card slot and +don't mind loading a new driver for each reader then ignore @p Lun. + +@ingroup IFDHandler +@param[in] Lun Logical Unit Number +@param[in] Tag Tag of the desired data value +@param[in,out] Length Length of the desired data value +@param[out] Value Value of the desired data + +This function is also called when the application uses the PC/SC +SCardGetAttrib() function. The list of supported tags is not limited. + +@return Error codes +@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS) +@retval IFD_ERROR_TAG Invalid tag given (\ref IFD_ERROR_TAG) +@retval IFD_ERROR_SET_FAILURE Could not set value (\ref IFD_ERROR_SET_FAILURE) +@retval IFD_ERROR_VALUE_READ_ONLY Trying to set read only value (\ref IFD_ERROR_VALUE_READ_ONLY) +@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE) + */ +RESPONSECODE IFDHSetCapabilities(DWORD Lun, DWORD Tag, DWORD Length, PUCHAR Value); + +/** +This function should set the Protocol Type Selection (PTS) of a +particular card/slot using the three PTS parameters sent + +@ingroup IFDHandler +@param[in] Lun Logical Unit Number +@param[in] Protocol Desired protocol +- \ref SCARD_PROTOCOL_T0 + T=0 protocol +- \ref SCARD_PROTOCOL_T1 + T=1 protocol +@param[in] Flags Logical OR of possible values to determine which PTS values +to negotiate +- \ref IFD_NEGOTIATE_PTS1 +- \ref IFD_NEGOTIATE_PTS2 +- \ref IFD_NEGOTIATE_PTS3 +@param[in] PTS1 1st PTS Value +@param[in] PTS2 2nd PTS Value +@param[in] PTS3 3rd PTS Value\n + See ISO 7816/EMV documentation. + +@return Error codes +@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS) +@retval IFD_ERROR_PTS_FAILURE Could not set PTS value (\ref IFD_ERROR_PTS_FAILURE) +@retval IFD_COMMUNICATION_ERROR Error has occurred (\ref IFD_COMMUNICATION_ERROR) +@retval IFD_PROTOCOL_NOT_SUPPORTED Protocol is not supported (\ref IFD_PROTOCOL_NOT_SUPPORTED) +@retval IFD_NOT_SUPPORTED Action not supported (\ref IFD_NOT_SUPPORTED) +@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE) + */ +RESPONSECODE IFDHSetProtocolParameters(DWORD Lun, DWORD Protocol, UCHAR Flags, + UCHAR PTS1, UCHAR PTS2, UCHAR PTS3); +/** +This function controls the power and reset signals of the smart card +reader at the particular reader/slot specified by @p Lun. + +@ingroup IFDHandler +@param[in] Lun Logical Unit Number +@param[in] Action Action to be taken on the card +- \ref IFD_POWER_UP + Power up the card (store and return Atr and AtrLength) +- \ref IFD_POWER_DOWN + Power down the card (Atr and AtrLength should be zeroed) +- \ref IFD_RESET + Perform a warm reset of the card (no power down). If the card is not powered then power up the card (store and return Atr and AtrLength) +@param[out] Atr Answer to Reset (ATR) of the card\n + The driver is responsible for caching this value in case + IFDHGetCapabilities() is called requesting the ATR and its length. The + ATR length should not exceed \ref MAX_ATR_SIZE. +@param[in,out] AtrLength Length of the ATR\n + This should not exceed \ref MAX_ATR_SIZE. + +@note +Memory cards without an ATR should return \ref IFD_SUCCESS on reset but the +Atr should be zeroed and the length should be zero Reset errors should +return zero for the AtrLength and return \ref IFD_ERROR_POWER_ACTION. + +@return Error codes +@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS) +@retval IFD_ERROR_POWER_ACTION Error powering/resetting card (\ref IFD_ERROR_POWER_ACTION) +@retval IFD_COMMUNICATION_ERROR Error has occurred (\ref IFD_COMMUNICATION_ERROR) +@retval IFD_NOT_SUPPORTED Action not supported (\ref IFD_NOT_SUPPORTED) +@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE) + */ +RESPONSECODE IFDHPowerICC(DWORD Lun, DWORD Action, PUCHAR Atr, PDWORD + AtrLength); + +/** +This function performs an APDU exchange with the card/slot specified by +Lun. The driver is responsible for performing any protocol specific +exchanges such as T=0, 1, etc. differences. Calling this function will +abstract all protocol differences. + +@ingroup IFDHandler +@param[in] Lun Logical Unit Number +@param[in] SendPci contains two structure members +- Protocol 0, 1, ... 14\n + T=0 ... T=14 +- Length\n + Not used. +@param[in] TxBuffer Transmit APDU\n + Example: "\x00\xA4\x00\x00\x02\x3F\x00" +@param[in] TxLength Length of this buffer +@param[out] RxBuffer Receive APDU\n + Example: "\x61\x14" +@param[in,out] RxLength Length of the received APDU\n + This function will be passed the size of the buffer of RxBuffer and + this function is responsible for setting this to the length of the + received APDU response. This should be ZERO on all errors. The + resource manager will take responsibility of zeroing out any temporary + APDU buffers for security reasons. +@param[out] RecvPci contains two structure members +- Protocol - 0, 1, ... 14\n + T=0 ... T=14 +- Length\n + Not used. + +@note +The driver is responsible for knowing what type of card it has. If the +current slot/card contains a memory card then this command should ignore +the Protocol and use the MCT style commands for support for these style +cards and transmit them appropriately. If your reader does not support +memory cards or you don't want to implement this functionality, then +ignore this. +@par +RxLength should be set to zero on error. +@par +The driver is not responsible for doing an automatic Get Response +command for received buffers containing 61 XX. + +@return Error codes +@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS) +@retval IFD_COMMUNICATION_ERROR Error has occurred (\ref IFD_COMMUNICATION_ERROR) +@retval IFD_RESPONSE_TIMEOUT The response timed out (\ref IFD_RESPONSE_TIMEOUT) +@retval IFD_ICC_NOT_PRESENT ICC is not present (\ref IFD_ICC_NOT_PRESENT) +@retval IFD_NOT_SUPPORTED Action not supported (\ref IFD_NOT_SUPPORTED) +@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE) + */ +RESPONSECODE IFDHTransmitToICC(DWORD Lun, SCARD_IO_HEADER SendPci, + PUCHAR TxBuffer, DWORD TxLength, PUCHAR RxBuffer, PDWORD + RxLength, PSCARD_IO_HEADER RecvPci); + +/** +This function returns the status of the card inserted in the reader/slot +specified by @p Lun. In cases where the device supports asynchronous +card insertion/removal detection, it is advised that the driver manages +this through a thread so the driver does not have to send and receive a +command each time this function is called. + +@ingroup IFDHandler +@param[in] Lun Logical Unit Number + +@return Error codes +@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS) +@retval IFD_COMMUNICATION_ERROR Error has occurred (\ref IFD_COMMUNICATION_ERROR) +@retval IFD_ICC_NOT_PRESENT ICC is not present (\ref IFD_ICC_NOT_PRESENT) +@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE) + */ +RESPONSECODE IFDHICCPresence(DWORD Lun); + +#endif diff --git a/de.persosim.driver.unix/MacOSX/pcsclite.h b/de.persosim.driver.unix/MacOSX/pcsclite.h new file mode 100644 index 0000000..0a454f6 --- /dev/null +++ b/de.persosim.driver.unix/MacOSX/pcsclite.h @@ -0,0 +1,2 @@ +#include +#include diff --git a/de.persosim.driver.unix/MacOSX/winscard.h b/de.persosim.driver.unix/MacOSX/winscard.h new file mode 100644 index 0000000..18dea51 --- /dev/null +++ b/de.persosim.driver.unix/MacOSX/winscard.h @@ -0,0 +1,2 @@ +#include +#include diff --git a/de.persosim.driver.unix/MacOSX/wintypes.h b/de.persosim.driver.unix/MacOSX/wintypes.h new file mode 100644 index 0000000..a9736e8 --- /dev/null +++ b/de.persosim.driver.unix/MacOSX/wintypes.h @@ -0,0 +1 @@ +#include diff --git a/de.persosim.driver.unix/README.md b/de.persosim.driver.unix/README.md new file mode 100644 index 0000000..2bd8bb8 --- /dev/null +++ b/de.persosim.driver.unix/README.md @@ -0,0 +1,28 @@ +# PersoSim - Der Open Source Simulator für den elektronischen Personalausweis +Stand: 02.06.2016 + +## Systemvorraussetzungen +Bisher getestet unter Ubuntu 12.04 LTS und OS X 10.10 + +### Ubuntu 12.04 LTS +Benötigt werden zusätzlich zur Standardinstallation die folgenden Pakete +- pcscd +- pcsc-tools +- libpcsclite-dev + +Diese können per `sudo apt-get install pcscd pcsc-tools libpcsclite-dev` installiert werden. + +### OS X 10.10 +Benötigt wird das Paket XCode, welches über den Mac App Store installiert werden kann. + +## Installation +Das Treiberpaket liegt momentan lediglich im Quellcode vor und kann mit der weit verbreiteten Kommandokombination +``` +cmake . +make +sudo make install +``` +kompiliert und installiert werden. + +# Sonstiges +Solange kein Simulator läuft, meldet der Treiber "Keine Karte im Leser". Sobald ein Simulator am konfigurierten Port verfügbar ist, ist dieser über den Treiber nutzbar. diff --git a/de.persosim.driver.linux/hexString.c b/de.persosim.driver.unix/hexString.c similarity index 100% rename from de.persosim.driver.linux/hexString.c rename to de.persosim.driver.unix/hexString.c diff --git a/de.persosim.driver.linux/hexString.h b/de.persosim.driver.unix/hexString.h similarity index 100% rename from de.persosim.driver.linux/hexString.h rename to de.persosim.driver.unix/hexString.h diff --git a/de.persosim.driver.linux/hexStringTest.c b/de.persosim.driver.unix/hexStringTest.c similarity index 100% rename from de.persosim.driver.linux/hexStringTest.c rename to de.persosim.driver.unix/hexStringTest.c diff --git a/de.persosim.driver.linux/ifdhPersoSim.c b/de.persosim.driver.unix/ifdhPersoSim.c similarity index 100% rename from de.persosim.driver.linux/ifdhPersoSim.c rename to de.persosim.driver.unix/ifdhPersoSim.c diff --git a/de.persosim.driver.unix/misc.h b/de.persosim.driver.unix/misc.h new file mode 100644 index 0000000..ea0d098 --- /dev/null +++ b/de.persosim.driver.unix/misc.h @@ -0,0 +1,83 @@ +/* + * This handles GCC attributes + * + * MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html ) + * + * Copyright (C) 2005-2010 + * Ludovic Rousseau + * +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __misc_h__ +#define __misc_h__ + +/* + * Declare the function as internal to the library: the function name is + * not exported and can't be used by a program linked to the library + * + * see http://gcc.gnu.org/onlinedocs/gcc-3.3.5/gcc/Function-Attributes.html#Function-Attributes + * see http://www.nedprod.com/programs/gccvisibility.html + */ +#if defined __GNUC__ && (! defined (__sun)) && (__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) +#define INTERNAL __attribute__ ((visibility("hidden"))) +#define PCSC_API __attribute__ ((visibility("default"))) +#elif (! defined __GNUC__ ) && defined (__sun) +/* http://wikis.sun.com/display/SunStudio/Macros+for+Shared+Library+Symbol+Visibility */ +#define INTERNAL __hidden +#define PCSC_API __global +#else +#define INTERNAL +#define PCSC_API +#endif +#define EXTERNAL PCSC_API + +#if defined __GNUC__ + +/* GNU Compiler Collection (GCC) */ +#define CONSTRUCTOR __attribute__ ((constructor)) +#define DESTRUCTOR __attribute__ ((destructor)) + +#else + +/* SUN C compiler does not use __attribute__ but #pragma init (function) + * We can't use a # inside a #define so it is not possible to use + * #define CONSTRUCTOR_DECLARATION(x) #pragma init (x) + * The #pragma is used directly where needed */ + +/* any other */ +#define CONSTRUCTOR +#define DESTRUCTOR + +#endif + +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +#ifndef COUNT_OF +#define COUNT_OF(arr) (sizeof(arr)/sizeof(arr[0])) +#endif + +#endif /* __misc_h__ */ diff --git a/de.persosim.driver.linux/persoSimConnect.c b/de.persosim.driver.unix/persoSimConnect.c similarity index 98% rename from de.persosim.driver.linux/persoSimConnect.c rename to de.persosim.driver.unix/persoSimConnect.c index a125b56..4fcc172 100644 --- a/de.persosim.driver.linux/persoSimConnect.c +++ b/de.persosim.driver.unix/persoSimConnect.c @@ -56,7 +56,7 @@ int transmit (int sockfd, const char* msgBuffer) { strcat(transmitBuffer, "\n"); Log2(PCSC_LOG_DEBUG, "Sending message to client: %s", transmitBuffer); - if (send(sockfd, transmitBuffer, bufferLength, MSG_NOSIGNAL) < 0) { + if (send(sockfd, transmitBuffer, bufferLength, 0) < 0) { Log1(PCSC_LOG_ERROR, "Failure during transmit to client"); return PSIM_COMMUNICATION_ERROR; } @@ -195,9 +195,10 @@ void * handleHandshakeConnections(void * param) { // enable connector as new reader curReader->clientSocket = clientSocket; +#if !defined(__APPLE__) //let pcsc rescan readers raise(SIGUSR1); - +#endif //XXX implement closing and disposal of client sockets (through handshake as well as on errors) } diff --git a/de.persosim.driver.linux/persoSimConnect.h b/de.persosim.driver.unix/persoSimConnect.h similarity index 100% rename from de.persosim.driver.linux/persoSimConnect.h rename to de.persosim.driver.unix/persoSimConnect.h diff --git a/de.persosim.driver.unix/reader.conf.in b/de.persosim.driver.unix/reader.conf.in new file mode 100644 index 0000000..e2a1527 --- /dev/null +++ b/de.persosim.driver.unix/reader.conf.in @@ -0,0 +1,4 @@ +FRIENDLYNAME "PersoSimHandshake" +DEVICENAME localhost:5678 +LIBPATH @LIBPATH@ +CHANNELID 0x8C7B