diff --git a/0211-qemu-socket-Make-socket_optslist-public.patch b/0211-qemu-socket-Make-socket_optslist-public.patch new file mode 100644 index 0000000..4fc8d97 --- /dev/null +++ b/0211-qemu-socket-Make-socket_optslist-public.patch @@ -0,0 +1,113 @@ +From 4190f44bbdde97adb467c9c0c625bdc2f89f4af7 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Fri, 15 Mar 2013 17:14:24 +0100 +Subject: [PATCH 211/241] qemu-socket: Make socket_optslist public + +Allow other users to create the QemuOpts needed for inet_connect_opts(). + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +(cherry picked from commit e62be8888a83aa0ab7f50eeb954deb2ec4e7201d) +--- + include/qemu/sockets.h | 2 ++ + util/qemu-sockets.c | 22 +++++++++++----------- + 2 files changed, 13 insertions(+), 11 deletions(-) + +diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h +index 42ca690..6eed34e 100644 +--- a/include/qemu/sockets.h ++++ b/include/qemu/sockets.h +@@ -31,6 +31,8 @@ int inet_aton(const char *cp, struct in_addr *ia); + #include "qapi/qmp/qerror.h" + #include "char/char.h" + ++extern QemuOptsList socket_optslist; ++ + /* misc helpers */ + int qemu_socket(int domain, int type, int protocol); + int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen); +diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c +index cd54fb4..b32510a 100644 +--- a/util/qemu-sockets.c ++++ b/util/qemu-sockets.c +@@ -33,10 +33,10 @@ + + static const int on=1, off=0; + +-/* used temporarely until all users are converted to QemuOpts */ +-static QemuOptsList dummy_opts = { +- .name = "dummy", +- .head = QTAILQ_HEAD_INITIALIZER(dummy_opts.head), ++/* used temporarily until all users are converted to QemuOpts */ ++QemuOptsList socket_optslist = { ++ .name = "socket", ++ .head = QTAILQ_HEAD_INITIALIZER(socket_optslist.head), + .desc = { + { + .name = "path", +@@ -579,7 +579,7 @@ int inet_listen(const char *str, char *ostr, int olen, + + addr = inet_parse(str, errp); + if (addr != NULL) { +- opts = qemu_opts_create_nofail(&dummy_opts); ++ opts = qemu_opts_create_nofail(&socket_optslist); + inet_addr_to_opts(opts, addr); + qapi_free_InetSocketAddress(addr); + sock = inet_listen_opts(opts, port_offset, errp); +@@ -652,7 +652,7 @@ int inet_nonblocking_connect(const char *str, + + addr = inet_parse(str, errp); + if (addr != NULL) { +- opts = qemu_opts_create_nofail(&dummy_opts); ++ opts = qemu_opts_create_nofail(&socket_optslist); + inet_addr_to_opts(opts, addr); + qapi_free_InetSocketAddress(addr); + sock = inet_connect_opts(opts, errp, callback, opaque); +@@ -795,7 +795,7 @@ int unix_listen(const char *str, char *ostr, int olen, Error **errp) + char *path, *optstr; + int sock, len; + +- opts = qemu_opts_create_nofail(&dummy_opts); ++ opts = qemu_opts_create_nofail(&socket_optslist); + + optstr = strchr(str, ','); + if (optstr) { +@@ -823,7 +823,7 @@ int unix_connect(const char *path, Error **errp) + QemuOpts *opts; + int sock; + +- opts = qemu_opts_create_nofail(&dummy_opts); ++ opts = qemu_opts_create_nofail(&socket_optslist); + qemu_opt_set(opts, "path", path); + sock = unix_connect_opts(opts, errp, NULL, NULL); + qemu_opts_del(opts); +@@ -840,7 +840,7 @@ int unix_nonblocking_connect(const char *path, + + g_assert(callback != NULL); + +- opts = qemu_opts_create_nofail(&dummy_opts); ++ opts = qemu_opts_create_nofail(&socket_optslist); + qemu_opt_set(opts, "path", path); + sock = unix_connect_opts(opts, errp, callback, opaque); + qemu_opts_del(opts); +@@ -891,7 +891,7 @@ int socket_connect(SocketAddress *addr, Error **errp, + QemuOpts *opts; + int fd; + +- opts = qemu_opts_create_nofail(&dummy_opts); ++ opts = qemu_opts_create_nofail(&socket_optslist); + switch (addr->kind) { + case SOCKET_ADDRESS_KIND_INET: + inet_addr_to_opts(opts, addr->inet); +@@ -923,7 +923,7 @@ int socket_listen(SocketAddress *addr, Error **errp) + QemuOpts *opts; + int fd; + +- opts = qemu_opts_create_nofail(&dummy_opts); ++ opts = qemu_opts_create_nofail(&socket_optslist); + switch (addr->kind) { + case SOCKET_ADDRESS_KIND_INET: + inet_addr_to_opts(opts, addr->inet); +-- +1.8.3.1 + diff --git a/0212-libcacard-correct-T0-historical-bytes-size.patch b/0212-libcacard-correct-T0-historical-bytes-size.patch new file mode 100644 index 0000000..f2d3507 --- /dev/null +++ b/0212-libcacard-correct-T0-historical-bytes-size.patch @@ -0,0 +1,38 @@ +From ec22a81dc76492a729695a54e32a837ab6384e65 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Sun, 2 Dec 2012 22:00:55 +0100 +Subject: [PATCH 212/241] libcacard: correct T0 historical bytes size +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The VCARD_ATR_PREFIX macro adds a prefix of 6 characters only. + +pcsc_scan was complaining before the patch: + ++ Historical bytes: 56 43 41 52 44 5F 4E 53 53 + ERROR! ATR is truncated: 2 byte(s) is/are missing + +Signed-off-by: Marc-André Lureau +Reviewed-by: Alon Levy +(cherry picked from commit e2fd2115ce26049335d66ae0ae5e5c0ad06fb498) +--- + libcacard/vcardt.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libcacard/vcardt.h b/libcacard/vcardt.h +index d3e9522..538bdde 100644 +--- a/libcacard/vcardt.h ++++ b/libcacard/vcardt.h +@@ -26,7 +26,7 @@ typedef struct VCardEmulStruct VCardEmul; + #define MAX_CHANNEL 4 + + /* create an ATR with appropriate historical bytes */ +-#define VCARD_ATR_PREFIX(size) 0x3b, 0x68+(size), 0x00, 0xff, \ ++#define VCARD_ATR_PREFIX(size) 0x3b, 0x66+(size), 0x00, 0xff, \ + 'V', 'C', 'A', 'R', 'D', '_' + + +-- +1.8.3.1 + diff --git a/0213-ccid-card-emul-do-not-crash-if-backend-is-not-provid.patch b/0213-ccid-card-emul-do-not-crash-if-backend-is-not-provid.patch new file mode 100644 index 0000000..0caa307 --- /dev/null +++ b/0213-ccid-card-emul-do-not-crash-if-backend-is-not-provid.patch @@ -0,0 +1,40 @@ +From 142383e938fddcf7ed4f81aa30a1e7c1a968cef8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Wed, 21 Nov 2012 14:16:08 +0100 +Subject: [PATCH 213/241] ccid-card-emul: do not crash if backend is not + provided +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Program received signal SIGSEGV, Segmentation fault. +__strcmp_sse42 () at ../sysdeps/x86_64/multiarch/strcmp-sse42.S:164 +164 movdqu (%rsi), %xmm2 +(gdb) bt + at /home/elmarco/320g/src/qemu/hw/ccid-card-emulated.c:477 + at /home/elmarco/320g/src/qemu/hw/ccid-card-emulated.c:503 + +Signed-off-by: Marc-André Lureau +Reviewed-by: Alon Levy +(cherry picked from commit d0ebd78890fba2ab458ec34763dae8566ccb1b72) +--- + hw/ccid-card-emulated.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/hw/ccid-card-emulated.c b/hw/ccid-card-emulated.c +index c8f8ba3..210433e 100644 +--- a/hw/ccid-card-emulated.c ++++ b/hw/ccid-card-emulated.c +@@ -473,6 +473,9 @@ static uint32_t parse_enumeration(char *str, + { + uint32_t ret = not_found_value; + ++ if (str == NULL) ++ return 0; ++ + while (table->name != NULL) { + if (strcmp(table->name, str) == 0) { + ret = table->value; +-- +1.8.3.1 + diff --git a/0214-ccid-make-backend_enum_table-static-const-and-adjust.patch b/0214-ccid-make-backend_enum_table-static-const-and-adjust.patch new file mode 100644 index 0000000..8ecc5a7 --- /dev/null +++ b/0214-ccid-make-backend_enum_table-static-const-and-adjust.patch @@ -0,0 +1,50 @@ +From e72e97097d1c619774cb07326496e38c0de46ef0 Mon Sep 17 00:00:00 2001 +From: Jim Meyering +Date: Mon, 21 May 2012 21:56:20 +0200 +Subject: [PATCH 214/241] ccid: make backend_enum_table "static const" and + adjust users +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Jim Meyering +Reviewed-by: Alon Levy +Reviewed-by: Marc-André Lureau +(cherry picked from commit d18c7117467aa5fae95a7c6eaffcf50618197e79) +--- + hw/ccid-card-emulated.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/hw/ccid-card-emulated.c b/hw/ccid-card-emulated.c +index 210433e..cb9ef10 100644 +--- a/hw/ccid-card-emulated.c ++++ b/hw/ccid-card-emulated.c +@@ -462,14 +462,14 @@ typedef struct EnumTable { + uint32_t value; + } EnumTable; + +-EnumTable backend_enum_table[] = { ++static const EnumTable backend_enum_table[] = { + {BACKEND_NSS_EMULATED_NAME, BACKEND_NSS_EMULATED}, + {BACKEND_CERTIFICATES_NAME, BACKEND_CERTIFICATES}, + {NULL, 0}, + }; + + static uint32_t parse_enumeration(char *str, +- EnumTable *table, uint32_t not_found_value) ++ const EnumTable *table, uint32_t not_found_value) + { + uint32_t ret = not_found_value; + +@@ -490,7 +490,7 @@ static int emulated_initfn(CCIDCardState *base) + { + EmulatedState *card = DO_UPCAST(EmulatedState, base, base); + VCardEmulError ret; +- EnumTable *ptable; ++ const EnumTable *ptable; + + QSIMPLEQ_INIT(&card->event_list); + QSIMPLEQ_INIT(&card->guest_apdu_list); +-- +1.8.3.1 + diff --git a/0215-ccid-declare-DEFAULT_ATR-table-to-be-static-const.patch b/0215-ccid-declare-DEFAULT_ATR-table-to-be-static-const.patch new file mode 100644 index 0000000..a93cafd --- /dev/null +++ b/0215-ccid-declare-DEFAULT_ATR-table-to-be-static-const.patch @@ -0,0 +1,32 @@ +From 0a8bbcf1c62e0cf12188eaad871b23633a336f73 Mon Sep 17 00:00:00 2001 +From: Jim Meyering +Date: Mon, 21 May 2012 21:51:33 +0200 +Subject: [PATCH 215/241] ccid: declare DEFAULT_ATR table to be "static const" +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Jim Meyering +Reviewed-by: Alon Levy +Reviewed-by: Marc-André Lureau +(cherry picked from commit da000a4867749434e03896a5072321771736352a) +--- + hw/ccid-card-passthru.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/ccid-card-passthru.c b/hw/ccid-card-passthru.c +index 0dde761..62070db 100644 +--- a/hw/ccid-card-passthru.c ++++ b/hw/ccid-card-passthru.c +@@ -27,7 +27,7 @@ do { \ + #define D_VERBOSE 4 + + /* TODO: do we still need this? */ +-uint8_t DEFAULT_ATR[] = { ++static const uint8_t DEFAULT_ATR[] = { + /* + * From some example somewhere + * 0x3B, 0xB0, 0x18, 0x00, 0xD1, 0x81, 0x05, 0xB1, 0x40, 0x38, 0x1F, 0x03, 0x28 +-- +1.8.3.1 + diff --git a/0216-libcacard-use-system-config-directory-for-nss-db-on-.patch b/0216-libcacard-use-system-config-directory-for-nss-db-on-.patch new file mode 100644 index 0000000..dc6ce62 --- /dev/null +++ b/0216-libcacard-use-system-config-directory-for-nss-db-on-.patch @@ -0,0 +1,51 @@ +From 2b60d2a60e98747e46e6addb89bf9a7f923ae499 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Wed, 27 Feb 2013 21:08:06 +0100 +Subject: [PATCH 216/241] libcacard: use system config directory for nss db on + win32 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +It's a bit nicer to look for default database under +CSIDL_COMMON_APPDATA\pki\nss rather that /etc/pki/nss. + +Signed-off-by: Marc-André Lureau +Reviewed-by: Alon Levy +(cherry picked from commit e2d9c5e769d59f2bca649b8286892d49bdcfc2b1) +--- + libcacard/vcard_emul_nss.c | 18 +++++++++++++++++- + 1 file changed, 17 insertions(+), 1 deletion(-) + +diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c +index df79476..21d4689 100644 +--- a/libcacard/vcard_emul_nss.c ++++ b/libcacard/vcard_emul_nss.c +@@ -893,7 +893,23 @@ vcard_emul_init(const VCardEmulOptions *options) + if (options->nss_db) { + rv = NSS_Init(options->nss_db); + } else { +- rv = NSS_Init("sql:/etc/pki/nssdb"); ++ gchar *path, *db; ++#ifndef _WIN32 ++ path = g_strdup("/etc/pki/nssdb"); ++#else ++ if (g_get_system_config_dirs() == NULL || ++ g_get_system_config_dirs()[0] == NULL) { ++ return VCARD_EMUL_FAIL; ++ } ++ ++ path = g_build_filename( ++ g_get_system_config_dirs()[0], "pki", "nssdb", NULL); ++#endif ++ db = g_strdup_printf("sql:%s", path); ++ ++ rv = NSS_Init(db); ++ g_free(db); ++ g_free(path); + } + if (rv != SECSuccess) { + return VCARD_EMUL_FAIL; +-- +1.8.3.1 + diff --git a/0217-util-move-socket_init-to-osdep.c.patch b/0217-util-move-socket_init-to-osdep.c.patch new file mode 100644 index 0000000..83de188 --- /dev/null +++ b/0217-util-move-socket_init-to-osdep.c.patch @@ -0,0 +1,97 @@ +From 2f2068568e87fc1f20bc891cce18b4e65965b091 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Mon, 25 Feb 2013 23:31:11 +0100 +Subject: [PATCH 217/241] util: move socket_init() to osdep.c +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +vscclient needs to call socket_init() for portability. +Moving to osdep.c since it has no internal dependency. + +Signed-off-by: Marc-André Lureau +Reviewed-by: Alon Levy +(cherry picked from commit d3bf825e59125bc6a0accec0dca119ea0155cb82) + +Conflicts: + util/qemu-sockets.c +--- + util/osdep.c | 23 +++++++++++++++++++++++ + util/qemu-sockets.c | 26 +------------------------- + 2 files changed, 24 insertions(+), 25 deletions(-) + +diff --git a/util/osdep.c b/util/osdep.c +index 5b51a03..3c1a0a3 100644 +--- a/util/osdep.c ++++ b/util/osdep.c +@@ -400,3 +400,26 @@ bool fips_get_state(void) + return fips_enabled; + } + ++#ifdef _WIN32 ++static void socket_cleanup(void) ++{ ++ WSACleanup(); ++} ++#endif ++ ++int socket_init(void) ++{ ++#ifdef _WIN32 ++ WSADATA Data; ++ int ret, err; ++ ++ ret = WSAStartup(MAKEWORD(2, 2), &Data); ++ if (ret != 0) { ++ err = WSAGetLastError(); ++ fprintf(stderr, "WSAStartup: %d\n", err); ++ return -1; ++ } ++ atexit(socket_cleanup); ++#endif ++ return 0; ++} +diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c +index b32510a..7909381 100644 +--- a/util/qemu-sockets.c ++++ b/util/qemu-sockets.c +@@ -618,7 +618,7 @@ int inet_connect(const char *str, Error **errp) + + addr = inet_parse(str, errp); + if (addr != NULL) { +- opts = qemu_opts_create_nofail(&dummy_opts); ++ opts = qemu_opts_create_nofail(&socket_optslist); + inet_addr_to_opts(opts, addr); + qapi_free_InetSocketAddress(addr); + sock = inet_connect_opts(opts, errp, NULL, NULL); +@@ -945,27 +945,3 @@ int socket_listen(SocketAddress *addr, Error **errp) + qemu_opts_del(opts); + return fd; + } +- +-#ifdef _WIN32 +-static void socket_cleanup(void) +-{ +- WSACleanup(); +-} +-#endif +- +-int socket_init(void) +-{ +-#ifdef _WIN32 +- WSADATA Data; +- int ret, err; +- +- ret = WSAStartup(MAKEWORD(2,2), &Data); +- if (ret != 0) { +- err = WSAGetLastError(); +- fprintf(stderr, "WSAStartup: %d\n", err); +- return -1; +- } +- atexit(socket_cleanup); +-#endif +- return 0; +-} +-- +1.8.3.1 + diff --git a/0218-build-sys-must-link-with-fstack-protector.patch b/0218-build-sys-must-link-with-fstack-protector.patch new file mode 100644 index 0000000..95a1dfe --- /dev/null +++ b/0218-build-sys-must-link-with-fstack-protector.patch @@ -0,0 +1,73 @@ +From 989623664fb428748a5efedbab162d75e1eb0432 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Mon, 25 Feb 2013 23:31:12 +0100 +Subject: [PATCH 218/241] build-sys: must link with -fstack-protector +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +It is needed to give that flag to the linker as well, but latest +libtool 2.4.2 still swallows that argument, so let's pass it with +libtool -Wc argument. + +qemu-1.4.0/stubs/arch-query-cpu-def.c:6: undefined reference to `__stack_chk_guard' + +Signed-off-by: Marc-André Lureau +Reviewed-by: Alon Levy +(cherry picked from commit 37746c5eacf309fa019ea0fa45f776c36c561457) + +Conflicts: + configure +--- + configure | 8 +++++++- + rules.mak | 1 + + 2 files changed, 8 insertions(+), 1 deletion(-) + +diff --git a/configure b/configure +index 2996e1d..e8633c5 100755 +--- a/configure ++++ b/configure +@@ -1197,7 +1197,7 @@ fi + gcc_flags="-Wold-style-declaration -Wold-style-definition -Wtype-limits" + gcc_flags="-Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers $gcc_flags" + gcc_flags="-Wmissing-include-dirs -Wempty-body -Wnested-externs $gcc_flags" +-gcc_flags="-fstack-protector-all -Wendif-labels $gcc_flags" ++gcc_flags="-Wendif-labels $gcc_flags" + gcc_flags="-Wno-initializer-overrides $gcc_flags" + # Note that we do not add -Werror to gcc_flags here, because that would + # enable it for all configure tests. If a configure test failed due +@@ -1216,6 +1216,11 @@ for flag in $gcc_flags; do + fi + done + ++if compile_prog "-Werror -fstack-protector-all" "" ; then ++ QEMU_CFLAGS="$QEMU_CFLAGS -fstack-protector-all" ++ LIBTOOLFLAGS="$LIBTOOLFLAGS -Wc,-fstack-protector-all" ++fi ++ + # Workaround for http://gcc.gnu.org/PR55489. Happens with -fPIE/-fPIC and + # large functions that use global variables. The bug is in all releases of + # GCC, but it became particularly acute in 4.6.x and 4.7.x. It is fixed in +@@ -3832,6 +3837,7 @@ fi + echo "LDFLAGS=$LDFLAGS" >> $config_host_mak + echo "ARLIBS_BEGIN=$arlibs_begin" >> $config_host_mak + echo "ARLIBS_END=$arlibs_end" >> $config_host_mak ++echo "LIBTOOLFLAGS=$LIBTOOLFLAGS" >> $config_host_mak + echo "LIBS+=$LIBS" >> $config_host_mak + echo "LIBS_TOOLS+=$libs_tools" >> $config_host_mak + echo "EXESUF=$EXESUF" >> $config_host_mak +diff --git a/rules.mak b/rules.mak +index edc2552..36aba2d 100644 +--- a/rules.mak ++++ b/rules.mak +@@ -36,6 +36,7 @@ LINK = $(call quiet-command,\ + $(if $(filter %.lo %.la,$^),$(LIBTOOL) --mode=link --tag=CC \ + )$(CC) $(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ \ + $(sort $(filter %.o, $1)) $(filter-out %.o, $1) $(version-obj-y) \ ++ $(if $(filter %.lo %.la,$^),$(LIBTOOLFLAGS)) \ + $(LIBS),$(if $(filter %.lo %.la,$^),"lt LINK ", " LINK ")"$(TARGET_DIR)$@") + endif + +-- +1.8.3.1 + diff --git a/0219-libcacard-fix-mingw64-cross-compilation.patch b/0219-libcacard-fix-mingw64-cross-compilation.patch new file mode 100644 index 0000000..106a709 --- /dev/null +++ b/0219-libcacard-fix-mingw64-cross-compilation.patch @@ -0,0 +1,57 @@ +From cc5a2202bc5484aba302a684fb75106da506b1f0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Mon, 25 Feb 2013 23:31:13 +0100 +Subject: [PATCH 219/241] libcacard: fix mingw64 cross-compilation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Compile and link with version.lo + +Signed-off-by: Marc-André Lureau +Reviewed-by: Alon Levy +(cherry picked from commit 5354e4d242175e067bb70732f694ae9322a81351) +--- + Makefile | 8 ++++++-- + rules.mak | 3 ++- + 2 files changed, 8 insertions(+), 3 deletions(-) + +diff --git a/Makefile b/Makefile +index 0d9099a..751cf1d 100644 +--- a/Makefile ++++ b/Makefile +@@ -148,11 +148,15 @@ recurse-all: $(SUBDIR_RULES) $(ROMSUBDIR_RULES) + + bt-host.o: QEMU_CFLAGS += $(BLUEZ_CFLAGS) + +-version.o: $(SRC_PATH)/version.rc config-host.h ++version.o: $(SRC_PATH)/version.rc config-host.h | version.lo + $(call quiet-command,$(WINDRES) -I. -o $@ $<," RC $(TARGET_DIR)$@") ++version.lo: $(SRC_PATH)/version.rc config-host.h ++ $(call quiet-command,$(LIBTOOL) --mode=compile --tag=RC $(WINDRES) -I. -o $@ $<,"lt RC $(TARGET_DIR)$@") + + version-obj-$(CONFIG_WIN32) += version.o +-Makefile: $(version-obj-y) ++version-lobj-$(CONFIG_WIN32) += $(if $(LIBTOOL),version.lo) ++Makefile: $(version-obj-y) $(version-lobj-y) ++ + + ###################################################################### + # Build libraries +diff --git a/rules.mak b/rules.mak +index 36aba2d..292a422 100644 +--- a/rules.mak ++++ b/rules.mak +@@ -35,7 +35,8 @@ LIBTOOL += $(if $(V),,--quiet) + LINK = $(call quiet-command,\ + $(if $(filter %.lo %.la,$^),$(LIBTOOL) --mode=link --tag=CC \ + )$(CC) $(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ \ +- $(sort $(filter %.o, $1)) $(filter-out %.o, $1) $(version-obj-y) \ ++ $(sort $(filter %.o, $1)) $(filter-out %.o, $1) \ ++ $(if $(filter %.lo %.la,$^),$(version-lobj-y),$(version-obj-y)) \ + $(if $(filter %.lo %.la,$^),$(LIBTOOLFLAGS)) \ + $(LIBS),$(if $(filter %.lo %.la,$^),"lt LINK ", " LINK ")"$(TARGET_DIR)$@") + endif +-- +1.8.3.1 + diff --git a/0220-libcacard-split-vscclient-main-from-socket-reading.patch b/0220-libcacard-split-vscclient-main-from-socket-reading.patch new file mode 100644 index 0000000..37fe0e7 --- /dev/null +++ b/0220-libcacard-split-vscclient-main-from-socket-reading.patch @@ -0,0 +1,377 @@ +From 2898705c820b4b0c6bbd196bccce55dd3d64f62c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Mon, 25 Feb 2013 23:31:14 +0100 +Subject: [PATCH 220/241] libcacard: split vscclient main() from socket reading +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Marc-André Lureau +Reviewed-by: Alon Levy +(cherry picked from commit a50b831ae1fe039b7c22793f307e0b8afdf50589) +--- + libcacard/vscclient.c | 314 ++++++++++++++++++++++++++------------------------ + 1 file changed, 162 insertions(+), 152 deletions(-) + +diff --git a/libcacard/vscclient.c b/libcacard/vscclient.c +index 9b744f2..5e00db3 100644 +--- a/libcacard/vscclient.c ++++ b/libcacard/vscclient.c +@@ -211,6 +211,166 @@ get_id_from_string(char *string, unsigned int default_id) + return id; + } + ++static int ++on_host_init(VSCMsgHeader *mhHeader, VSCMsgInit *incoming) ++{ ++ uint32_t *capabilities = (incoming->capabilities); ++ int num_capabilities = ++ 1 + ((mhHeader->length - sizeof(VSCMsgInit)) / sizeof(uint32_t)); ++ int i; ++ int rv; ++ pthread_t thread_id; ++ ++ incoming->version = ntohl(incoming->version); ++ if (incoming->version != VSCARD_VERSION) { ++ if (verbose > 0) { ++ printf("warning: host has version %d, we have %d\n", ++ verbose, VSCARD_VERSION); ++ } ++ } ++ if (incoming->magic != VSCARD_MAGIC) { ++ printf("unexpected magic: got %d, expected %d\n", ++ incoming->magic, VSCARD_MAGIC); ++ return -1; ++ } ++ for (i = 0 ; i < num_capabilities; ++i) { ++ capabilities[i] = ntohl(capabilities[i]); ++ } ++ /* Future: check capabilities */ ++ /* remove whatever reader might be left in qemu, ++ * in case of an unclean previous exit. */ ++ send_msg(VSC_ReaderRemove, VSCARD_MINIMAL_READER_ID, NULL, 0); ++ /* launch the event_thread. This will trigger reader adds for all the ++ * existing readers */ ++ rv = pthread_create(&thread_id, NULL, event_thread, NULL); ++ if (rv < 0) { ++ perror("pthread_create"); ++ return rv; ++ } ++ return 0; ++} ++ ++#define APDUBufSize 270 ++ ++static int ++do_socket_read(void) ++{ ++ int rv; ++ int dwSendLength; ++ int dwRecvLength; ++ uint8_t pbRecvBuffer[APDUBufSize]; ++ uint8_t pbSendBuffer[APDUBufSize]; ++ VReaderStatus reader_status; ++ VReader *reader = NULL; ++ VSCMsgHeader mhHeader; ++ VSCMsgError *error_msg; ++ ++ rv = read(sock, &mhHeader, sizeof(mhHeader)); ++ if (rv < sizeof(mhHeader)) { ++ /* Error */ ++ if (rv < 0) { ++ perror("header read error\n"); ++ } else { ++ fprintf(stderr, "header short read %d\n", rv); ++ } ++ return -1; ++ } ++ mhHeader.type = ntohl(mhHeader.type); ++ mhHeader.reader_id = ntohl(mhHeader.reader_id); ++ mhHeader.length = ntohl(mhHeader.length); ++ if (verbose) { ++ printf("Header: type=%d, reader_id=%u length=%d (0x%x)\n", ++ mhHeader.type, mhHeader.reader_id, mhHeader.length, ++ mhHeader.length); ++ } ++ switch (mhHeader.type) { ++ case VSC_APDU: ++ case VSC_Flush: ++ case VSC_Error: ++ case VSC_Init: ++ rv = read(sock, pbSendBuffer, mhHeader.length); ++ break; ++ default: ++ fprintf(stderr, "Unexpected message of type 0x%X\n", mhHeader.type); ++ return -1; ++ } ++ switch (mhHeader.type) { ++ case VSC_APDU: ++ if (rv < 0) { ++ /* Error */ ++ fprintf(stderr, "read error\n"); ++ close(sock); ++ return -1; ++ } ++ if (verbose) { ++ printf(" recv APDU: "); ++ print_byte_array(pbSendBuffer, mhHeader.length); ++ } ++ /* Transmit received APDU */ ++ dwSendLength = mhHeader.length; ++ dwRecvLength = sizeof(pbRecvBuffer); ++ reader = vreader_get_reader_by_id(mhHeader.reader_id); ++ reader_status = vreader_xfr_bytes(reader, ++ pbSendBuffer, dwSendLength, ++ pbRecvBuffer, &dwRecvLength); ++ if (reader_status == VREADER_OK) { ++ mhHeader.length = dwRecvLength; ++ if (verbose) { ++ printf(" send response: "); ++ print_byte_array(pbRecvBuffer, mhHeader.length); ++ } ++ send_msg(VSC_APDU, mhHeader.reader_id, ++ pbRecvBuffer, dwRecvLength); ++ } else { ++ rv = reader_status; /* warning: not meaningful */ ++ send_msg(VSC_Error, mhHeader.reader_id, &rv, sizeof(uint32_t)); ++ } ++ vreader_free(reader); ++ reader = NULL; /* we've freed it, don't use it by accident ++ again */ ++ break; ++ case VSC_Flush: ++ /* TODO: actually flush */ ++ send_msg(VSC_FlushComplete, mhHeader.reader_id, NULL, 0); ++ break; ++ case VSC_Error: ++ error_msg = (VSCMsgError *) pbSendBuffer; ++ if (error_msg->code == VSC_SUCCESS) { ++ qemu_mutex_lock(&pending_reader_lock); ++ if (pending_reader) { ++ vreader_set_id(pending_reader, mhHeader.reader_id); ++ vreader_free(pending_reader); ++ pending_reader = NULL; ++ qemu_cond_signal(&pending_reader_condition); ++ } ++ qemu_mutex_unlock(&pending_reader_lock); ++ break; ++ } ++ printf("warning: qemu refused to add reader\n"); ++ if (error_msg->code == VSC_CANNOT_ADD_MORE_READERS) { ++ /* clear pending reader, qemu can't handle any more */ ++ qemu_mutex_lock(&pending_reader_lock); ++ if (pending_reader) { ++ pending_reader = NULL; ++ /* make sure the event loop doesn't hang */ ++ qemu_cond_signal(&pending_reader_condition); ++ } ++ qemu_mutex_unlock(&pending_reader_lock); ++ } ++ break; ++ case VSC_Init: ++ if (on_host_init(&mhHeader, (VSCMsgInit *)pbSendBuffer) < 0) { ++ return -1; ++ } ++ break; ++ default: ++ printf("Default\n"); ++ return -1; ++ } ++ ++ return 0; ++} ++ + static void + do_command(void) + { +@@ -339,8 +499,6 @@ do_command(void) + } + + +-#define APDUBufSize 270 +- + /* just for ease of parsing command line arguments. */ + #define MAX_CERTS 100 + +@@ -385,44 +543,6 @@ connect_to_qemu( + return sock; + } + +-static int on_host_init(VSCMsgHeader *mhHeader, VSCMsgInit *incoming) +-{ +- uint32_t *capabilities = (incoming->capabilities); +- int num_capabilities = +- 1 + ((mhHeader->length - sizeof(VSCMsgInit)) / sizeof(uint32_t)); +- int i; +- int rv; +- pthread_t thread_id; +- +- incoming->version = ntohl(incoming->version); +- if (incoming->version != VSCARD_VERSION) { +- if (verbose > 0) { +- printf("warning: host has version %d, we have %d\n", +- verbose, VSCARD_VERSION); +- } +- } +- if (incoming->magic != VSCARD_MAGIC) { +- printf("unexpected magic: got %d, expected %d\n", +- incoming->magic, VSCARD_MAGIC); +- return -1; +- } +- for (i = 0 ; i < num_capabilities; ++i) { +- capabilities[i] = ntohl(capabilities[i]); +- } +- /* Future: check capabilities */ +- /* remove whatever reader might be left in qemu, +- * in case of an unclean previous exit. */ +- send_msg(VSC_ReaderRemove, VSCARD_MINIMAL_READER_ID, NULL, 0); +- /* launch the event_thread. This will trigger reader adds for all the +- * existing readers */ +- rv = pthread_create(&thread_id, NULL, event_thread, NULL); +- if (rv < 0) { +- perror("pthread_create"); +- return rv; +- } +- return 0; +-} +- + int + main( + int argc, +@@ -431,21 +551,13 @@ main( + char *qemu_host; + char *qemu_port; + VSCMsgHeader mhHeader; +- VSCMsgError *error_msg; + +- int rv; +- int dwSendLength; +- int dwRecvLength; +- uint8_t pbRecvBuffer[APDUBufSize]; +- uint8_t pbSendBuffer[APDUBufSize]; +- VReaderStatus reader_status; +- VReader *reader = NULL; + VCardEmulOptions *command_line_options = NULL; + + char *cert_names[MAX_CERTS]; + char *emul_args = NULL; + int cert_count = 0; +- int c; ++ int c, rv; + + while ((c = getopt(argc, argv, "c:e:pd:")) != -1) { + switch (c) { +@@ -548,109 +660,7 @@ main( + if (!FD_ISSET(sock, &fds)) { + continue; + } +- +- rv = read(sock, &mhHeader, sizeof(mhHeader)); +- if (rv < sizeof(mhHeader)) { +- /* Error */ +- if (rv < 0) { +- perror("header read error\n"); +- } else { +- fprintf(stderr, "header short read %d\n", rv); +- } +- return 8; +- } +- mhHeader.type = ntohl(mhHeader.type); +- mhHeader.reader_id = ntohl(mhHeader.reader_id); +- mhHeader.length = ntohl(mhHeader.length); +- if (verbose) { +- printf("Header: type=%d, reader_id=%u length=%d (0x%x)\n", +- mhHeader.type, mhHeader.reader_id, mhHeader.length, +- mhHeader.length); +- } +- switch (mhHeader.type) { +- case VSC_APDU: +- case VSC_Flush: +- case VSC_Error: +- case VSC_Init: +- rv = read(sock, pbSendBuffer, mhHeader.length); +- break; +- default: +- fprintf(stderr, "Unexpected message of type 0x%X\n", mhHeader.type); +- return 0; +- } +- switch (mhHeader.type) { +- case VSC_APDU: +- if (rv < 0) { +- /* Error */ +- fprintf(stderr, "read error\n"); +- close(sock); +- return 8; +- } +- if (verbose) { +- printf(" recv APDU: "); +- print_byte_array(pbSendBuffer, mhHeader.length); +- } +- /* Transmit received APDU */ +- dwSendLength = mhHeader.length; +- dwRecvLength = sizeof(pbRecvBuffer); +- reader = vreader_get_reader_by_id(mhHeader.reader_id); +- reader_status = vreader_xfr_bytes(reader, +- pbSendBuffer, dwSendLength, +- pbRecvBuffer, &dwRecvLength); +- if (reader_status == VREADER_OK) { +- mhHeader.length = dwRecvLength; +- if (verbose) { +- printf(" send response: "); +- print_byte_array(pbRecvBuffer, mhHeader.length); +- } +- send_msg(VSC_APDU, mhHeader.reader_id, +- pbRecvBuffer, dwRecvLength); +- } else { +- rv = reader_status; /* warning: not meaningful */ +- send_msg(VSC_Error, mhHeader.reader_id, &rv, sizeof(uint32_t)); +- } +- vreader_free(reader); +- reader = NULL; /* we've freed it, don't use it by accident +- again */ +- break; +- case VSC_Flush: +- /* TODO: actually flush */ +- send_msg(VSC_FlushComplete, mhHeader.reader_id, NULL, 0); +- break; +- case VSC_Error: +- error_msg = (VSCMsgError *) pbSendBuffer; +- if (error_msg->code == VSC_SUCCESS) { +- qemu_mutex_lock(&pending_reader_lock); +- if (pending_reader) { +- vreader_set_id(pending_reader, mhHeader.reader_id); +- vreader_free(pending_reader); +- pending_reader = NULL; +- qemu_cond_signal(&pending_reader_condition); +- } +- qemu_mutex_unlock(&pending_reader_lock); +- break; +- } +- printf("warning: qemu refused to add reader\n"); +- if (error_msg->code == VSC_CANNOT_ADD_MORE_READERS) { +- /* clear pending reader, qemu can't handle any more */ +- qemu_mutex_lock(&pending_reader_lock); +- if (pending_reader) { +- pending_reader = NULL; +- /* make sure the event loop doesn't hang */ +- qemu_cond_signal(&pending_reader_condition); +- } +- qemu_mutex_unlock(&pending_reader_lock); +- } +- break; +- case VSC_Init: +- if (on_host_init(&mhHeader, (VSCMsgInit *)pbSendBuffer) < 0) { +- return -1; +- } +- break; +- default: +- printf("Default\n"); +- return 0; +- } ++ rv = do_socket_read(); + } while (rv >= 0); + + return 0; +-- +1.8.3.1 + diff --git a/0221-libcacard-vscclient-to-use-QemuThread-for-portabilit.patch b/0221-libcacard-vscclient-to-use-QemuThread-for-portabilit.patch new file mode 100644 index 0000000..6d75edf --- /dev/null +++ b/0221-libcacard-vscclient-to-use-QemuThread-for-portabilit.patch @@ -0,0 +1,46 @@ +From dc54f4b260b2fe57af5ad57326f0a67a82f977d3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Mon, 25 Feb 2013 23:31:15 +0100 +Subject: [PATCH 221/241] libcacard: vscclient to use QemuThread for + portability +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Marc-André Lureau +Reviewed-by: Alon Levy +(cherry picked from commit 930c8ad472ec00d40cfbf1e9b1395946bf0dd392) +--- + libcacard/vscclient.c | 9 ++------- + 1 file changed, 2 insertions(+), 7 deletions(-) + +diff --git a/libcacard/vscclient.c b/libcacard/vscclient.c +index 5e00db3..5f47634 100644 +--- a/libcacard/vscclient.c ++++ b/libcacard/vscclient.c +@@ -218,8 +218,7 @@ on_host_init(VSCMsgHeader *mhHeader, VSCMsgInit *incoming) + int num_capabilities = + 1 + ((mhHeader->length - sizeof(VSCMsgInit)) / sizeof(uint32_t)); + int i; +- int rv; +- pthread_t thread_id; ++ QemuThread thread_id; + + incoming->version = ntohl(incoming->version); + if (incoming->version != VSCARD_VERSION) { +@@ -242,11 +241,7 @@ on_host_init(VSCMsgHeader *mhHeader, VSCMsgInit *incoming) + send_msg(VSC_ReaderRemove, VSCARD_MINIMAL_READER_ID, NULL, 0); + /* launch the event_thread. This will trigger reader adds for all the + * existing readers */ +- rv = pthread_create(&thread_id, NULL, event_thread, NULL); +- if (rv < 0) { +- perror("pthread_create"); +- return rv; +- } ++ qemu_thread_create(&thread_id, event_thread, NULL, 0); + return 0; + } + +-- +1.8.3.1 + diff --git a/0222-libcacard-teach-vscclient-to-use-GMainLoop-for-porta.patch b/0222-libcacard-teach-vscclient-to-use-GMainLoop-for-porta.patch new file mode 100644 index 0000000..4b9d39f --- /dev/null +++ b/0222-libcacard-teach-vscclient-to-use-GMainLoop-for-porta.patch @@ -0,0 +1,548 @@ +From d5830145bc9af4b8df2eddd5a6ece27c4010b3d6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Mon, 25 Feb 2013 23:31:16 +0100 +Subject: [PATCH 222/241] libcacard: teach vscclient to use GMainLoop for + portability +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This version handles non-blocking sending and receiving from the +socket. + +Signed-off-by: Marc-André Lureau +Reviewed-by: Alon Levy +(cherry picked from commit c9495ee9eb57786f5a60d4591bb186b23f6b6bef) +--- + libcacard/vscclient.c | 391 +++++++++++++++++++++++++++++++------------------- + 1 file changed, 246 insertions(+), 145 deletions(-) + +diff --git a/libcacard/vscclient.c b/libcacard/vscclient.c +index 5f47634..ac23647 100644 +--- a/libcacard/vscclient.c ++++ b/libcacard/vscclient.c +@@ -10,7 +10,10 @@ + * See the COPYING.LIB file in the top-level directory. + */ + ++#ifndef _WIN32 + #include ++#endif ++#include + + #include "qemu-common.h" + #include "qemu/thread.h" +@@ -22,9 +25,7 @@ + #include "vcard_emul.h" + #include "vevent.h" + +-int verbose; +- +-int sock; ++static int verbose; + + static void + print_byte_array( +@@ -51,7 +52,47 @@ print_usage(void) { + vcard_emul_usage(); + } + +-static QemuMutex write_lock; ++static GIOChannel *channel_socket; ++static GByteArray *socket_to_send; ++static QemuMutex socket_to_send_lock; ++static guint socket_tag; ++ ++static void ++update_socket_watch(gboolean out); ++ ++static gboolean ++do_socket_send(GIOChannel *source, ++ GIOCondition condition, ++ gpointer data) ++{ ++ gsize bw; ++ GError *err = NULL; ++ ++ g_return_val_if_fail(socket_to_send->len != 0, FALSE); ++ g_return_val_if_fail(condition & G_IO_OUT, FALSE); ++ ++ g_io_channel_write_chars(channel_socket, ++ (gchar *)socket_to_send->data, socket_to_send->len, &bw, &err); ++ if (err != NULL) { ++ g_error("Error while sending socket %s", err->message); ++ return FALSE; ++ } ++ g_byte_array_remove_range(socket_to_send, 0, bw); ++ ++ if (socket_to_send->len == 0) { ++ update_socket_watch(FALSE); ++ return FALSE; ++ } ++ return TRUE; ++} ++ ++static gboolean ++socket_prepare_sending(gpointer user_data) ++{ ++ update_socket_watch(TRUE); ++ ++ return FALSE; ++} + + static int + send_msg( +@@ -60,10 +101,9 @@ send_msg( + const void *msg, + unsigned int length + ) { +- int rv; + VSCMsgHeader mhHeader; + +- qemu_mutex_lock(&write_lock); ++ qemu_mutex_lock(&socket_to_send_lock); + + if (verbose > 10) { + printf("sending type=%d id=%u, len =%u (0x%x)\n", +@@ -73,23 +113,11 @@ send_msg( + mhHeader.type = htonl(type); + mhHeader.reader_id = 0; + mhHeader.length = htonl(length); +- rv = write(sock, &mhHeader, sizeof(mhHeader)); +- if (rv < 0) { +- /* Error */ +- fprintf(stderr, "write header error\n"); +- close(sock); +- qemu_mutex_unlock(&write_lock); +- return 16; +- } +- rv = write(sock, msg, length); +- if (rv < 0) { +- /* Error */ +- fprintf(stderr, "write error\n"); +- close(sock); +- qemu_mutex_unlock(&write_lock); +- return 16; +- } +- qemu_mutex_unlock(&write_lock); ++ g_byte_array_append(socket_to_send, (guint8 *)&mhHeader, sizeof(mhHeader)); ++ g_byte_array_append(socket_to_send, (guint8 *)msg, length); ++ g_idle_add(socket_prepare_sending, NULL); ++ ++ qemu_mutex_unlock(&socket_to_send_lock); + + return 0; + } +@@ -245,139 +273,203 @@ on_host_init(VSCMsgHeader *mhHeader, VSCMsgInit *incoming) + return 0; + } + ++ ++enum { ++ STATE_HEADER, ++ STATE_MESSAGE, ++}; ++ + #define APDUBufSize 270 + +-static int +-do_socket_read(void) ++static gboolean ++do_socket_read(GIOChannel *source, ++ GIOCondition condition, ++ gpointer data) + { + int rv; + int dwSendLength; + int dwRecvLength; + uint8_t pbRecvBuffer[APDUBufSize]; +- uint8_t pbSendBuffer[APDUBufSize]; ++ static uint8_t pbSendBuffer[APDUBufSize]; + VReaderStatus reader_status; + VReader *reader = NULL; +- VSCMsgHeader mhHeader; ++ static VSCMsgHeader mhHeader; + VSCMsgError *error_msg; ++ GError *err = NULL; + +- rv = read(sock, &mhHeader, sizeof(mhHeader)); +- if (rv < sizeof(mhHeader)) { +- /* Error */ +- if (rv < 0) { +- perror("header read error\n"); +- } else { +- fprintf(stderr, "header short read %d\n", rv); +- } +- return -1; +- } +- mhHeader.type = ntohl(mhHeader.type); +- mhHeader.reader_id = ntohl(mhHeader.reader_id); +- mhHeader.length = ntohl(mhHeader.length); +- if (verbose) { +- printf("Header: type=%d, reader_id=%u length=%d (0x%x)\n", +- mhHeader.type, mhHeader.reader_id, mhHeader.length, +- mhHeader.length); +- } +- switch (mhHeader.type) { +- case VSC_APDU: +- case VSC_Flush: +- case VSC_Error: +- case VSC_Init: +- rv = read(sock, pbSendBuffer, mhHeader.length); +- break; +- default: +- fprintf(stderr, "Unexpected message of type 0x%X\n", mhHeader.type); +- return -1; ++ static gchar *buf; ++ static gsize br, to_read; ++ static int state = STATE_HEADER; ++ ++ if (state == STATE_HEADER && to_read == 0) { ++ buf = (gchar *)&mhHeader; ++ to_read = sizeof(mhHeader); + } +- switch (mhHeader.type) { +- case VSC_APDU: +- if (rv < 0) { +- /* Error */ +- fprintf(stderr, "read error\n"); +- close(sock); +- return -1; ++ ++ if (to_read > 0) { ++ g_io_channel_read_chars(source, (gchar *)buf, to_read, &br, &err); ++ if (err != NULL) { ++ g_error("error while reading: %s", err->message); + } ++ buf += br; ++ to_read -= br; ++ if (to_read != 0) { ++ return TRUE; ++ } ++ } ++ ++ if (state == STATE_HEADER) { ++ mhHeader.type = ntohl(mhHeader.type); ++ mhHeader.reader_id = ntohl(mhHeader.reader_id); ++ mhHeader.length = ntohl(mhHeader.length); + if (verbose) { +- printf(" recv APDU: "); +- print_byte_array(pbSendBuffer, mhHeader.length); ++ printf("Header: type=%d, reader_id=%u length=%d (0x%x)\n", ++ mhHeader.type, mhHeader.reader_id, mhHeader.length, ++ mhHeader.length); + } +- /* Transmit received APDU */ +- dwSendLength = mhHeader.length; +- dwRecvLength = sizeof(pbRecvBuffer); +- reader = vreader_get_reader_by_id(mhHeader.reader_id); +- reader_status = vreader_xfr_bytes(reader, +- pbSendBuffer, dwSendLength, +- pbRecvBuffer, &dwRecvLength); +- if (reader_status == VREADER_OK) { +- mhHeader.length = dwRecvLength; ++ switch (mhHeader.type) { ++ case VSC_APDU: ++ case VSC_Flush: ++ case VSC_Error: ++ case VSC_Init: ++ buf = (gchar *)pbSendBuffer; ++ to_read = mhHeader.length; ++ state = STATE_MESSAGE; ++ return TRUE; ++ default: ++ fprintf(stderr, "Unexpected message of type 0x%X\n", mhHeader.type); ++ return FALSE; ++ } ++ } ++ ++ if (state == STATE_MESSAGE) { ++ switch (mhHeader.type) { ++ case VSC_APDU: + if (verbose) { +- printf(" send response: "); +- print_byte_array(pbRecvBuffer, mhHeader.length); ++ printf(" recv APDU: "); ++ print_byte_array(pbSendBuffer, mhHeader.length); + } +- send_msg(VSC_APDU, mhHeader.reader_id, +- pbRecvBuffer, dwRecvLength); +- } else { +- rv = reader_status; /* warning: not meaningful */ +- send_msg(VSC_Error, mhHeader.reader_id, &rv, sizeof(uint32_t)); +- } +- vreader_free(reader); +- reader = NULL; /* we've freed it, don't use it by accident +- again */ +- break; +- case VSC_Flush: +- /* TODO: actually flush */ +- send_msg(VSC_FlushComplete, mhHeader.reader_id, NULL, 0); +- break; +- case VSC_Error: +- error_msg = (VSCMsgError *) pbSendBuffer; +- if (error_msg->code == VSC_SUCCESS) { +- qemu_mutex_lock(&pending_reader_lock); +- if (pending_reader) { +- vreader_set_id(pending_reader, mhHeader.reader_id); +- vreader_free(pending_reader); +- pending_reader = NULL; +- qemu_cond_signal(&pending_reader_condition); ++ /* Transmit received APDU */ ++ dwSendLength = mhHeader.length; ++ dwRecvLength = sizeof(pbRecvBuffer); ++ reader = vreader_get_reader_by_id(mhHeader.reader_id); ++ reader_status = vreader_xfr_bytes(reader, ++ pbSendBuffer, dwSendLength, ++ pbRecvBuffer, &dwRecvLength); ++ if (reader_status == VREADER_OK) { ++ mhHeader.length = dwRecvLength; ++ if (verbose) { ++ printf(" send response: "); ++ print_byte_array(pbRecvBuffer, mhHeader.length); ++ } ++ send_msg(VSC_APDU, mhHeader.reader_id, ++ pbRecvBuffer, dwRecvLength); ++ } else { ++ rv = reader_status; /* warning: not meaningful */ ++ send_msg(VSC_Error, mhHeader.reader_id, &rv, sizeof(uint32_t)); + } +- qemu_mutex_unlock(&pending_reader_lock); ++ vreader_free(reader); ++ reader = NULL; /* we've freed it, don't use it by accident ++ again */ + break; +- } +- printf("warning: qemu refused to add reader\n"); +- if (error_msg->code == VSC_CANNOT_ADD_MORE_READERS) { +- /* clear pending reader, qemu can't handle any more */ +- qemu_mutex_lock(&pending_reader_lock); +- if (pending_reader) { +- pending_reader = NULL; +- /* make sure the event loop doesn't hang */ +- qemu_cond_signal(&pending_reader_condition); ++ case VSC_Flush: ++ /* TODO: actually flush */ ++ send_msg(VSC_FlushComplete, mhHeader.reader_id, NULL, 0); ++ break; ++ case VSC_Error: ++ error_msg = (VSCMsgError *) pbSendBuffer; ++ if (error_msg->code == VSC_SUCCESS) { ++ qemu_mutex_lock(&pending_reader_lock); ++ if (pending_reader) { ++ vreader_set_id(pending_reader, mhHeader.reader_id); ++ vreader_free(pending_reader); ++ pending_reader = NULL; ++ qemu_cond_signal(&pending_reader_condition); ++ } ++ qemu_mutex_unlock(&pending_reader_lock); ++ break; + } +- qemu_mutex_unlock(&pending_reader_lock); ++ printf("warning: qemu refused to add reader\n"); ++ if (error_msg->code == VSC_CANNOT_ADD_MORE_READERS) { ++ /* clear pending reader, qemu can't handle any more */ ++ qemu_mutex_lock(&pending_reader_lock); ++ if (pending_reader) { ++ pending_reader = NULL; ++ /* make sure the event loop doesn't hang */ ++ qemu_cond_signal(&pending_reader_condition); ++ } ++ qemu_mutex_unlock(&pending_reader_lock); ++ } ++ break; ++ case VSC_Init: ++ if (on_host_init(&mhHeader, (VSCMsgInit *)pbSendBuffer) < 0) { ++ return FALSE; ++ } ++ break; ++ default: ++ g_warn_if_reached(); ++ return FALSE; + } +- break; +- case VSC_Init: +- if (on_host_init(&mhHeader, (VSCMsgInit *)pbSendBuffer) < 0) { +- return -1; ++ ++ state = STATE_HEADER; ++ } ++ ++ ++ return TRUE; ++} ++ ++static gboolean ++do_socket(GIOChannel *source, ++ GIOCondition condition, ++ gpointer data) ++{ ++ /* not sure if two watches work well with a single win32 sources */ ++ if (condition & G_IO_OUT) { ++ if (!do_socket_send(source, condition, data)) { ++ return FALSE; + } +- break; +- default: +- printf("Default\n"); +- return -1; + } + +- return 0; ++ if (condition & G_IO_IN) { ++ if (!do_socket_read(source, condition, data)) { ++ return FALSE; ++ } ++ } ++ ++ return TRUE; + } + + static void +-do_command(void) ++update_socket_watch(gboolean out) ++{ ++ if (socket_tag != 0) { ++ g_source_remove(socket_tag); ++ } ++ ++ socket_tag = g_io_add_watch(channel_socket, ++ G_IO_IN | (out ? G_IO_OUT : 0), do_socket, NULL); ++} ++ ++static gboolean ++do_command(GIOChannel *source, ++ GIOCondition condition, ++ gpointer data) + { +- char inbuf[255]; + char *string; + VCardEmulError error; + static unsigned int default_reader_id; + unsigned int reader_id; + VReader *reader = NULL; ++ GError *err = NULL; ++ ++ g_assert(condition & G_IO_IN); + + reader_id = default_reader_id; +- string = fgets(inbuf, sizeof(inbuf), stdin); ++ g_io_channel_read_line(source, &string, NULL, NULL, &err); ++ if (err != NULL) { ++ g_error("Error while reading command: %s", err->message); ++ } ++ + if (string != NULL) { + if (strncmp(string, "exit", 4) == 0) { + /* remove all the readers */ +@@ -491,6 +583,8 @@ do_command(void) + vreader_free(reader); + printf("> "); + fflush(stdout); ++ ++ return TRUE; + } + + +@@ -504,7 +598,7 @@ connect_to_qemu( + ) { + struct addrinfo hints; + struct addrinfo *server; +- int ret; ++ int ret, sock; + + sock = qemu_socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { +@@ -543,6 +637,8 @@ main( + int argc, + char *argv[] + ) { ++ GMainLoop *loop; ++ GIOChannel *channel_stdin; + char *qemu_host; + char *qemu_port; + VSCMsgHeader mhHeader; +@@ -552,7 +648,10 @@ main( + char *cert_names[MAX_CERTS]; + char *emul_args = NULL; + int cert_count = 0; +- int c, rv; ++ int c, sock; ++ ++ if (socket_init() != 0) ++ return 1; + + while ((c = getopt(argc, argv, "c:e:pd:")) != -1) { + switch (c) { +@@ -618,15 +717,33 @@ main( + exit(5); + } + +- qemu_mutex_init(&write_lock); ++ socket_to_send = g_byte_array_new(); ++ qemu_mutex_init(&socket_to_send_lock); + qemu_mutex_init(&pending_reader_lock); + qemu_cond_init(&pending_reader_condition); + + vcard_emul_init(command_line_options); + ++ loop = g_main_loop_new(NULL, true); ++ + printf("> "); + fflush(stdout); + ++#ifdef _WIN32 ++ channel_stdin = g_io_channel_win32_new_fd(STDIN_FILENO); ++#else ++ channel_stdin = g_io_channel_unix_new(STDIN_FILENO); ++#endif ++ g_io_add_watch(channel_stdin, G_IO_IN, do_command, NULL); ++#ifdef _WIN32 ++ channel_socket = g_io_channel_win32_new_socket(sock); ++#else ++ channel_socket = g_io_channel_unix_new(sock); ++#endif ++ g_io_channel_set_encoding(channel_socket, NULL, NULL); ++ /* we buffer ourself for thread safety reasons */ ++ g_io_channel_set_buffered(channel_socket, FALSE); ++ + /* Send init message, Host responds (and then we send reader attachments) */ + VSCMsgInit init = { + .version = htonl(VSCARD_VERSION), +@@ -635,28 +752,12 @@ main( + }; + send_msg(VSC_Init, mhHeader.reader_id, &init, sizeof(init)); + +- do { +- fd_set fds; +- +- FD_ZERO(&fds); +- FD_SET(1, &fds); +- FD_SET(sock, &fds); ++ g_main_loop_run(loop); ++ g_main_loop_unref(loop); + +- /* waiting on input from the socket */ +- rv = select(sock+1, &fds, NULL, NULL, NULL); +- if (rv < 0) { +- /* handle error */ +- perror("select"); +- return 7; +- } +- if (FD_ISSET(1, &fds)) { +- do_command(); +- } +- if (!FD_ISSET(sock, &fds)) { +- continue; +- } +- rv = do_socket_read(); +- } while (rv >= 0); ++ g_io_channel_unref(channel_stdin); ++ g_io_channel_unref(channel_socket); ++ g_byte_array_unref(socket_to_send); + + return 0; + } +-- +1.8.3.1 + diff --git a/0223-libcacard-remove-sql-prefix.patch b/0223-libcacard-remove-sql-prefix.patch new file mode 100644 index 0000000..ee58836 --- /dev/null +++ b/0223-libcacard-remove-sql-prefix.patch @@ -0,0 +1,47 @@ +From 1975b2acbff807d88d494153db64882d19410724 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Wed, 20 Mar 2013 14:07:48 +0100 +Subject: [PATCH 223/241] libcacard: remove sql: prefix +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +For some reason, with sql:/ prefix, the PKCS11 modules are not loaded. + +This patch goes on top of Alon smartcard series. + +Signed-off-by: Marc-André Lureau +Reviewed-by: Alon Levy +(cherry picked from commit 667e0b4b6806d53e0b46e29a15d24427ef958c78) +--- + libcacard/vcard_emul_nss.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c +index 21d4689..6b1ca8a 100644 +--- a/libcacard/vcard_emul_nss.c ++++ b/libcacard/vcard_emul_nss.c +@@ -893,7 +893,7 @@ vcard_emul_init(const VCardEmulOptions *options) + if (options->nss_db) { + rv = NSS_Init(options->nss_db); + } else { +- gchar *path, *db; ++ gchar *path; + #ifndef _WIN32 + path = g_strdup("/etc/pki/nssdb"); + #else +@@ -905,10 +905,8 @@ vcard_emul_init(const VCardEmulOptions *options) + path = g_build_filename( + g_get_system_config_dirs()[0], "pki", "nssdb", NULL); + #endif +- db = g_strdup_printf("sql:%s", path); + +- rv = NSS_Init(db); +- g_free(db); ++ rv = NSS_Init(path); + g_free(path); + } + if (rv != SECSuccess) { +-- +1.8.3.1 + diff --git a/0224-libcacard-remove-default-libcoolkey-loading.patch b/0224-libcacard-remove-default-libcoolkey-loading.patch new file mode 100644 index 0000000..77cb055 --- /dev/null +++ b/0224-libcacard-remove-default-libcoolkey-loading.patch @@ -0,0 +1,64 @@ +From 26acaa4bf064f7608dec08cff4d23769b167dced Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Wed, 20 Mar 2013 14:07:49 +0100 +Subject: [PATCH 224/241] libcacard: remove default libcoolkey loading +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use only the modules defined in the NSS database. + +Signed-off-by: Marc-André Lureau +Reviewed-by: Alon Levy +(cherry picked from commit ad2181f2b612cd8bf0a790faa2a1b51559f7234b) +--- + libcacard/vcard_emul_nss.c | 17 +---------------- + 1 file changed, 1 insertion(+), 16 deletions(-) + +diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c +index 6b1ca8a..9ba80fb 100644 +--- a/libcacard/vcard_emul_nss.c ++++ b/libcacard/vcard_emul_nss.c +@@ -870,7 +870,7 @@ VCardEmulError + vcard_emul_init(const VCardEmulOptions *options) + { + SECStatus rv; +- PRBool ret, has_readers = PR_FALSE, need_coolkey_module; ++ PRBool ret, has_readers = PR_FALSE; + VReader *vreader; + VReaderEmul *vreader_emul; + SECMODListLock *module_lock; +@@ -983,30 +983,15 @@ vcard_emul_init(const VCardEmulOptions *options) + /* make sure we have some PKCS #11 module loaded */ + module_lock = SECMOD_GetDefaultModuleListLock(); + module_list = SECMOD_GetDefaultModuleList(); +- need_coolkey_module = !has_readers; + SECMOD_GetReadLock(module_lock); + for (mlp = module_list; mlp; mlp = mlp->next) { + SECMODModule *module = mlp->module; + if (module_has_removable_hw_slots(module)) { +- need_coolkey_module = PR_FALSE; + break; + } + } + SECMOD_ReleaseReadLock(module_lock); + +- if (need_coolkey_module) { +- SECMODModule *module; +- module = SECMOD_LoadUserModule( +- (char *)"library=libcoolkeypk11.so name=Coolkey", +- NULL, PR_FALSE); +- if (module == NULL) { +- return VCARD_EMUL_FAIL; +- } +- SECMOD_DestroyModule(module); /* free our reference, Module will still +- * be on the list. +- * until we destroy it */ +- } +- + /* now examine all the slots, finding which should be readers */ + /* We should control this with options. For now we mirror out any + * removable hardware slot */ +-- +1.8.3.1 + diff --git a/0225-dev-smartcard-reader-white-space-fixes.patch b/0225-dev-smartcard-reader-white-space-fixes.patch new file mode 100644 index 0000000..c00da7d --- /dev/null +++ b/0225-dev-smartcard-reader-white-space-fixes.patch @@ -0,0 +1,54 @@ +From c1a01e889c7562c5e61cbd2da7844697c56940bd Mon Sep 17 00:00:00 2001 +From: Alon Levy +Date: Mon, 4 Mar 2013 18:45:49 +0200 +Subject: [PATCH 225/241] dev-smartcard-reader: white space fixes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Alon Levy +Reviewed-by: Marc-André Lureau +(cherry picked from commit 4543d43c6181d90f86fb528430f250810dde03d5) +--- + hw/usb/dev-smartcard-reader.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c +index 979a473..24c84ce 100644 +--- a/hw/usb/dev-smartcard-reader.c ++++ b/hw/usb/dev-smartcard-reader.c +@@ -471,6 +471,7 @@ static const USBDesc desc_ccid = { + static const uint8_t *ccid_card_get_atr(CCIDCardState *card, uint32_t *len) + { + CCIDCardClass *cc = CCID_CARD_GET_CLASS(card); ++ + if (cc->get_atr) { + return cc->get_atr(card, len); + } +@@ -482,6 +483,7 @@ static void ccid_card_apdu_from_guest(CCIDCardState *card, + uint32_t len) + { + CCIDCardClass *cc = CCID_CARD_GET_CLASS(card); ++ + if (cc->apdu_from_guest) { + cc->apdu_from_guest(card, apdu, len); + } +@@ -490,6 +492,7 @@ static void ccid_card_apdu_from_guest(CCIDCardState *card, + static int ccid_card_exitfn(CCIDCardState *card) + { + CCIDCardClass *cc = CCID_CARD_GET_CLASS(card); ++ + if (cc->exitfn) { + return cc->exitfn(card); + } +@@ -499,6 +502,7 @@ static int ccid_card_exitfn(CCIDCardState *card) + static int ccid_card_initfn(CCIDCardState *card) + { + CCIDCardClass *cc = CCID_CARD_GET_CLASS(card); ++ + if (cc->initfn) { + return cc->initfn(card); + } +-- +1.8.3.1 + diff --git a/0226-dev-smartcard-reader-nicer-debug-messages.patch b/0226-dev-smartcard-reader-nicer-debug-messages.patch new file mode 100644 index 0000000..660c460 --- /dev/null +++ b/0226-dev-smartcard-reader-nicer-debug-messages.patch @@ -0,0 +1,144 @@ +From bd39de640ffd3f552775bfb1a084657872acd114 Mon Sep 17 00:00:00 2001 +From: Alon Levy +Date: Mon, 4 Mar 2013 18:50:33 +0200 +Subject: [PATCH 226/241] dev-smartcard-reader: nicer debug messages +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Alon Levy +Reviewed-by: Marc-André Lureau +(cherry picked from commit 7e1ac5abe3fbbfee4ddfc2d9971a644bd787e055) +--- + hw/usb/dev-smartcard-reader.c | 69 +++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 63 insertions(+), 6 deletions(-) + +diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c +index 24c84ce..173dcc9 100644 +--- a/hw/usb/dev-smartcard-reader.c ++++ b/hw/usb/dev-smartcard-reader.c +@@ -639,13 +639,47 @@ static void ccid_handle_reset(USBDevice *dev) + ccid_reset(s); + } + ++static const char *ccid_control_to_str(USBCCIDState *s, int request) ++{ ++ switch (request) { ++ /* generic - should be factored out if there are other debugees */ ++ case DeviceOutRequest | USB_REQ_SET_ADDRESS: ++ return "(generic) set address"; ++ case DeviceRequest | USB_REQ_GET_DESCRIPTOR: ++ return "(generic) get descriptor"; ++ case DeviceRequest | USB_REQ_GET_CONFIGURATION: ++ return "(generic) get configuration"; ++ case DeviceOutRequest | USB_REQ_SET_CONFIGURATION: ++ return "(generic) set configuration"; ++ case DeviceRequest | USB_REQ_GET_STATUS: ++ return "(generic) get status"; ++ case DeviceOutRequest | USB_REQ_CLEAR_FEATURE: ++ return "(generic) clear feature"; ++ case DeviceOutRequest | USB_REQ_SET_FEATURE: ++ return "(generic) set_feature"; ++ case InterfaceRequest | USB_REQ_GET_INTERFACE: ++ return "(generic) get interface"; ++ case InterfaceOutRequest | USB_REQ_SET_INTERFACE: ++ return "(generic) set interface"; ++ /* class requests */ ++ case ClassInterfaceOutRequest | CCID_CONTROL_ABORT: ++ return "ABORT"; ++ case ClassInterfaceRequest | CCID_CONTROL_GET_CLOCK_FREQUENCIES: ++ return "GET_CLOCK_FREQUENCIES"; ++ case ClassInterfaceRequest | CCID_CONTROL_GET_DATA_RATES: ++ return "GET_DATA_RATES"; ++ } ++ return "unknown"; ++} ++ + static void ccid_handle_control(USBDevice *dev, USBPacket *p, int request, + int value, int index, int length, uint8_t *data) + { + USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev); + int ret; + +- DPRINTF(s, 1, "got control %x, value %x\n", request, value); ++ DPRINTF(s, 1, "%s: got control %s (%x), value %x\n", __func__, ++ ccid_control_to_str(s, request), request, value); + ret = usb_desc_handle_control(dev, p, request, value, index, length, data); + if (ret >= 0) { + return; +@@ -695,7 +729,7 @@ static uint8_t ccid_calc_status(USBCCIDState *s) + * bmCommandStatus + */ + uint8_t ret = ccid_card_status(s) | (s->bmCommandStatus << 6); +- DPRINTF(s, D_VERBOSE, "status = %d\n", ret); ++ DPRINTF(s, D_VERBOSE, "%s: status = %d\n", __func__, ret); + return ret; + } + +@@ -756,7 +790,7 @@ static void ccid_write_data_block(USBCCIDState *s, uint8_t slot, uint8_t seq, + p->b.bStatus = ccid_calc_status(s); + p->b.bError = s->bError; + if (p->b.bError) { +- DPRINTF(s, D_VERBOSE, "error %d", p->b.bError); ++ DPRINTF(s, D_VERBOSE, "error %d\n", p->b.bError); + } + memcpy(p->abData, data, len); + ccid_reset_error_status(s); +@@ -873,6 +907,28 @@ static void ccid_on_apdu_from_guest(USBCCIDState *s, CCID_XferBlock *recv) + } + } + ++static const char *ccid_message_type_to_str(uint8_t type) ++{ ++ switch (type) { ++ case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOn: return "IccPowerOn"; ++ case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOff: return "IccPowerOff"; ++ case CCID_MESSAGE_TYPE_PC_to_RDR_GetSlotStatus: return "GetSlotStatus"; ++ case CCID_MESSAGE_TYPE_PC_to_RDR_XfrBlock: return "XfrBlock"; ++ case CCID_MESSAGE_TYPE_PC_to_RDR_GetParameters: return "GetParameters"; ++ case CCID_MESSAGE_TYPE_PC_to_RDR_ResetParameters: return "ResetParameters"; ++ case CCID_MESSAGE_TYPE_PC_to_RDR_SetParameters: return "SetParameters"; ++ case CCID_MESSAGE_TYPE_PC_to_RDR_Escape: return "Escape"; ++ case CCID_MESSAGE_TYPE_PC_to_RDR_IccClock: return "IccClock"; ++ case CCID_MESSAGE_TYPE_PC_to_RDR_T0APDU: return "T0APDU"; ++ case CCID_MESSAGE_TYPE_PC_to_RDR_Secure: return "Secure"; ++ case CCID_MESSAGE_TYPE_PC_to_RDR_Mechanical: return "Mechanical"; ++ case CCID_MESSAGE_TYPE_PC_to_RDR_Abort: return "Abort"; ++ case CCID_MESSAGE_TYPE_PC_to_RDR_SetDataRateAndClockFrequency: ++ return "SetDataRateAndClockFrequency"; ++ } ++ return "unknown"; ++} ++ + static void ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p) + { + CCID_Header *ccid_header; +@@ -895,13 +951,15 @@ static void ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p) + "%s: bad USB_TOKEN_OUT length, should be at least 10 bytes\n", + __func__); + } else { +- DPRINTF(s, D_MORE_INFO, "%s %x\n", __func__, ccid_header->bMessageType); ++ DPRINTF(s, D_MORE_INFO, "%s %x %s\n", __func__, ++ ccid_header->bMessageType, ++ ccid_message_type_to_str(ccid_header->bMessageType)); + switch (ccid_header->bMessageType) { + case CCID_MESSAGE_TYPE_PC_to_RDR_GetSlotStatus: + ccid_write_slot_status(s, ccid_header); + break; + case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOn: +- DPRINTF(s, 1, "PowerOn: %d\n", ++ DPRINTF(s, 1, "%s: PowerOn: %d\n", __func__, + ((CCID_IccPowerOn *)(ccid_header))->bPowerSelect); + s->powered = true; + if (!ccid_card_inserted(s)) { +@@ -911,7 +969,6 @@ static void ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p) + ccid_write_data_block_atr(s, ccid_header); + break; + case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOff: +- DPRINTF(s, 1, "PowerOff\n"); + ccid_reset_error_status(s); + s->powered = false; + ccid_write_slot_status(s, ccid_header); +-- +1.8.3.1 + diff --git a/0227-dev-smartcard-reader-remove-aborts-never-triggered-b.patch b/0227-dev-smartcard-reader-remove-aborts-never-triggered-b.patch new file mode 100644 index 0000000..6306c72 --- /dev/null +++ b/0227-dev-smartcard-reader-remove-aborts-never-triggered-b.patch @@ -0,0 +1,71 @@ +From 006440535dd1d581f0e5b7b15295fe511589c3e2 Mon Sep 17 00:00:00 2001 +From: Alon Levy +Date: Mon, 4 Mar 2013 18:55:07 +0200 +Subject: [PATCH 227/241] dev-smartcard-reader: remove aborts (never triggered, + but just in case) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Alon Levy +Reviewed-by: Marc-André Lureau +(cherry picked from commit 47bf53af7507986fc473cb308324340448fd85e7) +--- + hw/usb/dev-smartcard-reader.c | 20 ++++++++++++-------- + 1 file changed, 12 insertions(+), 8 deletions(-) + +diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c +index 173dcc9..54ea536 100644 +--- a/hw/usb/dev-smartcard-reader.c ++++ b/hw/usb/dev-smartcard-reader.c +@@ -796,6 +796,12 @@ static void ccid_write_data_block(USBCCIDState *s, uint8_t slot, uint8_t seq, + ccid_reset_error_status(s); + } + ++static void ccid_report_error_failed(USBCCIDState *s, uint8_t error) ++{ ++ s->bmCommandStatus = COMMAND_STATUS_FAILED; ++ s->bError = error; ++} ++ + static void ccid_write_data_block_answer(USBCCIDState *s, + const uint8_t *data, uint32_t len) + { +@@ -803,7 +809,9 @@ static void ccid_write_data_block_answer(USBCCIDState *s, + uint8_t slot; + + if (!ccid_has_pending_answers(s)) { +- abort(); ++ DPRINTF(s, D_WARN, "error: no pending answer to return to guest\n"); ++ ccid_report_error_failed(s, ERROR_ICC_MUTE); ++ return; + } + ccid_remove_pending_answer(s, &slot, &seq); + ccid_write_data_block(s, slot, seq, data, len); +@@ -857,12 +865,6 @@ static void ccid_reset_parameters(USBCCIDState *s) + memcpy(s->abProtocolDataStructure, abDefaultProtocolDataStructure, len); + } + +-static void ccid_report_error_failed(USBCCIDState *s, uint8_t error) +-{ +- s->bmCommandStatus = COMMAND_STATUS_FAILED; +- s->bError = error; +-} +- + /* NOTE: only a single slot is supported (SLOT_0) */ + static void ccid_on_slot_change(USBCCIDState *s, bool full) + { +@@ -1129,7 +1131,9 @@ void ccid_card_send_apdu_to_guest(CCIDCardState *card, + s->bmCommandStatus = COMMAND_STATUS_NO_ERROR; + answer = ccid_peek_next_answer(s); + if (answer == NULL) { +- abort(); ++ DPRINTF(s, D_WARN, "%s: error: unexpected lack of answer\n", __func__); ++ ccid_report_error_failed(s, ERROR_HW_ERROR); ++ return; + } + DPRINTF(s, 1, "APDU returned to guest %d (answer seq %d, slot %d)\n", + len, answer->seq, answer->slot); +-- +1.8.3.1 + diff --git a/0228-dev-smartcard-reader-support-windows-guest.patch b/0228-dev-smartcard-reader-support-windows-guest.patch new file mode 100644 index 0000000..6fd2e09 --- /dev/null +++ b/0228-dev-smartcard-reader-support-windows-guest.patch @@ -0,0 +1,38 @@ +From 6339bbf28651cbcb5cf24bd1d53cd7b52028ff1b Mon Sep 17 00:00:00 2001 +From: Alon Levy +Date: Mon, 4 Mar 2013 21:40:53 +0200 +Subject: [PATCH 228/241] dev-smartcard-reader: support windows guest +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +By not advertising USB wakeup support (which we don't). + +Signed-off-by: Alon Levy +Reviewed-by: Marc-André Lureau +(cherry picked from commit c5cd7c875608911ec74817d24cd12b825014ba19) +--- + hw/usb/dev-smartcard-reader.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c +index 54ea536..db5dd6d 100644 +--- a/hw/usb/dev-smartcard-reader.c ++++ b/hw/usb/dev-smartcard-reader.c +@@ -359,11 +359,11 @@ static const uint8_t qemu_ccid_descriptor[] = { + * 20000 Short APDU level exchange with CCID + * 40000 Short and Extended APDU level exchange with CCID + * +- * + 100000 USB Wake up signaling supported on card ++ * 100000 USB Wake up signaling supported on card + * insertion and removal. Must set bit 5 in bmAttributes + * in Configuration descriptor if 100000 is set. + */ +- 0xfe, 0x04, 0x11, 0x00, ++ 0xfe, 0x04, 0x01, 0x00, + /* + * u32 dwMaxCCIDMessageLength; For extended APDU in + * [261 + 10 , 65544 + 10]. Otherwise the minimum is +-- +1.8.3.1 + diff --git a/0229-dev-smartcard-reader-reuse-usb.h-definitions.patch b/0229-dev-smartcard-reader-reuse-usb.h-definitions.patch new file mode 100644 index 0000000..1616e7a --- /dev/null +++ b/0229-dev-smartcard-reader-reuse-usb.h-definitions.patch @@ -0,0 +1,65 @@ +From b7fd4cdb21c93be3a3e4b2d309f07e56d47eb2a4 Mon Sep 17 00:00:00 2001 +From: Alon Levy +Date: Tue, 5 Mar 2013 15:31:26 +0200 +Subject: [PATCH 229/241] dev-smartcard-reader: reuse usb.h definitions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Alon Levy +Reviewed-by: Marc-André Lureau +(cherry picked from commit 693e47738d05463b2743b0a652412d33cf254977) +--- + hw/usb/dev-smartcard-reader.c | 16 +++++----------- + 1 file changed, 5 insertions(+), 11 deletions(-) + +diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c +index db5dd6d..75f813c 100644 +--- a/hw/usb/dev-smartcard-reader.c ++++ b/hw/usb/dev-smartcard-reader.c +@@ -68,12 +68,6 @@ do { \ + #define BULK_IN_BUF_SIZE 384 + #define BULK_IN_PENDING_NUM 8 + +-#define InterfaceOutClass \ +- ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE)<<8) +- +-#define InterfaceInClass \ +- ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE)<<8) +- + #define CCID_MAX_PACKET_SIZE 64 + + #define CCID_CONTROL_ABORT 0x1 +@@ -410,8 +404,8 @@ static const USBDescStrings desc_strings = { + static const USBDescIface desc_iface0 = { + .bInterfaceNumber = 0, + .bNumEndpoints = 3, +- .bInterfaceClass = 0x0b, +- .bInterfaceSubClass = 0x00, ++ .bInterfaceClass = USB_CLASS_CSCID, ++ .bInterfaceSubClass = USB_SUBCLASS_UNDEFINED, + .bInterfaceProtocol = 0x00, + .iInterface = STR_INTERFACE, + .ndesc = 1, +@@ -687,15 +681,15 @@ static void ccid_handle_control(USBDevice *dev, USBPacket *p, int request, + + switch (request) { + /* Class specific requests. */ +- case InterfaceOutClass | CCID_CONTROL_ABORT: ++ case ClassInterfaceOutRequest | CCID_CONTROL_ABORT: + DPRINTF(s, 1, "ccid_control abort UNIMPLEMENTED\n"); + p->status = USB_RET_STALL; + break; +- case InterfaceInClass | CCID_CONTROL_GET_CLOCK_FREQUENCIES: ++ case ClassInterfaceRequest | CCID_CONTROL_GET_CLOCK_FREQUENCIES: + DPRINTF(s, 1, "ccid_control get clock frequencies UNIMPLEMENTED\n"); + p->status = USB_RET_STALL; + break; +- case InterfaceInClass | CCID_CONTROL_GET_DATA_RATES: ++ case ClassInterfaceRequest | CCID_CONTROL_GET_DATA_RATES: + DPRINTF(s, 1, "ccid_control get data rates UNIMPLEMENTED\n"); + p->status = USB_RET_STALL; + break; +-- +1.8.3.1 + diff --git a/0230-libcacard-change-default-ATR.patch b/0230-libcacard-change-default-ATR.patch new file mode 100644 index 0000000..3cfee43 --- /dev/null +++ b/0230-libcacard-change-default-ATR.patch @@ -0,0 +1,42 @@ +From b3d57573e23a456b2c21f045b153e2c0a621f886 Mon Sep 17 00:00:00 2001 +From: Alon Levy +Date: Tue, 5 Mar 2013 15:35:24 +0200 +Subject: [PATCH 230/241] libcacard: change default ATR +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Alon Levy +Reviewed-by: Marc-André Lureau +(cherry picked from commit a26dfd95d33d650f9f9f93b6ee6f03be925db1a8) +--- + libcacard/vcardt.h | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/libcacard/vcardt.h b/libcacard/vcardt.h +index 538bdde..3b9a619 100644 +--- a/libcacard/vcardt.h ++++ b/libcacard/vcardt.h +@@ -26,9 +26,17 @@ typedef struct VCardEmulStruct VCardEmul; + #define MAX_CHANNEL 4 + + /* create an ATR with appropriate historical bytes */ +-#define VCARD_ATR_PREFIX(size) 0x3b, 0x66+(size), 0x00, 0xff, \ +- 'V', 'C', 'A', 'R', 'D', '_' ++#define TS_DIRECT_CONVENTION 0x3b ++#define TA_PRESENT 0x10 ++#define TB_PRESENT 0x20 ++#define TC_PRESENT 0x40 ++#define TD_PRESENT 0x80 + ++#define VCARD_ATR_PREFIX(size) \ ++ TS_DIRECT_CONVENTION, \ ++ TD_PRESENT + (6 + size), \ ++ 0x00, \ ++ 'V', 'C', 'A', 'R', 'D', '_' + + typedef enum { + VCARD_DONE, +-- +1.8.3.1 + diff --git a/0231-ccid-card-passthru-add-atr-check.patch b/0231-ccid-card-passthru-add-atr-check.patch new file mode 100644 index 0000000..abae187 --- /dev/null +++ b/0231-ccid-card-passthru-add-atr-check.patch @@ -0,0 +1,95 @@ +From 1c4d96f6622f00c4d4b84b5e17f8e42dcb5b7501 Mon Sep 17 00:00:00 2001 +From: Alon Levy +Date: Mon, 4 Mar 2013 18:39:09 +0200 +Subject: [PATCH 231/241] ccid-card-passthru: add atr check +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Alon Levy +Reviewed-by: Marc-André Lureau +(cherry picked from commit 0e61400c1941aabc9f45d5ff961b57337c7caac6) +--- + hw/ccid-card-passthru.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 59 insertions(+) + +diff --git a/hw/ccid-card-passthru.c b/hw/ccid-card-passthru.c +index 62070db..7fecd10 100644 +--- a/hw/ccid-card-passthru.c ++++ b/hw/ccid-card-passthru.c +@@ -138,6 +138,59 @@ static void ccid_card_vscard_handle_init( + ccid_card_vscard_send_init(card); + } + ++static int check_atr(PassthruState *card, uint8_t *data, int len) ++{ ++ int historical_length, opt_bytes; ++ int td_count = 0; ++ int td; ++ ++ if (len < 2) { ++ return 0; ++ } ++ historical_length = data[1] & 0xf; ++ opt_bytes = 0; ++ if (data[0] != 0x3b && data[0] != 0x3f) { ++ DPRINTF(card, D_WARN, "atr's T0 is 0x%X, not in {0x3b, 0x3f}\n", ++ data[0]); ++ return 0; ++ } ++ td_count = 0; ++ td = data[1] >> 4; ++ while (td && td_count < 2 && opt_bytes + historical_length + 2 < len) { ++ td_count++; ++ if (td & 0x1) { ++ opt_bytes++; ++ } ++ if (td & 0x2) { ++ opt_bytes++; ++ } ++ if (td & 0x4) { ++ opt_bytes++; ++ } ++ if (td & 0x8) { ++ opt_bytes++; ++ td = data[opt_bytes + 2] >> 4; ++ } ++ } ++ if (len < 2 + historical_length + opt_bytes) { ++ DPRINTF(card, D_WARN, ++ "atr too short: len %d, but historical_len %d, T1 0x%X\n", ++ len, historical_length, data[1]); ++ return 0; ++ } ++ if (len > 2 + historical_length + opt_bytes) { ++ DPRINTF(card, D_WARN, ++ "atr too long: len %d, but hist/opt %d/%d, T1 0x%X\n", ++ len, historical_length, opt_bytes, data[1]); ++ /* let it through */ ++ } ++ DPRINTF(card, D_VERBOSE, ++ "atr passes check: %d total length, %d historical, %d optional\n", ++ len, historical_length, opt_bytes); ++ ++ return 1; ++} ++ + static void ccid_card_vscard_handle_message(PassthruState *card, + VSCMsgHeader *scr_msg_header) + { +@@ -152,6 +205,12 @@ static void ccid_card_vscard_handle_message(PassthruState *card, + VSC_GENERAL_ERROR); + break; + } ++ if (!check_atr(card, data, scr_msg_header->length)) { ++ error_report("ATR is inconsistent, ignoring"); ++ ccid_card_vscard_send_error(card, scr_msg_header->reader_id, ++ VSC_GENERAL_ERROR); ++ break; ++ } + memcpy(card->atr, data, scr_msg_header->length); + card->atr_length = scr_msg_header->length; + ccid_card_card_inserted(&card->base); +-- +1.8.3.1 + diff --git a/0232-ccid-card-passthru-dev-smartcard-reader-add-debug-en.patch b/0232-ccid-card-passthru-dev-smartcard-reader-add-debug-en.patch new file mode 100644 index 0000000..39cb23e --- /dev/null +++ b/0232-ccid-card-passthru-dev-smartcard-reader-add-debug-en.patch @@ -0,0 +1,110 @@ +From f462152289d55ae01456d1d9122e26ff63407520 Mon Sep 17 00:00:00 2001 +From: Alon Levy +Date: Mon, 4 Mar 2013 18:41:28 +0200 +Subject: [PATCH 232/241] ccid-card-passthru, dev-smartcard-reader: add debug + environment variables +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Introduces a new utility function: parse_debug_env to avoid code +duplication. + +This overrides whatever debug value is set on the corresponding devices +from the command line, and is meant to ease the usage with any +management stack. For libvirt you can set environment variables by +extending the dom namespace, i.e: + + + + + + + + +Signed-off-by: Alon Levy +Reviewed-by: Marc-André Lureau +(cherry picked from commit b16352acf3105000e14f194b556e159d5d06cff9) + +Conflicts: + include/qemu-common.h +--- + hw/ccid-card-passthru.c | 2 ++ + hw/usb/dev-smartcard-reader.c | 1 + + include/qemu-common.h | 5 +++++ + util/cutils.c | 23 +++++++++++++++++++++++ + 4 files changed, 31 insertions(+) + +diff --git a/hw/ccid-card-passthru.c b/hw/ccid-card-passthru.c +index 7fecd10..4026ccd 100644 +--- a/hw/ccid-card-passthru.c ++++ b/hw/ccid-card-passthru.c +@@ -353,6 +353,8 @@ static int passthru_initfn(CCIDCardState *base) + error_report("missing chardev"); + return -1; + } ++ card->debug = parse_debug_env("QEMU_CCID_PASSTHRU_DEBUG", D_VERBOSE, ++ card->debug); + assert(sizeof(DEFAULT_ATR) <= MAX_ATR_SIZE); + memcpy(card->atr, DEFAULT_ATR, sizeof(DEFAULT_ATR)); + card->atr_length = sizeof(DEFAULT_ATR); +diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c +index 75f813c..09c2403 100644 +--- a/hw/usb/dev-smartcard-reader.c ++++ b/hw/usb/dev-smartcard-reader.c +@@ -1260,6 +1260,7 @@ static int ccid_initfn(USBDevice *dev) + s->bulk_out_pos = 0; + ccid_reset_parameters(s); + ccid_reset(s); ++ s->debug = parse_debug_env("QEMU_CCID_DEBUG", D_VERBOSE, s->debug); + return 0; + } + +diff --git a/include/qemu-common.h b/include/qemu-common.h +index 80016ad..77d0980 100644 +--- a/include/qemu-common.h ++++ b/include/qemu-common.h +@@ -430,4 +430,9 @@ int64_t pow2floor(int64_t value); + int uleb128_encode_small(uint8_t *out, uint32_t n); + int uleb128_decode_small(const uint8_t *in, uint32_t *n); + ++/* ++ * helper to parse debug environment variables ++ */ ++int parse_debug_env(const char *name, int max, int initial); ++ + #endif +diff --git a/util/cutils.c b/util/cutils.c +index 1439da4..32e1f5b 100644 +--- a/util/cutils.c ++++ b/util/cutils.c +@@ -422,3 +422,26 @@ int uleb128_decode_small(const uint8_t *in, uint32_t *n) + return 2; + } + } ++ ++/* ++ * helper to parse debug environment variables ++ */ ++int parse_debug_env(const char *name, int max, int initial) ++{ ++ char *debug_env = getenv(name); ++ char *inv = NULL; ++ int debug; ++ ++ if (!debug_env) { ++ return initial; ++ } ++ debug = strtol(debug_env, &inv, 10); ++ if (inv == debug_env) { ++ return initial; ++ } ++ if (debug < 0 || debug > max) { ++ fprintf(stderr, "warning: %s not in [0, %d]", name, max); ++ return initial; ++ } ++ return debug; ++} +-- +1.8.3.1 + diff --git a/0233-dev-smartcard-reader-define-structs-for-CCID_Paramet.patch b/0233-dev-smartcard-reader-define-structs-for-CCID_Paramet.patch new file mode 100644 index 0000000..89f2fb5 --- /dev/null +++ b/0233-dev-smartcard-reader-define-structs-for-CCID_Paramet.patch @@ -0,0 +1,161 @@ +From 4d36e75eb55c7ee557bebabd6fe33c5a65d52228 Mon Sep 17 00:00:00 2001 +From: Alon Levy +Date: Mon, 4 Mar 2013 18:57:45 +0200 +Subject: [PATCH 233/241] dev-smartcard-reader: define structs for + CCID_Parameter internals +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Alon Levy +Reviewed-by: Marc-André Lureau +(cherry picked from commit 4942d6c39477f441a106430ab11f85806b4532f5) +--- + hw/usb/dev-smartcard-reader.c | 74 +++++++++++++++++++++++++++---------------- + 1 file changed, 47 insertions(+), 27 deletions(-) + +diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c +index 09c2403..f2cab09 100644 +--- a/hw/usb/dev-smartcard-reader.c ++++ b/hw/usb/dev-smartcard-reader.c +@@ -189,10 +189,34 @@ typedef struct QEMU_PACKED CCID_SlotStatus { + uint8_t bClockStatus; + } CCID_SlotStatus; + ++typedef struct QEMU_PACKED CCID_T0ProtocolDataStructure { ++ uint8_t bmFindexDindex; ++ uint8_t bmTCCKST0; ++ uint8_t bGuardTimeT0; ++ uint8_t bWaitingIntegerT0; ++ uint8_t bClockStop; ++} CCID_T0ProtocolDataStructure; ++ ++typedef struct QEMU_PACKED CCID_T1ProtocolDataStructure { ++ uint8_t bmFindexDindex; ++ uint8_t bmTCCKST1; ++ uint8_t bGuardTimeT1; ++ uint8_t bWaitingIntegerT1; ++ uint8_t bClockStop; ++ uint8_t bIFSC; ++ uint8_t bNadValue; ++} CCID_T1ProtocolDataStructure; ++ ++typedef union CCID_ProtocolDataStructure { ++ CCID_T0ProtocolDataStructure t0; ++ CCID_T1ProtocolDataStructure t1; ++ uint8_t data[7]; /* must be = max(sizeof(t0), sizeof(t1)) */ ++} CCID_ProtocolDataStructure; ++ + typedef struct QEMU_PACKED CCID_Parameter { + CCID_BULK_IN b; + uint8_t bProtocolNum; +- uint8_t abProtocolDataStructure[0]; ++ CCID_ProtocolDataStructure abProtocolDataStructure; + } CCID_Parameter; + + typedef struct QEMU_PACKED CCID_DataBlock { +@@ -224,7 +248,7 @@ typedef struct QEMU_PACKED CCID_SetParameters { + CCID_Header hdr; + uint8_t bProtocolNum; + uint16_t abRFU; +- uint8_t abProtocolDataStructure[0]; ++ CCID_ProtocolDataStructure abProtocolDataStructure; + } CCID_SetParameters; + + typedef struct CCID_Notify_Slot_Change { +@@ -254,8 +278,6 @@ typedef struct CCIDBus { + BusState qbus; + } CCIDBus; + +-#define MAX_PROTOCOL_SIZE 7 +- + /* + * powered - defaults to true, changed by PowerOn/PowerOff messages + */ +@@ -279,7 +301,7 @@ typedef struct USBCCIDState { + uint8_t bError; + uint8_t bmCommandStatus; + uint8_t bProtocolNum; +- uint8_t abProtocolDataStructure[MAX_PROTOCOL_SIZE]; ++ CCID_ProtocolDataStructure abProtocolDataStructure; + uint32_t ulProtocolDataStructureSize; + uint32_t state_vmstate; + uint32_t migration_target_ip; +@@ -765,7 +787,7 @@ static void ccid_write_parameters(USBCCIDState *s, CCID_Header *recv) + h->b.bStatus = ccid_calc_status(s); + h->b.bError = s->bError; + h->bProtocolNum = s->bProtocolNum; +- memcpy(h->abProtocolDataStructure, s->abProtocolDataStructure, len); ++ h->abProtocolDataStructure = s->abProtocolDataStructure; + ccid_reset_error_status(s); + } + +@@ -825,38 +847,36 @@ static void ccid_write_data_block_atr(USBCCIDState *s, CCID_Header *recv) + static void ccid_set_parameters(USBCCIDState *s, CCID_Header *recv) + { + CCID_SetParameters *ph = (CCID_SetParameters *) recv; +- uint32_t len = 0; +- if ((ph->bProtocolNum & 3) == 0) { +- len = 5; +- } +- if ((ph->bProtocolNum & 3) == 1) { +- len = 7; +- } +- if (len == 0) { +- s->bmCommandStatus = COMMAND_STATUS_FAILED; +- s->bError = 7; /* Protocol invalid or not supported */ ++ uint32_t protocol_num = ph->bProtocolNum & 3; ++ ++ if (protocol_num != 0 && protocol_num != 1) { ++ ccid_report_error_failed(s, ERROR_CMD_NOT_SUPPORTED); + return; + } +- s->bProtocolNum = ph->bProtocolNum; +- memcpy(s->abProtocolDataStructure, ph->abProtocolDataStructure, len); +- s->ulProtocolDataStructureSize = len; +- DPRINTF(s, 1, "%s: using len %d\n", __func__, len); ++ s->bProtocolNum = protocol_num; ++ s->abProtocolDataStructure = ph->abProtocolDataStructure; + } + + /* + * must be 5 bytes for T=0, 7 bytes for T=1 + * See page 52 + */ +-static const uint8_t abDefaultProtocolDataStructure[7] = { +- 0x77, 0x00, 0x00, 0x00, 0x00, 0xfe /*IFSC*/, 0x00 /*NAD*/ }; ++static const CCID_ProtocolDataStructure defaultProtocolDataStructure = { ++ .t1 = { ++ .bmFindexDindex = 0x77, ++ .bmTCCKST1 = 0x00, ++ .bGuardTimeT1 = 0x00, ++ .bWaitingIntegerT1 = 0x00, ++ .bClockStop = 0x00, ++ .bIFSC = 0xfe, ++ .bNadValue = 0x00, ++ } ++}; + + static void ccid_reset_parameters(USBCCIDState *s) + { +- uint32_t len = sizeof(abDefaultProtocolDataStructure); +- + s->bProtocolNum = 1; /* T=1 */ +- s->ulProtocolDataStructureSize = len; +- memcpy(s->abProtocolDataStructure, abDefaultProtocolDataStructure, len); ++ s->abProtocolDataStructure = defaultProtocolDataStructure; + } + + /* NOTE: only a single slot is supported (SLOT_0) */ +@@ -1345,7 +1365,7 @@ static VMStateDescription ccid_vmstate = { + VMSTATE_UINT8(bError, USBCCIDState), + VMSTATE_UINT8(bmCommandStatus, USBCCIDState), + VMSTATE_UINT8(bProtocolNum, USBCCIDState), +- VMSTATE_BUFFER(abProtocolDataStructure, USBCCIDState), ++ VMSTATE_BUFFER(abProtocolDataStructure.data, USBCCIDState), + VMSTATE_UINT32(ulProtocolDataStructureSize, USBCCIDState), + VMSTATE_STRUCT_ARRAY(bulk_in_pending, USBCCIDState, + BULK_IN_PENDING_NUM, 1, bulk_in_vmstate, BulkIn), +-- +1.8.3.1 + diff --git a/0234-dev-smartcard-reader-change-default-protocol-to-T-0.patch b/0234-dev-smartcard-reader-change-default-protocol-to-T-0.patch new file mode 100644 index 0000000..05e11ea --- /dev/null +++ b/0234-dev-smartcard-reader-change-default-protocol-to-T-0.patch @@ -0,0 +1,50 @@ +From f7019fa4fc6d883f1922bb0e3b18ceb3a628b340 Mon Sep 17 00:00:00 2001 +From: Alon Levy +Date: Wed, 27 Mar 2013 10:14:15 +0200 +Subject: [PATCH 234/241] dev-smartcard-reader: change default protocol to T=0 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We don't support T=1 so we shouldn't advertise it by default. + +Two independent changes: +* Default ATR + sets T=0. This gets overwritten by the client provided ATR later. +* Class descriptor + changes dwAdvertise dwProtocols.PPPP to 0x1 and dwProtocols.RRRR=0 per spec. + +Signed-off-by: Alon Levy +Reviewed-by: Marc-André Lureau +(cherry picked from commit d7d218ef02d87c637d20d64da8f575d434ff6f78) +--- + hw/usb/dev-smartcard-reader.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c +index f2cab09..e97dfcb 100644 +--- a/hw/usb/dev-smartcard-reader.c ++++ b/hw/usb/dev-smartcard-reader.c +@@ -335,8 +335,8 @@ static const uint8_t qemu_ccid_descriptor[] = { + */ + 0x07, /* u8 bVoltageSupport; 01h - 5.0v, 02h - 3.0, 03 - 1.8 */ + +- 0x03, 0x00, /* u32 dwProtocols; RRRR PPPP. RRRR = 0000h.*/ +- 0x00, 0x00, /* PPPP: 0001h = Protocol T=0, 0002h = Protocol T=1 */ ++ 0x00, 0x00, /* u32 dwProtocols; RRRR PPPP. RRRR = 0000h.*/ ++ 0x01, 0x00, /* PPPP: 0001h = Protocol T=0, 0002h = Protocol T=1 */ + /* u32 dwDefaultClock; in kHZ (0x0fa0 is 4 MHz) */ + 0xa0, 0x0f, 0x00, 0x00, + /* u32 dwMaximumClock; */ +@@ -875,7 +875,7 @@ static const CCID_ProtocolDataStructure defaultProtocolDataStructure = { + + static void ccid_reset_parameters(USBCCIDState *s) + { +- s->bProtocolNum = 1; /* T=1 */ ++ s->bProtocolNum = 0; /* T=0 */ + s->abProtocolDataStructure = defaultProtocolDataStructure; + } + +-- +1.8.3.1 + diff --git a/0235-dev-smartcard-reader-copy-atr-protocol-to-ccid-param.patch b/0235-dev-smartcard-reader-copy-atr-protocol-to-ccid-param.patch new file mode 100644 index 0000000..e0be516 --- /dev/null +++ b/0235-dev-smartcard-reader-copy-atr-protocol-to-ccid-param.patch @@ -0,0 +1,85 @@ +From 2e26deacddb52bb3f7eb100ac5fe9709d6089cf3 Mon Sep 17 00:00:00 2001 +From: Alon Levy +Date: Mon, 4 Mar 2013 18:58:29 +0200 +Subject: [PATCH 235/241] dev-smartcard-reader: copy atr protocol to ccid + parameters +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Adds todos. + +Signed-off-by: Alon Levy +Reviewed-by: Marc-André Lureau +(cherry picked from commit 2f8f916b6d4482976bb5cf179f65aa2cfcd1aec9) +--- + hw/usb/dev-smartcard-reader.c | 45 +++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 45 insertions(+) + +diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c +index e97dfcb..4e08f9b 100644 +--- a/hw/usb/dev-smartcard-reader.c ++++ b/hw/usb/dev-smartcard-reader.c +@@ -833,14 +833,59 @@ static void ccid_write_data_block_answer(USBCCIDState *s, + ccid_write_data_block(s, slot, seq, data, len); + } + ++static uint8_t atr_get_protocol_num(const uint8_t *atr, uint32_t len) ++{ ++ int i; ++ ++ if (len < 2 || !(atr[1] & 0x80)) { ++ /* too short or TD1 not included */ ++ return 0; /* T=0, default */ ++ } ++ i = 1 + !!(atr[1] & 0x10) + !!(atr[1] & 0x20) + !!(atr[1] & 0x40); ++ i += !!(atr[1] & 0x80); ++ return atr[i] & 0x0f; ++} ++ + static void ccid_write_data_block_atr(USBCCIDState *s, CCID_Header *recv) + { + const uint8_t *atr = NULL; + uint32_t len = 0; ++ uint8_t atr_protocol_num; ++ CCID_T0ProtocolDataStructure *t0 = &s->abProtocolDataStructure.t0; ++ CCID_T1ProtocolDataStructure *t1 = &s->abProtocolDataStructure.t1; + + if (s->card) { + atr = ccid_card_get_atr(s->card, &len); + } ++ atr_protocol_num = atr_get_protocol_num(atr, len); ++ DPRINTF(s, D_VERBOSE, "%s: atr contains protocol=%d\n", __func__, ++ atr_protocol_num); ++ /* set parameters from ATR - see spec page 109 */ ++ s->bProtocolNum = (atr_protocol_num <= 1 ? atr_protocol_num ++ : s->bProtocolNum); ++ switch (atr_protocol_num) { ++ case 0: ++ /* TODO: unimplemented ATR T0 parameters */ ++ t0->bmFindexDindex = 0; ++ t0->bmTCCKST0 = 0; ++ t0->bGuardTimeT0 = 0; ++ t0->bWaitingIntegerT0 = 0; ++ t0->bClockStop = 0; ++ break; ++ case 1: ++ /* TODO: unimplemented ATR T1 parameters */ ++ t1->bmFindexDindex = 0; ++ t1->bmTCCKST1 = 0; ++ t1->bGuardTimeT1 = 0; ++ t1->bWaitingIntegerT1 = 0; ++ t1->bClockStop = 0; ++ t1->bIFSC = 0; ++ t1->bNadValue = 0; ++ break; ++ default: ++ DPRINTF(s, D_WARN, "%s: error: unsupported ATR protocol %d\n", ++ __func__, atr_protocol_num); ++ } + ccid_write_data_block(s, recv->bSlot, recv->bSeq, atr, len); + } + +-- +1.8.3.1 + diff --git a/0236-libcacard-vreader-add-debugging-messages-for-apdu.patch b/0236-libcacard-vreader-add-debugging-messages-for-apdu.patch new file mode 100644 index 0000000..20dffe4 --- /dev/null +++ b/0236-libcacard-vreader-add-debugging-messages-for-apdu.patch @@ -0,0 +1,169 @@ +From 71560a321c2c7678191f0f7da42f25917ed40974 Mon Sep 17 00:00:00 2001 +From: Alon Levy +Date: Tue, 5 Mar 2013 15:32:19 +0200 +Subject: [PATCH 236/241] libcacard/vreader: add debugging messages for apdu +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Using g_debug with log domain libcacard + +Signed-off-by: Alon Levy +Reviewed-by: Marc-André Lureau +(cherry picked from commit 7a6858962457c54be44715d6562504c765d9ea76) +--- + libcacard/cac.c | 7 ----- + libcacard/cac.h | 8 ++++++ + libcacard/vreader.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 85 insertions(+), 7 deletions(-) + +diff --git a/libcacard/cac.c b/libcacard/cac.c +index 927a4ca..5864539 100644 +--- a/libcacard/cac.c ++++ b/libcacard/cac.c +@@ -12,13 +12,6 @@ + #include "vcard_emul.h" + #include "card_7816.h" + +-#define CAC_GET_PROPERTIES 0x56 +-#define CAC_GET_ACR 0x4c +-#define CAC_READ_BUFFER 0x52 +-#define CAC_UPDATE_BUFFER 0x58 +-#define CAC_SIGN_DECRYPT 0x42 +-#define CAC_GET_CERTIFICATE 0x36 +- + /* private data for PKI applets */ + typedef struct CACPKIAppletDataStruct { + unsigned char *cert; +diff --git a/libcacard/cac.h b/libcacard/cac.h +index 15a61be..d24a2a8 100644 +--- a/libcacard/cac.h ++++ b/libcacard/cac.h +@@ -9,6 +9,14 @@ + #define CAC_H 1 + #include "vcard.h" + #include "vreader.h" ++ ++#define CAC_GET_PROPERTIES 0x56 ++#define CAC_GET_ACR 0x4c ++#define CAC_READ_BUFFER 0x52 ++#define CAC_UPDATE_BUFFER 0x58 ++#define CAC_SIGN_DECRYPT 0x42 ++#define CAC_GET_CERTIFICATE 0x36 ++ + /* + * Initialize the cac card. This is the only public function in this file. All + * the rest are connected through function pointers. +diff --git a/libcacard/vreader.c b/libcacard/vreader.c +index f3efc27..5793d73 100644 +--- a/libcacard/vreader.c ++++ b/libcacard/vreader.c +@@ -5,6 +5,12 @@ + * See the COPYING.LIB file in the top-level directory. + */ + ++#ifdef G_LOG_DOMAIN ++#undef G_LOG_DOMAIN ++#endif ++#define G_LOG_DOMAIN "libcacard" ++#include ++ + #include "qemu-common.h" + #include "qemu/thread.h" + +@@ -13,6 +19,9 @@ + #include "card_7816.h" + #include "vreader.h" + #include "vevent.h" ++#include "cac.h" /* just for debugging defines */ ++ ++#define LIBCACARD_LOG_DOMAIN "libcacard" + + struct VReaderStruct { + int reference_count; +@@ -24,6 +33,66 @@ struct VReaderStruct { + VReaderEmulFree reader_private_free; + }; + ++/* ++ * Debug helpers ++ */ ++ ++static const char * ++apdu_ins_to_string(int ins) ++{ ++ switch (ins) { ++ case VCARD7816_INS_MANAGE_CHANNEL: ++ return "manage channel"; ++ case VCARD7816_INS_EXTERNAL_AUTHENTICATE: ++ return "external authenticate"; ++ case VCARD7816_INS_GET_CHALLENGE: ++ return "get challenge"; ++ case VCARD7816_INS_INTERNAL_AUTHENTICATE: ++ return "internal authenticate"; ++ case VCARD7816_INS_ERASE_BINARY: ++ return "erase binary"; ++ case VCARD7816_INS_READ_BINARY: ++ return "read binary"; ++ case VCARD7816_INS_WRITE_BINARY: ++ return "write binary"; ++ case VCARD7816_INS_UPDATE_BINARY: ++ return "update binary"; ++ case VCARD7816_INS_READ_RECORD: ++ return "read record"; ++ case VCARD7816_INS_WRITE_RECORD: ++ return "write record"; ++ case VCARD7816_INS_UPDATE_RECORD: ++ return "update record"; ++ case VCARD7816_INS_APPEND_RECORD: ++ return "append record"; ++ case VCARD7816_INS_ENVELOPE: ++ return "envelope"; ++ case VCARD7816_INS_PUT_DATA: ++ return "put data"; ++ case VCARD7816_INS_GET_DATA: ++ return "get data"; ++ case VCARD7816_INS_SELECT_FILE: ++ return "select file"; ++ case VCARD7816_INS_VERIFY: ++ return "verify"; ++ case VCARD7816_INS_GET_RESPONSE: ++ return "get response"; ++ case CAC_GET_PROPERTIES: ++ return "get properties"; ++ case CAC_GET_ACR: ++ return "get acr"; ++ case CAC_READ_BUFFER: ++ return "read buffer"; ++ case CAC_UPDATE_BUFFER: ++ return "update buffer"; ++ case CAC_SIGN_DECRYPT: ++ return "sign decrypt"; ++ case CAC_GET_CERTIFICATE: ++ return "get certificate"; ++ } ++ return "unknown"; ++} ++ + /* manage locking */ + static inline void + vreader_lock(VReader *reader) +@@ -204,7 +273,15 @@ vreader_xfr_bytes(VReader *reader, + response = vcard_make_response(status); + card_status = VCARD_DONE; + } else { ++ g_debug("%s: CLS=0x%x,INS=0x%x,P1=0x%x,P2=0x%x,Lc=%d,Le=%d %s\n", ++ __func__, apdu->a_cla, apdu->a_ins, apdu->a_p1, apdu->a_p2, ++ apdu->a_Lc, apdu->a_Le, apdu_ins_to_string(apdu->a_ins)); + card_status = vcard_process_apdu(card, apdu, &response); ++ if (response) { ++ g_debug("%s: status=%d sw1=0x%x sw2=0x%x len=%d (total=%d)\n", ++ __func__, response->b_status, response->b_sw1, ++ response->b_sw2, response->b_len, response->b_total_len); ++ } + } + assert(card_status == VCARD_DONE); + if (card_status == VCARD_DONE) { +-- +1.8.3.1 + diff --git a/0237-libcacard-move-atr-setting-from-macro-to-function.patch b/0237-libcacard-move-atr-setting-from-macro-to-function.patch new file mode 100644 index 0000000..d622ae2 --- /dev/null +++ b/0237-libcacard-move-atr-setting-from-macro-to-function.patch @@ -0,0 +1,161 @@ +From 703a72f26668f26f2bb98851f1a2edd9a8681f86 Mon Sep 17 00:00:00 2001 +From: Alon Levy +Date: Tue, 5 Mar 2013 16:27:43 +0200 +Subject: [PATCH 237/241] libcacard: move atr setting from macro to function +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Only because qemu's checkpatch complains about it. + +Signed-off-by: Alon Levy +Reviewed-by: Marc-André Lureau +(cherry picked from commit 0b6a16c1a47b622b1a692ab179013d9e30e9cf3b) +--- + Makefile.objs | 1 + + libcacard/vcard_emul_nss.c | 14 +++++++++++--- + libcacard/vcardt.c | 40 ++++++++++++++++++++++++++++++++++++++++ + libcacard/vcardt.h | 13 ------------- + libcacard/vcardt_internal.h | 6 ++++++ + 5 files changed, 58 insertions(+), 16 deletions(-) + create mode 100644 libcacard/vcardt.c + create mode 100644 libcacard/vcardt_internal.h + +diff --git a/Makefile.objs b/Makefile.objs +index 3884790..729be2b 100644 +--- a/Makefile.objs ++++ b/Makefile.objs +@@ -32,6 +32,7 @@ libcacard-y += libcacard/vcard.o libcacard/vreader.o + libcacard-y += libcacard/vcard_emul_nss.o + libcacard-y += libcacard/vcard_emul_type.o + libcacard-y += libcacard/card_7816.o ++libcacard-y += libcacard/vcardt.o + + ###################################################################### + # Target independent part of system emulation. The long term path is to +diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c +index 9ba80fb..1a3e568 100644 +--- a/libcacard/vcard_emul_nss.c ++++ b/libcacard/vcard_emul_nss.c +@@ -33,6 +33,9 @@ + #include "vreader.h" + #include "vevent.h" + ++#include "libcacard/vcardt_internal.h" ++ ++ + typedef enum { + VCardEmulUnknown = -1, + VCardEmulFalse = 0, +@@ -519,18 +522,23 @@ vcard_emul_reader_get_slot(VReader *vreader) + } + + /* +- * Card ATR's map to physical cards. VCARD_ATR_PREFIX will set appropriate ++ * Card ATR's map to physical cards. vcard_alloc_atr will set appropriate + * historical bytes for any software emulated card. The remaining bytes can be + * used to indicate the actual emulator + */ +-static const unsigned char nss_atr[] = { VCARD_ATR_PREFIX(3), 'N', 'S', 'S' }; ++static unsigned char *nss_atr; ++static int nss_atr_len; + + void + vcard_emul_get_atr(VCard *card, unsigned char *atr, int *atr_len) + { +- int len = MIN(sizeof(nss_atr), *atr_len); ++ int len; + assert(atr != NULL); + ++ if (nss_atr == NULL) { ++ nss_atr = vcard_alloc_atr("NSS", &nss_atr_len); ++ } ++ len = MIN(nss_atr_len, *atr_len); + memcpy(atr, nss_atr, len); + *atr_len = len; + } +diff --git a/libcacard/vcardt.c b/libcacard/vcardt.c +new file mode 100644 +index 0000000..9ce4648 +--- /dev/null ++++ b/libcacard/vcardt.c +@@ -0,0 +1,40 @@ ++#include ++#include ++#include ++ ++#include "libcacard/vcardt.h" ++ ++#include "libcacard/vcardt_internal.h" ++ ++/* create an ATR with appropriate historical bytes */ ++#define ATR_TS_DIRECT_CONVENTION 0x3b ++#define ATR_TA_PRESENT 0x10 ++#define ATR_TB_PRESENT 0x20 ++#define ATR_TC_PRESENT 0x40 ++#define ATR_TD_PRESENT 0x80 ++ ++unsigned char *vcard_alloc_atr(const char *postfix, int *atr_len) ++{ ++ int postfix_len; ++ const char prefix[] = "VCARD_"; ++ const char default_postfix[] = "DEFAULT"; ++ const int prefix_len = sizeof(prefix) - 1; ++ int total_len; ++ unsigned char *atr; ++ ++ if (postfix == NULL) { ++ postfix = default_postfix; ++ } ++ postfix_len = strlen(postfix); ++ total_len = 3 + prefix_len + postfix_len; ++ atr = g_malloc(total_len); ++ atr[0] = ATR_TS_DIRECT_CONVENTION; ++ atr[1] = ATR_TD_PRESENT + prefix_len + postfix_len; ++ atr[2] = 0x00; ++ memcpy(&atr[3], prefix, prefix_len); ++ memcpy(&atr[3 + prefix_len], postfix, postfix_len); ++ if (atr_len) { ++ *atr_len = total_len; ++ } ++ return atr; ++} +diff --git a/libcacard/vcardt.h b/libcacard/vcardt.h +index 3b9a619..795e265 100644 +--- a/libcacard/vcardt.h ++++ b/libcacard/vcardt.h +@@ -25,19 +25,6 @@ typedef struct VCardEmulStruct VCardEmul; + + #define MAX_CHANNEL 4 + +-/* create an ATR with appropriate historical bytes */ +-#define TS_DIRECT_CONVENTION 0x3b +-#define TA_PRESENT 0x10 +-#define TB_PRESENT 0x20 +-#define TC_PRESENT 0x40 +-#define TD_PRESENT 0x80 +- +-#define VCARD_ATR_PREFIX(size) \ +- TS_DIRECT_CONVENTION, \ +- TD_PRESENT + (6 + size), \ +- 0x00, \ +- 'V', 'C', 'A', 'R', 'D', '_' +- + typedef enum { + VCARD_DONE, + VCARD_NEXT, +diff --git a/libcacard/vcardt_internal.h b/libcacard/vcardt_internal.h +new file mode 100644 +index 0000000..e5c8d2d +--- /dev/null ++++ b/libcacard/vcardt_internal.h +@@ -0,0 +1,6 @@ ++#ifndef VCARDT_INTERNAL_H ++#define VCARDT_INTERNAL_H ++ ++unsigned char *vcard_alloc_atr(const char *postfix, int *atr_len); ++ ++#endif +-- +1.8.3.1 + diff --git a/0238-dev-smartcard-reader-empty-implementation-for-Mechan.patch b/0238-dev-smartcard-reader-empty-implementation-for-Mechan.patch new file mode 100644 index 0000000..340a550 --- /dev/null +++ b/0238-dev-smartcard-reader-empty-implementation-for-Mechan.patch @@ -0,0 +1,34 @@ +From 002714edb70b00c20de7d54980a528ac7232bb33 Mon Sep 17 00:00:00 2001 +From: Alon Levy +Date: Tue, 5 Mar 2013 17:31:10 +0200 +Subject: [PATCH 238/241] dev-smartcard-reader: empty implementation for + Mechanical (fail correctly) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Alon Levy +Reviewed-by: Marc-André Lureau +(cherry picked from commit 58aeda15abb963196faaa4a0f23c5af45840f1b0) +--- + hw/usb/dev-smartcard-reader.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c +index 4e08f9b..a473b87 100644 +--- a/hw/usb/dev-smartcard-reader.c ++++ b/hw/usb/dev-smartcard-reader.c +@@ -1051,6 +1051,10 @@ static void ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p) + ccid_reset_error_status(s); + ccid_write_parameters(s, ccid_header); + break; ++ case CCID_MESSAGE_TYPE_PC_to_RDR_Mechanical: ++ ccid_report_error_failed(s, 0); ++ ccid_write_slot_status(s, ccid_header); ++ break; + default: + DPRINTF(s, 1, + "handle_data: ERROR: unhandled message type %Xh\n", +-- +1.8.3.1 + diff --git a/0239-libcacard-cac-change-big-switch-functions-to-single-.patch b/0239-libcacard-cac-change-big-switch-functions-to-single-.patch new file mode 100644 index 0000000..1d77761 --- /dev/null +++ b/0239-libcacard-cac-change-big-switch-functions-to-single-.patch @@ -0,0 +1,209 @@ +From 8527c47117c0ec6d12929b6c19206eed6ee90528 Mon Sep 17 00:00:00 2001 +From: Alon Levy +Date: Mon, 4 Mar 2013 21:43:36 +0200 +Subject: [PATCH 239/241] libcacard/cac: change big switch functions to single + return point +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Alon Levy +Reviewed-by: Marc-André Lureau +(cherry picked from commit 57f97834efe0c208ffadc9d2959f3d3d55580e52) +--- + libcacard/cac.c | 73 ++++++++++++++++++++++++++++++++++++++++----------------- + 1 file changed, 52 insertions(+), 21 deletions(-) + +diff --git a/libcacard/cac.c b/libcacard/cac.c +index 5864539..7a06b5a 100644 +--- a/libcacard/cac.c ++++ b/libcacard/cac.c +@@ -40,41 +40,51 @@ static VCardStatus + cac_common_process_apdu(VCard *card, VCardAPDU *apdu, VCardResponse **response) + { + int ef; ++ VCardStatus ret = VCARD_FAIL; + + switch (apdu->a_ins) { + case VCARD7816_INS_SELECT_FILE: + if (apdu->a_p1 != 0x02) { + /* let the 7816 code handle applet switches */ +- return VCARD_NEXT; ++ ret = VCARD_NEXT; ++ break; + } + /* handle file id setting */ + if (apdu->a_Lc != 2) { + *response = vcard_make_response( + VCARD7816_STATUS_ERROR_DATA_INVALID); +- return VCARD_DONE; ++ ret = VCARD_DONE; ++ break; + } + /* CAC 1.0 only supports ef = 0 */ + ef = apdu->a_body[0] | (apdu->a_body[1] << 8); + if (ef != 0) { + *response = vcard_make_response( + VCARD7816_STATUS_ERROR_FILE_NOT_FOUND); +- return VCARD_DONE; ++ ret = VCARD_DONE; ++ break; + } + *response = vcard_make_response(VCARD7816_STATUS_SUCCESS); +- return VCARD_DONE; ++ ret = VCARD_DONE; ++ break; + case VCARD7816_INS_GET_RESPONSE: + case VCARD7816_INS_VERIFY: + /* let the 7816 code handle these */ +- return VCARD_NEXT; ++ ret = VCARD_NEXT; ++ break; + case CAC_GET_PROPERTIES: + case CAC_GET_ACR: + /* skip these for now, this will probably be needed */ + *response = vcard_make_response(VCARD7816_STATUS_ERROR_P1_P2_INCORRECT); +- return VCARD_DONE; ++ ret = VCARD_DONE; ++ break; ++ default: ++ *response = vcard_make_response( ++ VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED); ++ ret = VCARD_DONE; ++ break; + } +- *response = vcard_make_response( +- VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED); +- return VCARD_DONE; ++ return ret; + } + + /* +@@ -108,6 +118,7 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu, + int size, next; + unsigned char *sign_buffer; + vcard_7816_status_t status; ++ VCardStatus ret = VCARD_FAIL; + + applet_private = vcard_get_current_applet_private(card, apdu->a_channel); + assert(applet_private); +@@ -117,7 +128,8 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu, + case CAC_UPDATE_BUFFER: + *response = vcard_make_response( + VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED); +- return VCARD_DONE; ++ ret = VCARD_DONE; ++ break; + case CAC_GET_CERTIFICATE: + if ((apdu->a_p2 != 0) || (apdu->a_p1 != 0)) { + *response = vcard_make_response( +@@ -147,7 +159,8 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu, + *response = vcard_make_response( + VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE); + } +- return VCARD_DONE; ++ ret = VCARD_DONE; ++ break; + case CAC_SIGN_DECRYPT: + if (apdu->a_p2 != 0) { + *response = vcard_make_response( +@@ -164,7 +177,8 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu, + pki_applet->sign_buffer_len = 0; + *response = vcard_make_response( + VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE); +- return VCARD_DONE; ++ ret = VCARD_DONE; ++ break; + } + memcpy(sign_buffer+pki_applet->sign_buffer_len, apdu->a_body, size); + size += pki_applet->sign_buffer_len; +@@ -175,7 +189,8 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu, + pki_applet->sign_buffer = sign_buffer; + pki_applet->sign_buffer_len = size; + *response = vcard_make_response(VCARD7816_STATUS_SUCCESS); +- return VCARD_DONE; ++ ret = VCARD_DONE; ++ break; + case 0x00: + /* we now have the whole buffer, do the operation, result will be + * in the sign_buffer */ +@@ -200,15 +215,20 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu, + g_free(sign_buffer); + pki_applet->sign_buffer = NULL; + pki_applet->sign_buffer_len = 0; +- return VCARD_DONE; ++ ret = VCARD_DONE; ++ break; + case CAC_READ_BUFFER: + /* new CAC call, go ahead and use the old version for now */ + /* TODO: implement */ + *response = vcard_make_response( + VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED); +- return VCARD_DONE; ++ ret = VCARD_DONE; ++ break; ++ default: ++ ret = cac_common_process_apdu(card, apdu, response); ++ break; + } +- return cac_common_process_apdu(card, apdu, response); ++ return ret; + } + + +@@ -216,19 +236,26 @@ static VCardStatus + cac_applet_id_process_apdu(VCard *card, VCardAPDU *apdu, + VCardResponse **response) + { ++ VCardStatus ret = VCARD_FAIL; ++ + switch (apdu->a_ins) { + case CAC_UPDATE_BUFFER: + *response = vcard_make_response( + VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED); +- return VCARD_DONE; ++ ret = VCARD_DONE; ++ break; + case CAC_READ_BUFFER: + /* new CAC call, go ahead and use the old version for now */ + /* TODO: implement */ + *response = vcard_make_response( + VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED); +- return VCARD_DONE; ++ ret = VCARD_DONE; ++ break; ++ default: ++ ret = cac_common_process_apdu(card, apdu, response); ++ break; + } +- return cac_common_process_apdu(card, apdu, response); ++ return ret; + } + + +@@ -240,16 +267,20 @@ static VCardStatus + cac_applet_container_process_apdu(VCard *card, VCardAPDU *apdu, + VCardResponse **response) + { ++ VCardStatus ret = VCARD_FAIL; ++ + switch (apdu->a_ins) { + case CAC_READ_BUFFER: + case CAC_UPDATE_BUFFER: + *response = vcard_make_response( + VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED); +- return VCARD_DONE; ++ ret = VCARD_DONE; ++ break; + default: ++ ret = cac_common_process_apdu(card, apdu, response); + break; + } +- return cac_common_process_apdu(card, apdu, response); ++ return ret; + } + + /* +-- +1.8.3.1 + diff --git a/0240-libcacard-vscclient-fix-leakage-of-socket-on-error-p.patch b/0240-libcacard-vscclient-fix-leakage-of-socket-on-error-p.patch new file mode 100644 index 0000000..b23df89 --- /dev/null +++ b/0240-libcacard-vscclient-fix-leakage-of-socket-on-error-p.patch @@ -0,0 +1,55 @@ +From aae98aa5aa23dbddf3a6e8c8c0399948f0d43480 Mon Sep 17 00:00:00 2001 +From: Alon Levy +Date: Tue, 4 Jun 2013 16:23:37 -0400 +Subject: [PATCH 240/241] libcacard/vscclient: fix leakage of socket on error + paths + +Spotted by Coverity. + +Signed-off-by: Alon Levy +Reviewed-by: Peter Maydell +Signed-off-by: Michael Tokarev +(cherry picked from commit 581fe784c3adf85dc167a47a4a60fd1245a98217) +--- + libcacard/vscclient.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/libcacard/vscclient.c b/libcacard/vscclient.c +index ac23647..5180d29 100644 +--- a/libcacard/vscclient.c ++++ b/libcacard/vscclient.c +@@ -618,18 +618,22 @@ connect_to_qemu( + if (ret != 0) { + /* Error */ + fprintf(stderr, "getaddrinfo failed\n"); +- return -1; ++ goto cleanup_socket; + } + + if (connect(sock, server->ai_addr, server->ai_addrlen) < 0) { + /* Error */ + fprintf(stderr, "Could not connect\n"); +- return -1; ++ goto cleanup_socket; + } + if (verbose) { + printf("Connected (sizeof Header=%zd)!\n", sizeof(VSCMsgHeader)); + } + return sock; ++ ++cleanup_socket: ++ closesocket(sock); ++ return -1; + } + + int +@@ -759,5 +763,6 @@ main( + g_io_channel_unref(channel_socket); + g_byte_array_unref(socket_to_send); + ++ closesocket(sock); + return 0; + } +-- +1.8.3.1 + diff --git a/0241-libcacard-Fix-cppcheck-warning-and-remove-unneeded-c.patch b/0241-libcacard-Fix-cppcheck-warning-and-remove-unneeded-c.patch new file mode 100644 index 0000000..06965b0 --- /dev/null +++ b/0241-libcacard-Fix-cppcheck-warning-and-remove-unneeded-c.patch @@ -0,0 +1,89 @@ +From 742e78d849a701e49f3c7d3c13eb9c4013f2cec3 Mon Sep 17 00:00:00 2001 +From: Stefan Weil +Date: Sun, 16 Jun 2013 11:08:52 +0200 +Subject: [PATCH 241/241] libcacard: Fix cppcheck warning and remove unneeded + code + +The local function vcard_emul_alloc_arrays always returned PR_TRUE. +Therefore cppcheck complained about code which handled the +non-existent PR_FALSE case. + +Remove the function's return value and the dead code. + +Signed-off-by: Stefan Weil +Signed-off-by: Michael Tokarev +(cherry picked from commit 48f0475f813dfa5ceb0e1f10c2ac3f28a8af583b) +--- + libcacard/vcard_emul_nss.c | 22 ++++++---------------- + 1 file changed, 6 insertions(+), 16 deletions(-) + +diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c +index 1a3e568..fb429b1 100644 +--- a/libcacard/vcard_emul_nss.c ++++ b/libcacard/vcard_emul_nss.c +@@ -90,17 +90,13 @@ static int nss_emul_init; + /* + * allocate the set of arrays for certs, cert_len, key + */ +-static PRBool ++static void + vcard_emul_alloc_arrays(unsigned char ***certsp, int **cert_lenp, + VCardKey ***keysp, int cert_count) + { +- *certsp = NULL; +- *cert_lenp = NULL; +- *keysp = NULL; + *certsp = (unsigned char **)g_malloc(sizeof(unsigned char *)*cert_count); + *cert_lenp = (int *)g_malloc(sizeof(int)*cert_count); + *keysp = (VCardKey **)g_malloc(sizeof(VCardKey *)*cert_count); +- return PR_TRUE; + } + + /* +@@ -601,7 +597,6 @@ vcard_emul_mirror_card(VReader *vreader) + int *cert_len; + VCardKey **keys; + PK11SlotInfo *slot; +- PRBool ret; + VCard *card; + + slot = vcard_emul_reader_get_slot(vreader); +@@ -627,10 +622,7 @@ vcard_emul_mirror_card(VReader *vreader) + } + + /* allocate the arrays */ +- ret = vcard_emul_alloc_arrays(&certs, &cert_len, &keys, cert_count); +- if (ret == PR_FALSE) { +- return NULL; +- } ++ vcard_emul_alloc_arrays(&certs, &cert_len, &keys, cert_count); + + /* fill in the arrays */ + cert_count = 0; +@@ -878,7 +870,7 @@ VCardEmulError + vcard_emul_init(const VCardEmulOptions *options) + { + SECStatus rv; +- PRBool ret, has_readers = PR_FALSE; ++ PRBool has_readers = PR_FALSE; + VReader *vreader; + VReaderEmul *vreader_emul; + SECMODListLock *module_lock; +@@ -944,11 +936,9 @@ vcard_emul_init(const VCardEmulOptions *options) + vreader_add_reader(vreader); + cert_count = options->vreader[i].cert_count; + +- ret = vcard_emul_alloc_arrays(&certs, &cert_len, &keys, +- options->vreader[i].cert_count); +- if (ret == PR_FALSE) { +- continue; +- } ++ vcard_emul_alloc_arrays(&certs, &cert_len, &keys, ++ options->vreader[i].cert_count); ++ + cert_count = 0; + for (j = 0; j < options->vreader[i].cert_count; j++) { + /* we should have a better way of identifying certs than by +-- +1.8.3.1 + diff --git a/qemu.spec b/qemu.spec index e3d4256..6d9caed 100644 --- a/qemu.spec +++ b/qemu.spec @@ -131,7 +131,7 @@ Summary: QEMU is a FAST! processor emulator Name: qemu Version: 1.4.2 -Release: 6%{?dist} +Release: 7%{?dist} # Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped Epoch: 2 License: GPLv2+ and LGPLv2+ and BSD @@ -254,6 +254,39 @@ Patch0209: 0209-Fix-usage-of-USB_DEV_FLAG_IS_HOST-flag.patch # Fix crash when adding spice vdagent channel in the guest (bz #969084) Patch0210: 0210-qxl-Fix-QXLRam-initialisation.patch +# 917860 related libcacard and qemu/hw/ccid windows 7 smartcard support. +Patch0211: 0211-qemu-socket-Make-socket_optslist-public.patch +Patch0212: 0212-libcacard-correct-T0-historical-bytes-size.patch +Patch0213: 0213-ccid-card-emul-do-not-crash-if-backend-is-not-provid.patch +Patch0214: 0214-ccid-make-backend_enum_table-static-const-and-adjust.patch +Patch0215: 0215-ccid-declare-DEFAULT_ATR-table-to-be-static-const.patch +Patch0216: 0216-libcacard-use-system-config-directory-for-nss-db-on-.patch +Patch0217: 0217-util-move-socket_init-to-osdep.c.patch +Patch0218: 0218-build-sys-must-link-with-fstack-protector.patch +Patch0219: 0219-libcacard-fix-mingw64-cross-compilation.patch +Patch0220: 0220-libcacard-split-vscclient-main-from-socket-reading.patch +Patch0221: 0221-libcacard-vscclient-to-use-QemuThread-for-portabilit.patch +Patch0222: 0222-libcacard-teach-vscclient-to-use-GMainLoop-for-porta.patch +Patch0223: 0223-libcacard-remove-sql-prefix.patch +Patch0224: 0224-libcacard-remove-default-libcoolkey-loading.patch +Patch0225: 0225-dev-smartcard-reader-white-space-fixes.patch +Patch0226: 0226-dev-smartcard-reader-nicer-debug-messages.patch +Patch0227: 0227-dev-smartcard-reader-remove-aborts-never-triggered-b.patch +Patch0228: 0228-dev-smartcard-reader-support-windows-guest.patch +Patch0229: 0229-dev-smartcard-reader-reuse-usb.h-definitions.patch +Patch0230: 0230-libcacard-change-default-ATR.patch +Patch0231: 0231-ccid-card-passthru-add-atr-check.patch +Patch0232: 0232-ccid-card-passthru-dev-smartcard-reader-add-debug-en.patch +Patch0233: 0233-dev-smartcard-reader-define-structs-for-CCID_Paramet.patch +Patch0234: 0234-dev-smartcard-reader-change-default-protocol-to-T-0.patch +Patch0235: 0235-dev-smartcard-reader-copy-atr-protocol-to-ccid-param.patch +Patch0236: 0236-libcacard-vreader-add-debugging-messages-for-apdu.patch +Patch0237: 0237-libcacard-move-atr-setting-from-macro-to-function.patch +Patch0238: 0238-dev-smartcard-reader-empty-implementation-for-Mechan.patch +Patch0239: 0239-libcacard-cac-change-big-switch-functions-to-single-.patch +Patch0240: 0240-libcacard-vscclient-fix-leakage-of-socket-on-error-p.patch +Patch0241: 0241-libcacard-Fix-cppcheck-warning-and-remove-unneeded-c.patch + BuildRequires: SDL-devel BuildRequires: zlib-devel BuildRequires: which @@ -796,6 +829,39 @@ CAC emulation development files. # Fix crash when adding spice vdagent channel in the guest (bz #969084) %patch0210 -p1 +# 917860 libcacard and qemu/hw/ccid windows 7 smartcard support. +%patch0211 -p1 +%patch0212 -p1 +%patch0213 -p1 +%patch0214 -p1 +%patch0215 -p1 +%patch0216 -p1 +%patch0217 -p1 +%patch0218 -p1 +%patch0219 -p1 +%patch0220 -p1 +%patch0221 -p1 +%patch0222 -p1 +%patch0223 -p1 +%patch0224 -p1 +%patch0225 -p1 +%patch0226 -p1 +%patch0227 -p1 +%patch0228 -p1 +%patch0229 -p1 +%patch0230 -p1 +%patch0231 -p1 +%patch0232 -p1 +%patch0233 -p1 +%patch0234 -p1 +%patch0235 -p1 +%patch0236 -p1 +%patch0237 -p1 +%patch0238 -p1 +%patch0239 -p1 +%patch0240 -p1 +%patch0241 -p1 + %build %if %{with kvmonly} buildarch="%{kvm_target}-softmmu" @@ -1441,6 +1507,9 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Sun Aug 18 2013 Alon Levy - 2:1.4.2-7 +- Support windows 7 smartcard using guests and clients - (bz #917860 rhel 6.5) + * Thu Aug 01 2013 Cole Robinson - 2:1.4.2-6 - Fix crash when adding spice vdagent channel in the guest (bz #969084)