Patchwork [1/2] usb-ccid: add CCID device. add configure option.

login
register
mail settings
Submitter Alon Levy
Date Oct. 5, 2010, 9:32 p.m.
Message ID <1286314380-23653-2-git-send-email-alevy@redhat.com>
Download mbox | patch
Permalink /patch/66871/
State New
Headers show

Comments

Alon Levy - Oct. 5, 2010, 9:32 p.m.
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 <alevy@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

Patch

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.thibault@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