Accessing the Cambridge University Smartcard from Linux

Jon Warbrick
University of Cambridge Computing Service

These are some notes on my experience in getting Linux to communicate with the University Smartcard, together with assorted links and background information. The object of the exercise is partly to gain familiarity with the technology, but also to investigate the possibility of using the smartcard to provide authentication services to OpenSSL.

My conclusions to date is that Linux smartcard support is flaky at best, and there is little that works 'out of the box'. However it is clear that the technology can be made to work under some circumstances. I suspect that this is because, while the various elements (cards, readers, interface software) are well standardized, these standards are complex and rarely completely and correctly implemented. As a result a particular combination of card, reader and software may work for a particular application (perhaps after considerable work) but an arbitrary choice of components may be problematic.

Smartcard background

The behavior of smartcards incorporating CPU chips, such as the Cambridge card, is defined in ISO7816 (and some other standards). There is a summary of parts 1-3 of the standard (covering Physical characteristics, Dimensions and location of the contacts, and Electronic signals and transmission protocols) at http://www.geocities.com/ResearchTriangle/Lab/1578/iso7816.txt, and what looks like a bad OCR of part 4 (Interindustry command for interchange) at http://www.geocities.com/ResearchTriangle/Lab/1578/iso78164.htm. Probably a better general reference work is Smart Card Handbook, Wolfgang Rankl and Wolfgang Effing, 2nd Edition, John Wiley and Sons Ltd; ISBN: 0471988758. Unfortunately it's both big and expensive.

In essence, a card and card reader communicate using a byte orientated serial protocol. The reader sends a command along with parameters and optional data, and the card replies with a status indication and optional reply data. Documents commonly refers to these commands as APDUs (Application Protocol Data Units). These commands are defined in ISO7861 part 4, and there is a useful summary of the commands that the Cambridge card accepts at http://smartcard.caret.cam.ac.uk/MFC-APDU.html. Understanding these APDUs is important, since most of the programming APIs provide, in essence, a means of sending APDUs to the card and of retrieving the responses.

ISO7816 cards implement permanent data storage as a tree-like 'file system'. Nodes in the tree are either 'Dedicated Files' (DF), which roughly correspond to directories, or 'Elementary Files' (EF) containing actual data. Nodes are identified by two byte 'file identifiers', and the root of the structure is a DF called the 'Master File' (MF) with file identifier '0x3f00'. There is a useful diagram showing this (for a different card from the Cambridge one) at http://www.citi.umich.edu/projects/smartcard/smartcard_seminar/6.html. Commands exist for navigating this tree, retrieving and setting data values, etc. There are also commands for non-file relate actions such as key retrieval, data signing, etc. Files can also have access controls applied to them. These can, for example, require that a particular PIN be supplied to the card before a particular file can be accessed.

There appears to be little standardization of what various 'files' are used for, leaving such definition up to each smartcard application. The files used on the Cambridge card are documented at http://smartcard.caret.cam.ac.uk/card-files.html. [Note that 'sfi' as shown in this list is a 'short file identifier' that provides direct access to selected files].

Card access APIs

