This patch adds the configure option --enable-smartcard, adds hw/usb-ccid.c to Makefile.objs, and adds the documentation. Only an empty hw/usb-ccid.c is provided (couldn't add an empty file so added initial comment only).
Signed-off-by: Alon Levy <al...@redhat.com> --- Makefile.objs | 1 + configure | 12 +++++ docs/usb-ccid.txt | 115 ++++++++++++++++++++++++++++++++++++++++++++++++ hw/usb-ccid.c | 13 ++++++ hw/vscard_common.h | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 264 insertions(+), 0 deletions(-) create mode 100644 docs/usb-ccid.txt create mode 100644 hw/usb-ccid.c create mode 100644 hw/vscard_common.h diff --git a/Makefile.objs b/Makefile.objs index 9c13bb3..4b581e7 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -170,6 +170,7 @@ hw-obj-$(CONFIG_FDC) += fdc.o hw-obj-$(CONFIG_ACPI) += acpi.o acpi_piix4.o hw-obj-$(CONFIG_APM) += pm_smbus.o apm.o hw-obj-$(CONFIG_DMA) += dma.o +hw-obj-$(CONFIG_SMARTCARD) += usb-ccid.o # PPC devices hw-obj-$(CONFIG_OPENPIC) += openpic.o diff --git a/configure b/configure index e0d34fd..fc59a40 100755 --- a/configure +++ b/configure @@ -327,6 +327,7 @@ user_pie="no" zero_malloc="" trace_backend="nop" trace_file="trace" +smartcard="no" # OS specific if check_define __linux__ ; then @@ -730,6 +731,10 @@ for opt do ;; --enable-vhost-net) vhost_net="yes" ;; + --disable-smartcard) smartcard="no" + ;; + --enable-smartcard) smartcard="yes" + ;; --*dir) ;; *) echo "ERROR: unknown option $opt"; show_help="yes" @@ -921,6 +926,8 @@ echo " --enable-vhost-net enable vhost-net acceleration support" echo " --trace-backend=B Trace backend nop simple ust" echo " --trace-file=NAME Full PATH,NAME of file to store traces" echo " Default:trace-<pid>" +echo " --disable-smartcard disable smartcard support" +echo " --enable-smartcard enable smartcard support" echo "" echo "NOTE: The object files are built at the place where configure is launched" exit 1 @@ -2285,6 +2292,7 @@ echo "uuid support $uuid" echo "vhost-net support $vhost_net" echo "Trace backend $trace_backend" echo "Trace output file $trace_file-<pid>" +echo "smartcard support $smartcard" if test $sdl_too_old = "yes"; then echo "-> Your SDL version is too old - please upgrade to have SDL support" @@ -2540,6 +2548,10 @@ if test "$posix_madvise" = "yes" ; then echo "CONFIG_POSIX_MADVISE=y" >> $config_host_mak fi +if test "$smartcard" = "yes" ; then + echo "CONFIG_SMARTCARD=y" >> $config_host_mak +fi + # XXX: suppress that if [ "$bsd" = "yes" ] ; then echo "CONFIG_BSD=y" >> $config_host_mak diff --git a/docs/usb-ccid.txt b/docs/usb-ccid.txt new file mode 100644 index 0000000..e418456 --- /dev/null +++ b/docs/usb-ccid.txt @@ -0,0 +1,115 @@ +Contents +1. What is the USB CCID device? +2. What is it the CCID used for? +3. How can I remote my smart card reader to the guest? +4. How do I emulate a smart card using certificates? +5. Build instructions for qemu with usb-ccid and libcaccard +6. How does it work? + +1. What is the USB CCID device? + +The USB CCID device is a USB device implementing the CCID specification, which lets one connect smart card readers that implement the same spec. For more information see the specification: + + Universal Serial Bus + Device Class: Smart Card + CCID + Specification for + Integrated Circuit(s) Cards Interface Devices + Revision 1.1 + April 22rd, 2005 + +2. What is the CCID used for? + +Smartcard are used for authentication, single sign on, decryption in +public/private schemes and digital signatures. A smartcard reader on the client +cannot be used on a guest with simple usb passthrough since it will then not be +available on the client, possibly locking the computer when it is "removed". On +the other hand this device can let you use the smartcard on both the client and +the guest machine. It is also possible to have a completely virtual smart card +reader and smart card (i.e. not backed by a physical device) using this device. + +3. How do I remote a smartcard reader to the guest? + +After following the building instructions for qemu and vscclient run vscclient on the client machine (the one with the smart card reader) and qemu on another (possibly the same) machine like this: + +Assume we use port 2001 on the qemu machine, which we call qemuhost: + +on qemuhost: (run this first, qemu acts as the server) + + qemu -chardev socket,server,host=0.0.0.0,port=2001,id=ccid,nowait -usb -device usb-ccid,chardev=ccid + +on client: + + vscclient qemuhost 2001 + +4. How do I emulate a smartcard using certificates? + +qmeu side doesn't change. + +on client side: +create the certificates. vscclient uses libcac_card, which currently uses +NSS as the backend. To create some self signed certificates using nss: + + certutil -d /etc/pki/nssdb -x -t "CT,CT,CT" -S -s "CN=cert1" -n cert1 + +Note: three certificates are the maximum the emulated card will take. + +Then run vscclient with the local certificates: +(Note: vscclient command line interface is in a state of change) + + ./vscclient -e "db=\"/etc/pki/nssdb\" use_hw=no soft=(,Test,CAC,,cert1,cert2,cert3)" localhost 2001 + + +5. Build instructions for qemu with usb-ccid and libcaccard + +prerequisites: +clone libcaccard (there are no binary or source releases at this time): +git clone git://anongit.freedesktop.org/~alon/cac_card + +fedora: + yum install nss-devel +ubuntu: + apt-get install libnss3-dev + (not tested on ubuntu) + +build cac_card: + cd cac_card + ./configure && make && sudo make install + +qemu: + ./configure --enable-smartcard && make + +Note that if you install to a non default prefix you need to set +PKG_CONFIG_PATH to compile qemu successfully. + +6. How does it work? + +usb-ccid is a usb device. It defaults to an unattached usb device on startup. +usb-ccid expects a chardev and expects the protocol defined in cac_card/vscard_common.h to be passed over that. +A typical interchange is: + +client event vscclient usb-ccid guest event + + VSC_Init + VSC_ReaderAdd + sees new usb device. +card inserted + VSC_ATR + some guest operation on the card + VSC_APDU + VSC_APDU + [APDU<->APDU repeats several times] +card removed + VSC_CardRemove +kill/quit vscclient + VSC_ReaderRemove + usb device removed. + + +vscclient implements a completely virtual CAC (DoD standard for smart cards) +compliant card and uses NSS to actually retrive certificates and do any +encryption using the backend (real reader + card or file backed certificates +and on pc encryption). + +For documentation of cac_card see README in libcac_card package. + diff --git a/hw/usb-ccid.c b/hw/usb-ccid.c new file mode 100644 index 0000000..98805bb --- /dev/null +++ b/hw/usb-ccid.c @@ -0,0 +1,13 @@ +/* + * CCID Device emulation + * + * Based on usb-serial.c: + * Copyright (c) 2006 CodeSourcery. + * Copyright (c) 2008 Samuel Thibault <samuel.thiba...@ens-lyon.org> + * Written by Paul Brook, reused for FTDI by Samuel Thibault, + * reused for CCID by Alon Levy. + * Copyright (c) 2010 Red Hat. + * + * This code is licenced under the LGPL. + */ + diff --git a/hw/vscard_common.h b/hw/vscard_common.h new file mode 100644 index 0000000..7966258 --- /dev/null +++ b/hw/vscard_common.h @@ -0,0 +1,123 @@ +/* Virtual Smart Card protocol definition + * + * This protocol is between a host implementing a group of virtual smart card + * reader, and a client implementing a virtual smart card, or passthrough to + * a real card. + * + * The current implementation passes the raw APDU's from 7816 and additionally + * contains messages to setup and teardown readers, handle insertion and + * removal of cards, negotiate the protocol and provide for error responses. + * + * Copyright (c) 2010 Red Hat. + * + * This code is licensed under the LGPL. + */ + +#ifndef _VSCARD_COMMON_H +#define _VSCARD_COMMON_H + +#include <stdint.h> + +#define VERSION_MAJOR_BITS 11 +#define VERSION_MIDDLE_BITS 11 +#define VERSION_MINOR_BITS 10 + +#define MAKE_VERSION(major, middle, minor) \ + ( (major << (VERSION_MINOR_BITS + VERSION_MIDDLE_BITS)) \ + | (middle << VERSION_MINOR_BITS) \ + | (minor) ) + +/** IMPORTANT NOTE on VERSION + * + * The version below MUST be changed whenever a change in this file is made. + * + * The last digit, the minor, is for bug fix changes only. + * + * The middle digit is for backward / forward compatible changes, updates + * to the existing messages, addition of fields. + * + * The major digit is for a breaking change of protocol, presumably + * something that cannot be accomodated with the existing protocol. + */ + +#define VSCARD_VERSION MAKE_VERSION(0,0,1) + +#define VSCARD_UNDEFINED_READER_ID -1 +#define VSCARD_MINIMAL_READER_ID 0 + +typedef enum { + VSC_Init, + VSC_Error, + VSC_ReaderAdd, + VSC_ReaderAddResponse, + VSC_ReaderRemove, + VSC_ATR, + VSC_CardRemove, + VSC_APDU +} VSCMsgType; + +typedef enum { + VSC_GENERAL_ERROR=1, + VSC_CANNOT_ADD_MORE_READERS, +} VSCErrorCode; + +typedef uint32_t reader_id_t; + +typedef struct VSCMsgHeader { + VSCMsgType type; + reader_id_t reader_id; + uint32_t length; + uint8_t data[0]; +} VSCMsgHeader; + +/* VSCMsgInit Client <-> Host + * Host replies with allocated reader id in ReaderAddResponse + * */ +typedef struct VSCMsgInit { + uint32_t version; +} VSCMsgInit; + +/* VSCMsgError Client <-> Host + * */ +typedef struct VSCMsgError { + uint32_t code; +} VSCMsgError; + +/* VSCMsgReaderAdd Client -> Host + * Host replies with allocated reader id in ReaderAddResponse + * name - name of the reader on client side. + * */ +typedef struct VSCMsgReaderAdd { + uint8_t name[0]; +} VSCMsgReaderAdd; + +/* VSCMsgReaderAddResponse Host -> Client + * Reply to ReaderAdd + * */ +typedef struct VSCMsgReaderAddResponse { +} VSCMsgReaderAddResponse; + +/* VSCMsgReaderRemove Client -> Host + * */ +typedef struct VSCMsgReaderRemove { +} VSCMsgReaderRemove; + +/* VSCMsgATR Client -> Host + * Answer to reset. Sent for card insertion or card reset. + * */ +typedef struct VSCMsgATR { + uint8_t atr[0]; +} VSCMsgATR; + +/* VSCMsgCardRemove Client -> Host + * */ +typedef struct VSCMsgCardRemove { +} VSCMsgCardRemove; + +/* VSCMsgAPDU Client <-> Host + * */ +typedef struct VSCMsgAPDU { + uint8_t data[0]; +} VSCMsgAPDU; + +#endif -- 1.7.3.1