Card readers interface with cards as described above, and interface with computers over RS323 serial lines, USB, PCMCIA, etc. There is no standardization of this interface (except sometimes within one manufacturer's products). To avoid making programs reader-dependent, it is usual to implement a reader-dependent driver that exposes a reader-independent programming API.

Under Windows, the 'winscard' interface provides such an API, and is supported by operating system services and device drivers. winscard is 'standardized' by the PC/SC Workgroup, http://www.pcscworkgroup.com/, and the API is commonly referred to as PC/SC (Personal Computer/Smart Card).

Under Linux, a cut-down version of PC/SC called PCSC-Lite has been implemented by the MUSCLE (Movement for the Use of Smartcards in a Linux Environment) project. PCSC-Lite consists of a user-callable library (libpcsclite) which implements the PC/SC interface - see http://www.linuxnet.com/documentation/files/pcsc-lite-0.7.3.pdf. This communicates over a Unix domain socket with a daemon (pcscd), which in turn talks to one or more card readers using 'IFD' drivers. These drivers are shared libraries loaded by pcscd as required; their specification is at http://linuxnet.com/documentation/files/ifdhandler20.pdf. Note that, while I have been unable to find any documentation for this, there appear to be two versions of the IFD specification: version one that used routines with names beginning 'IO_' and 'IFD_', and version two that uses routines beginning 'IFD'. pcscd is able to use drivers based on either version.

An alternative API is provided by the sc7816 library developed by the Centre for Information Technology Integration at the University of Michigan - see http://www.citi.umich.edu/projects/smartcard/sc7816.html. This uses the same IFD drivers as pcscd, though has apparently only been tested with Michigan's own driver for the Todos Argos Mini reader. It also appears to only support IFD version 1 drivers. A number of utility programs are available that work against this interface, though much of the work is based on Java-capable cards, which ours isn't. Note that with this interface the serial port (or other interface) connecting the card reader must be accessible by the id under which the client program runs; using pscd it's only necessary for the port to be accessible by the id under which the daemon runs.

Yet an other API is provided by SCEZ: http://www.franken.de/crypt/scez.html. This uses either Muscle IFD drivers to communicate with the card and reader, or the interface provided by CT-API: see http://www.linuxnet.com/documentation/files/ctapi.html and http://www.panstruga.de/ct-api/spec/spec_v09.html.

There is a Perl interface to pcsc: http://www.linuxnet.com/middleware/files/pcsc-perl-1.0.8.tar.gz.

Cambridge card utilities

Graham Phillips, currently from the Centre for Applied Research in Education Technology (CARET) (graham@caret.cam.ac.uk), wrote a set of utility programs for the Cambridge card that run under Windows: Change PIN, View card, Quick identifier, Extract certificate (see http://smartcard.caret.cam.ac.uk/). He also wrote a module that implements a pkcs#11 interface to allow Windows Netscape to use the certificate on the card for SSL authentication.

Rich Wareham (richwareham@users.sourceforge.net) has produced a similar set for Linux - see http://smartcard.caret.cam.ac.uk/linux/ (and http://www.srcf.ucam.org/~rjw57/sc/ and http://www.srcf.ucam.org/~rjw57/sc/software/). Rich's libcamcard C++ class library provides a useful reference for the APDUs needed to work with the Cambridge card. I found some of Rich's programs problematic:

In addition, the graphical applications need at least RedHat 7.1 to provide appropriate levels of KDE's QT library.

Experience with Card Readers

As mentioned above, getting Linux programs to talk to the Cambridge card is something of a hit-and-miss affair, and depends on exactly which reader, driver and software you are using. My experience with a number of example readers is set out below.

An additional complication is that many of these readers have a USB interface. USB support in Linux is evolving rapidly, even in the 'stable' kernel releases. Because of this, results may additionally depend critically on the kernel version and distribution that you are using.

The results below apply to a RedHat 7.1 system running kernel 2.4.9-21 and used Muscle's pcsc-lite version 1.0.1.

GemPlus GemPC410

A GemPlus GemPC410 serial reader, identifying itself as containing the GemCore firmware GemCore-R1.21-GM8.

The 'standard' driver for this reader appears to be libGemPC410.so (http://ludovic.rousseau.free.fr/softwares/ifd-GemPC/ifd-GemPC.html), which now replaces the earlier libgp-core.so (http://www.linuxnet.com/drivers/readers/files/gp-core-2.4.0.tar.gz and/or http://ludovic.rousseau.free.fr/softwares/gp-core/gp-core.html). While both drivers (version 2.4.0 of libgp-core.so and libGemPC410 from version 0.5.9 of ifd-GemPC) appeared to be able to talk to the reader, neither would talk to the Cambridge card.

It looks as if this is the same problem Rich discovered, and which resulted in him producing libcamgemcore.so, a modified version of libgp-core.so that addresses some problems with the original driver (see this message, this entire thread and this message from the sclinux mailing list for some further details of this). Using v. 1.1.0 of libcamgemcore.so it was indeed possible to successfully communicate with the Cambridge card and extract useful information.

GemPlus GCR410

This is a different serial reader from GemPlus. It looks very similar to the GemPC410, and seems to be considered by many people to be identical. However there is no doubt that this is not the case: while all of libgp-core.so, libGemPC410.so and libcamgemcore.so appeared to be able to communicate with the reader, none would communicate with the Cambridge card. If it helps to distinguish between the two versions, my GCR410 was marked on the base 'M/N: GCR410-2', while the PC410 was marked 'M/N: GemPC410'. The GemPC version also had a 'Designed for Windows NT/Windows98' sticker on the back. It identified itself as containing firmware version GemCore-R1.10-0M8.

GemPlus GemPC430

This is a USB reader from GemPlus. It appears to be supported by the libGemPC430.so library from (http://ludovic.rousseau.free.fr/softwares/ifd-GemPC/ifd-GemPC.html). The copy from v. 0.5.9 of IFD-GemPC appears to at least initially be able to communicate with the reader. However attempts to communicate with the card result in timeout error messages and the following in the system log:

Mar  1 11:59:37 mnementh kernel: usb_control/bulk_msg: timeout
Mar  1 11:59:37 mnementh kernel: usbdevfs: USBDEVFS_BULK failed dev 4 ep 0x6 len 2 ret -110

suggesting some major problem with the kernel USB support and apparently requiring a reboot to rectify.

ACR CyberMouse

ACR CyberMouse serial reader, ACR20S, using version 0.3.5 of the libacs_cmouse.so driver driver from http://www.acs.com.hk/downloads_drivers.asp.

With this I had some but limited success. A cut-down version of Rich's scardkbd will read the user-id field from the card fairly reliably. However kcardview appears to work but reports a user-id of "Card" and an expire date of "Empty" (consistent with the attempt to communicate with the card failing). scardkbd works the first time a card is inserted but causes pcscd to hang when the next card is inserted. This latter seems to be somehow related to the SCARD_RESET_CARD state used when disconnecting from the card, changing this to SCARD_EJECT_CARD seems to work around the problem. I suspect that many of these problems may be due to shortcomings in the CyberMouse reader itself and/or the IFD driver. The SCEZ website notes:

"ACR20S/Cybermouse does not accept class 2 or 4 commands where Le is 0 and returns malformed packets with some commands. Also inverse convention does not work with my driver. I recommend to run like hell, when you see this reader".

Towitoko Chipdrive Micro 130

Towitoko Chipdrive Micro 130 USB adapter, using version 2.0.5 of the driver at http://www.geocities.com/cprados/.

The documentation notes:

USB readers: Linux kernel version 2.4.12 or greater with PL2303 USB serial driver enabled is needed. ... Note that PL2303 support is still in experimental stage!

The pl2303 driver does seem to be present in kernel version 2.4.9-21. However attempts to use the reader resulted in the test machine repeatedly hard-hanging the second time pcsc was started after each reboot, and so further tests were discontinued.

However this does look like a nice reader, and the driver code looks (at a first glance) to be of good quality. And it includes a CT-API for good measure. The only problem so far is with driving the USB interface and virtually identical readers are available with a serial interface. I think a serial Towitoko reader would be worth a further look.

Utimaco (Omnikey) CardMan 2020

Utimaco (or Omnikey) CardMan 2020 USB reader, using v. 1.0.3 of the driver kit from http://www.utimaco.de/eng/content_products/product_download.html.

The driver consists of a shared library (libcm2020.so) and a kernel module, which are supplied ready-compiled without source. Unlike other USB Muscle drivers which are auto-detected, this driver requires configuration in the /etc/readers.conf file normally used for serial configurations.

Various versions of the pre-compiled kernel module are provided, to match various kernel versions from 2.2.18 upwards. Unfortunately there is no version for 2.4.9-21, and attempts to use the version for 2.4.9 resulted in pcscd being unable to communicate with the reader

References and links


Jon Warbrick
Last modified: Fri Mar 1 18:16:05 GMT 2002