Sunday, December 18, 2011

new version of pcsc-tools: 1.4.18

I just released a new version of pcsc-tools. No new feature but some enhancements.

If you do not know what pcsc-tools is, it contains 4 tools:
  • pcsc_scan(1) regularly scans every PC/SC reader connected to the host if a card is inserted or removed a "line" is printed.
  • ATR_analysis(1) is a Perl script used to parse the smart card ATR. This script is called (by default) by pcsc_scan.
  • scriptor(1) is a Perl script to send commands to a smart card using a batch file or stdin.
  • gscriptor(1) the same idea as scriptor.pl(1) but with a Perl-Gtk2 GUI.

An equivalent of ATR_analysis is available online http://smartcard-atr.appspot.com/

Changes:
1.4.18 - 18 December 2011, Ludovic ROUSSEAU
  • gscriptor: Display hex dumps in lines of 16 bytes instead of 17
  • gscriptor: Display bytes of value 0x20 as ' ' instead of '.'
  • scriptor: Display lines of 16 bytes instead of 24
  • 223 new ATRs
  • pcsc_scan: Correctly detect reader Plug and Play support

Wednesday, December 14, 2011

Short APDU readers supporting limited extended APDUs

Because of a bug report on the OpenSC mailing list I discovered that some CCID readers declare to support Short APDU only but can in fact accept APDU with more than 256 bytes of data.

I found only 2 readers with this particularity in my list:

Technical details

These 2 readers declare in the USB descriptor (the .txt file):
  • Short APDU level exchange in dwFeatures
  • a dwMaxCCIDMessageLength greater than 271 bytes

Effects

These readers declare to be short APDU so they should not be able to send or receive more than 256 bytes of data. 256 bytes of data + 5 bytes of header (CLA, INS, P1, P2, Lc) = 261 bytes. With the 10 bytes of CCID header we have the 271 bytes indicated in dwMaxCCIDMessageLength for all the (normal) Short APDU readers.

Up to version 1.3.12 (May 2010) my CCID driver would not support APDU bigger than 261 bytes with these readers. For example Mac OS X provides the CCID driver version 1.3.8 (June 2008). But in version 1.3.12 I modified the buffer size from 261 bytes to 64k bytes. This was needed for extended APDU readers.

The side effect of the change in version 1.3.12 is that the CCID driver will not reject APDU commands greater than 261 bytes.

Results

The Xiring MyLeo reader will support APDU of up to 512 bytes (522 minus 10 bytes for the CCID header).

The TianYu CCID SmartKey reader/token will support APDU of up to 502 bytes (512 minus 10 bytes for the CCID header).

If you want to use (limited) extended APDU with these readers on Mac OS X you have to upgrade the CCID driver to at least version 1.3.12.

Conclusion

These two readers are using a strange CCID combination. I do not say it is illegal but it is clearly a hack to support some form of (limited) extended APDU.

Monday, December 12, 2011

PC/SC workgroup, November 2011 meeting results

The PC/SC workgroup, November 2011 meeting is now over. The meeting minutes are available to PC/SC members. But this document is not public.

Here are the results about issues I reported for the meeting.

Extended APDU support reported by PC/SC

See the previous article Extended APDU support reported by PC/SC. The idea to for an application to be able to know if a reader+driver do support extended APDU.

The new version of PC/SC v2 part 10 describing the solution is not yet available. But the solution works like this:
  • The application uses SCardControl(FEATURE_GET_TLV_PROPERTIES, ...) and look for the tag dwMaxAPDUDataSize.
  • The value of dwMaxAPDUDataSize gives the maximum APDU data size supported by the reader+driver.
This proposal has been accepted.

Identifying a reader model

See the previous article Identifying a reader model. The idea is to be able to precisely identify a reader model before sending (potentially dangerous) SCardControl() commands.

The new version of PC/SC v2 part 10 describing the solution is not yet available. But the solution works like this:
The application uses SCardControl(FEATURE_GET_TLV_PROPERTIES, ...) and look for the tags PCSCv2_PART10_PROPERTY_idVendor and PCSCv2_PART10_PROPERTY_idProduct. These are the USB vendor ID and product ID of the device.

This proposal has been accepted.

Changes in PC/SC workgroup documents

Request: The PC/SC workgroup specifications contain a "Revision History" section with a brief description of the changes. It would be even better to have all the changes directly visible within the document.

The documents will be available as Word files in the member only area of the web site. Changes will be available as track changes.

No good news for non PC/SC workgroup members. You will have to compare two versions of the specification by hand (as before).

Firewalled pinpad

Request: The PC/SC workgroup should define the status word (SW1 and SW2) to be reported by the reader if a command is rejected by the firewall.

This is outside the scope of the PC/SC workgroup.

FEATURE_WRITE_DISPLAY, FEATURE_GET_KEY and FEATURE_VERIFY_PIN_START

Request: Document how FEATURE_WRITE_DISPLAY, FEATURE_GET_KEY and FEATURE_VERIFY_PIN_START should or could be implemented at the CCID level.

A subcommittee will be created to work on the question.

Unblock PIN feature and PIN merge feature

This is outside the scope of the PC/SC workgroup. You should contact the manufacturer if the reader is not working as expected.

Conclusion

My two main issues have been accepted.

The other requests have been discussed but rejected. It is not really surprising since the proposals were not described in details. For example the code returned by PC/SC when a command is refused by a firewalled pinpad may be accepted at a later meeting if correctly presented and described.

Saturday, December 3, 2011

libusb-1.0.9-rc3

The libusb 1.0.9 adventure is still ongoing. In a previous article "libusb 1.0.9-rc1" I announced that the 1.0.9 official/stable version was expected for 21st of September 2011. Of course this did not happen :-(

With the upgrade of the Linux kernel in lots of distributions it looks like the 60 seconds delay issue is more present and/or occurs more often. So I get more bug reports. The problem is not pcsc-lite or the CCID driver. The bug is in libusb.

History of the bug #56


This is the 4th article about this libsub bug. We already had:

How to get a fixed libusb?

$ git clone git://git.libusb.org/libusb.git
$ cd libusb
$ git branch testing origin/testing
$ git checkout testing

If you want to use an already prepared .tar.bz2 archive I provide one at http://ludovic.rousseau.free.fr/softwares/pcsc-lite/libusb-1.0.9-rc3.tar.bz2.

Conclusion

A lot of time and energy is lost by users of smart cards reporting bugs, and by me answering to bugs.

The bad news is that I don't see any positive signal for the future of libusb. I will continue to refer to the this article for any bug report mentioning a 60 seconds delay.

Thursday, December 1, 2011

EMV-CAP article now available online

In a previous article "EMV-CAP in MISC Magazine n°56" I presented a paper published in the French magazine MISC. The paper is now available online.

Thanks to Philippe Teuwen, co-author of the article, for the info.

Friday, November 25, 2011

New version of pcsc-lite: 1.8.1


I just released new version of pcsc-lite 1.8.1.
This version fixes a stupid mistake I made: I forgot to include some files in the source code archive.

Changes:
pcsc-lite-1.8.1: Ludovic Rousseau
25 November 2011
  • Distribute missing files from src/spy/

Saturday, November 19, 2011

New version of pcsc-lite: 1.8.0

I just released new version of pcsc-lite 1.8.0.

Changes:
pcsc-lite-1.8.0: Ludovic Rousseau
19 November 2011
  • PC/SC spy tool. See "PCSC API spy, third try"
  • Support systemd socket activation (the auto start of pcscd from the library has been removed. Use systemd instead). See "pcscd auto start using systemd"
  • SCardGetStatusChange(): check all the readers are already known and return SCARD_E_UNKNOWN_READER if a reader name is not present. Windows XP has this behavior.
  • SCardEstablishContext(): Invalidate all the handles in the son after a fork
  • Add define of FEATURE_EXECUTE_PACE from PCSC v2 Part 10 Amendment 1 2011-06-03
  • Fix some memory leaks reported by Coverity
  • Enable silent build by default
  • log_line(): correctly calculate delta time when no color is used The update of last_time was only done in case of colorization (LogDoColor). So on unsupported consoles the time was wrong.
  • log_xxd_always(): Use a variable-length array The debug message buffer is no more with a fixed size (around 600
    bytes of buffer to log) but uses a variable-length array. It is now possible to log extended APDU of 64kB.
    The variable-length array feature is available in GCC in C90 mode and is mandatory in C99 standard.
  • Some other minor improvements and bug corrections

Friday, November 18, 2011

PCSC API spy, third try

I already blogged about how to spy the PCSC API in PCSC API spy for GNU systems and PCSC API spy, another way. But I am still not happy with the limitations and side effects.

Limitations of previous solutions

ltrace

ltrace is able to trace the calls to any library (including libpcsclite.so.1). But one major limitation is that it does not work if the library is not linked to the executable. It does not work when:
  • libpcsclite.so.1 is used by a library used by the executable (like a PKCS#11 library)
  • libpcsclite.so.1 is dynamically loaded using dlopen() as is done by OpenSC

Internal tracing

Internal tracing do not have the limitations of ltrace. But one major drawback is the need to rebuild pcsc-lite with a specific configuration. This may be very difficult or impossible to do on a production system.

Use an independent library

The new idea is to not need to rebuild pcsc-lite. Instead we will use a new library that will be placed between the PC/SC client and the PC/SC library. This new library will spy all the calls and send them to a pretty displayer.

+------------------+
|  PC/SC client    |
+------------------+
        |
+------------------+    +-------------+
| libpcscspy.so.0  | -> | pcsc-spy.py |
+------------------+    +-------------+
        |
+------------------+
| libpcsclite.so.1 |
+------------------+

Two configurations are available


To be able to spy the PC/SC layer the application flow must be modified so that all PC/SC calls are redirected.

Applications linked with libpcsclite.so.1


We will use the standard LD_PRELOAD loader option to load our spying library.

Example:
LD_PRELOAD=/usr/lib/libpcscspy.so opensc-tool -a

Application loading libpcsclite.so.1


This is the case for the PC/SC wrappers like pyscard (for Python) and pcsc-perl (for Perl). The LD_PRELOAD mechanism can't be used. Instead we replace the libpcsclite.so.1 library by the spying one.

Use install_spy.sh and uninstall_spy.sh to install and uninstall the spying library.

Using the spying library without pcsc-spy.py is not a problem but has side effects:
  • a line "libpcsclite_nospy.so.1: cannot open shared object file: No such file or directory" will be displayed
  • some CPU time will be lost because of the PC/SC calls redirection

Starting the spy tool


Direct output

$ pcsc-spy.py

Store for later use

If a command argument is passed we use it instead of the default ~/pcsc-spy FIFO file. It is then possible to record an execution log and use pcsc-spy.py multiple times on the same log.

To create the log file just do:

$ mkfifo ~/pcsc-spy
$ cat ~/pcsc-spy > logfile

and run your PC/SC application. The API trace is stored in the file logfile. It is displayed using:
$ pcsc-spy.py logfile

Example using OpenSC


Executed command

$ LD_PRELOAD=/usr/lib/libpcscspy.so opensc-tool -a
Using reader with a card: Gemalto GemPC Twin 00 00
3b:9f:95:81:31:fe:9f:00:65:46:53:05:30:06:71:df:00:00:00:81:61:0f:d9

API log

$ pcsc-spy.py
SCardEstablishContext
 i dwScope: SCARD_SCOPE_USER (0x00000000)
 o hContext: 0x0103E68C
 => Command successful. (SCARD_S_SUCCESS [0x00000000])  [0.000219919]
SCardListReaders
 i hContext: 0x0103E68C
 i mszGroups: (null)
 o pcchReaders: 0x0000001A
 o mszReaders: NULL
 => Command successful. (SCARD_S_SUCCESS [0x00000000])  [0.000000128]
SCardListReaders
 i hContext: 0x0103E68C
 i mszGroups: (null)
 o pcchReaders: 0x0000001A
 o mszReaders: Gemalto GemPC Twin 00 00
 o mszReaders: 
 => Command successful. (SCARD_S_SUCCESS [0x00000000])  [0.000000101]
SCardGetStatusChange
 i hContext: 0x0103E68C
 i dwTimeout: 0x00000000 (0)
 i cReaders: 1
 i szReader: Gemalto GemPC Twin 00 00
 i  dwCurrentState:  (0x00000000)
 i  dwEventState:  (0x00000000)
 i  Atr length: 0x00000000 (0)
 i  Atr: 
 o szReader: Gemalto GemPC Twin 00 00
 o  dwCurrentState:  (0x00000000)
 o  dwEventState: SCARD_STATE_CHANGED, SCARD_STATE_PRESENT (0x00000022)
 o  Atr length: 0x00000017 (23)
 o  Atr: 3B 9F 95 81 31 FE 9F 00 65 46 53 05 30 06 71 DF 00 00 00 81 61 0F D9
 => Command successful. (SCARD_S_SUCCESS [0x00000000])  [0.000000184]
SCardConnect
 i hContext: 0x0103E68C
 i szReader Gemalto GemPC Twin 00 00
 i dwShareMode: SCARD_SHARE_SHARED (0x00000002)
 i dwPreferredProtocols: 0x00000003 (T=0, T=1)
 i phCard 0x02432010 (37953552)
 i pdwActiveProtocol 0x00000020 (32)
 o phCard 0x00015425 (87077)
 o dwActiveProtocol: T=1 (0x00000002)
 => Command successful. (SCARD_S_SUCCESS [0x00000000])  [0.000020242]
SCarControl
 i hCard: 0x00015425
 i dwControlCode: CM_IOCTL_GET_FEATURE_REQUEST (0x42000D48)
 i bSendLength 0x00000000 (0)
 i bSendBuffer
 i  NULL
 o bRecvLength 0x00000012 (18)
 o bRecvBuffer
 o  0000 0A 04 42 33 00 0A 12 04 42 33 00 12 13 04 42 00 ..B3....B3....B.
 o  0010 00 01                                           ..
  parsing CM_IOCTL_GET_FEATURE_REQUEST results:
  Tag FEATURE_IFD_PIN_PROPERTIES is 0x4233000A
  Tag FEATURE_GET_TLV_PROPERTIES is 0x42330012
  Tag FEATURE_CCID_ESC_COMMAND is 0x42000001
 => Command successful. (SCARD_S_SUCCESS [0x00000000])  [0.000000130]
SCarControl
 i bSendBuffer
 i  NULL
 o bRecvLength 0x00000004 (4)
 o bRecvBuffer
 o  0000 00 00 07 00                                     ....
  parsing FEATURE_IFD_PIN_PROPERTIES results:
  wLcdLayout: 0 0
  bEntryValidationCondition: 7
  bTimeOut2: 0
 => Command successful. (SCARD_S_SUCCESS [0x00000000])  [0.000000334]
SCardDisconnect
 i hCard: 0x00015425
 i dwDisposition: SCARD_LEAVE_CARD (0x00000000)
 => Command successful. (SCARD_S_SUCCESS [0x00000000])  [0.000000362]
SCardGetStatusChange
 i hContext: 0x0103E68C
 i dwTimeout: 0x00000000 (0)
 i cReaders: 1
 i szReader: Gemalto GemPC Twin 00 00
 i  dwCurrentState: SCARD_STATE_CHANGED, SCARD_STATE_PRESENT (0x00000022)
 i  dwEventState: SCARD_STATE_CHANGED, SCARD_STATE_PRESENT (0x00000022)
 i  Atr length: 0x00000017 (23)
 i  Atr: 3B 9F 95 81 31 FE 9F 00 65 46 53 05 30 06 71 DF 00 00 00 81 61 0F D9
 o szReader: Gemalto GemPC Twin 00 00
 o  dwCurrentState: SCARD_STATE_CHANGED, SCARD_STATE_PRESENT (0x00000022)
 o  dwEventState: SCARD_STATE_PRESENT (0x00000020)
 o  Atr length: 0x00000017 (23)
 o  Atr: 3B 9F 95 81 31 FE 9F 00 65 46 53 05 30 06 71 DF 00 00 00 81 61 0F D9
 => Command timeout. (SCARD_E_TIMEOUT [0x8010000A])  [0.000000352]
SCardGetStatusChange
 i hContext: 0x0103E68C
 i dwTimeout: 0x00000000 (0)
 i cReaders: 1
 i szReader: Gemalto GemPC Twin 00 00
 i  dwCurrentState: SCARD_STATE_PRESENT (0x00000020)
 i  dwEventState: SCARD_STATE_PRESENT (0x00000020)
 i  Atr length: 0x00000017 (23)
 i  Atr: 3B 9F 95 81 31 FE 9F 00 65 46 53 05 30 06 71 DF 00 00 00 81 61 0F D9
 o szReader: Gemalto GemPC Twin 00 00
 o  dwCurrentState: SCARD_STATE_PRESENT (0x00000020)
 o  dwEventState: SCARD_STATE_PRESENT (0x00000020)
 o  Atr length: 0x00000017 (23)
 o  Atr: 3B 9F 95 81 31 FE 9F 00 65 46 53 05 30 06 71 DF 00 00 00 81 61 0F D9
 => Command timeout. (SCARD_E_TIMEOUT [0x8010000A])  [0.000000303]
SCardGetStatusChange
 i hContext: 0x0103E68C
 i dwTimeout: 0x00000000 (0)
 i cReaders: 1
 i szReader: Gemalto GemPC Twin 00 00
 i  dwCurrentState: SCARD_STATE_PRESENT (0x00000020)
 i  dwEventState: SCARD_STATE_PRESENT (0x00000020)
 i  Atr length: 0x00000017 (23)
 i  Atr: 3B 9F 95 81 31 FE 9F 00 65 46 53 05 30 06 71 DF 00 00 00 81 61 0F D9
 o szReader: Gemalto GemPC Twin 00 00
 o  dwCurrentState: SCARD_STATE_PRESENT (0x00000020)
 o  dwEventState: SCARD_STATE_PRESENT (0x00000020)
 o  Atr length: 0x00000017 (23)
 o  Atr: 3B 9F 95 81 31 FE 9F 00 65 46 53 05 30 06 71 DF 00 00 00 81 61 0F D9
 => Command timeout. (SCARD_E_TIMEOUT [0x8010000A])  [0.000000215]
SCardConnect
 i hContext: 0x0103E68C
 i szReader Gemalto GemPC Twin 00 00
 i dwShareMode: SCARD_SHARE_SHARED (0x00000002)
 i dwPreferredProtocols: 0x00000003 (T=0, T=1)
 i phCard 0x0243EA80 (38005376)
 i pdwActiveProtocol 0x7FFEE90B2420 (140732808242208)
 o phCard 0x000104C4 (66756)
 o dwActiveProtocol: T=1 (0x00000002)
 => Command successful. (SCARD_S_SUCCESS [0x00000000])  [0.000000142]
SCardBeginTransaction
 i hCard: 0x000104C4
 => Command successful. (SCARD_S_SUCCESS [0x00000000])  [0.000000070]
SCardEndTransaction
 i hCard: 0x000104C4
 i dwDisposition: SCARD_LEAVE_CARD (0x00000000)
 => Command successful. (SCARD_S_SUCCESS [0x00000000])  [0.000002802]
SCardDisconnect
 i hCard: 0x000104C4
 i dwDisposition: SCARD_RESET_CARD (0x00000001)
 => Command successful. (SCARD_S_SUCCESS [0x00000000])  [0.000058724]
SCardReleaseContext
 i hContext: 0x0103E68C
 => Command successful. (SCARD_S_SUCCESS [0x00000000])  [0.000000204]

Results sorted by total execution time
total time: 0.304753 sec
0.219919 sec (  1 calls) 72.16% SCardEstablishContext
0.059086 sec (  2 calls) 19.39% SCardDisconnect
0.020384 sec (  2 calls)  6.69% SCardConnect
0.002802 sec (  1 calls)  0.92% SCardEndTransaction
0.001054 sec (  4 calls)  0.35% SCardGetStatusChange
0.000464 sec (  2 calls)  0.15% SCardControl
0.000229 sec (  2 calls)  0.08% SCardListReaders
0.000204 sec (  1 calls)  0.07% SCardReleaseContext
0.000070 sec (  1 calls)  0.02% SCardBeginTransaction

Analysis


  • PC/SC commands are in blue
  • Input arguments are in green
  • Output arguments are in mangenta
  • Errors are in bold red
  • The last part of the log contains some statistics about: functions called and times consumed by each of them

Next steps

Some ideas for the future:

Parse the APDU

For now the APDUs are displayed as a buffer of bytes. It would be great to display the command name corresponding to an INS byte. For example "SELECT FILE" is easier to read than "A4".

Smart card activity live monitoring

I often run pcscd in debug mode to know if something is happening at the PC/SC layer. I then know if the application is doing a lot of smart card accesses and I will just wait or if the application is locked somewhere and I should kill/debug it.

The idea is to send the PC/SC API log stream to a "live monitor" able to display a status using colors for example. The GUI still has to be designed. Please propose ideas.

PC/SC calls correctness

Will all the PC/SC API calls you can check your application is using the API correctly. For example you should have the same number of SCardEstablishContext() and SCardReleaseContext() calls.

Mac OS X support

Logs from pcscd are very difficult to read. See pcscd debug output on Mac OS X. A clear PCSC API spy tool would be a real plus.

I do plan to work on porting the spying layer but I don't know when I will work on it. You can work on it and provide patches and ideas.

Windows support?

I do not plan to work on a Windows port myself. At least not without a very big amount of money :-).

If you want to work on this please do. I may integrate your changes if they do not break GNU/Linux and Mac OS X supports.

[UPDATE] Petr Svenda wrote a PC/SC API spy for Windows: PC/SC APDU inspection and manipulation tool (APDUPlay)

Conclusion

I hope this API spy feature will work in the long term. It is already the 3rd iteration of API log.

The displayer program (pcsc-spy.py) is written in Python. It should be easy to extend and make it do some complex tasks.

Tuesday, November 15, 2011

pcscd auto start using systemd

In pcsc-lite version 1.6.0 (5 May 2010) I introduced a mechanism to start the pcscd daemon only when an application called SCardstablishContext() to get a PC/SC context. Read "Configuring your system for pcscd auto-start" for more information.

Old way: start by the libpcsclite library

One of the problem is that pcscd is then started as the user running the application. The pcscd process has to be setgid to get special privileges to get access to the USB devices (the smart card readers). Some people (and I understand) do not like files with special access right (like setgid).

New way: systemd

Around the same time (23 Aug 2010) the first article about systemd was posted by systemd author: Lennart Poettering

Socket activation

I will not describe systemd in details. But one of the services of systemd is to start a process when an application tries to communicate to a socket. The good news is that libpcsclite and pcscd are communicating through a UNIX (local) socket. So systemd provides a way to start pcscd when libpcsclite starts the communication.

The good news is that the changes are really minimal. libpcsclite has not changed and only the initialisation of pcscd has been updated a bit to use systemd services.

systemd configuration

pcsc-lite now use 2 systemd configuration files: pcscd.service and pcscd.socket

File pcscd.service:
[Unit]
Description=PC/SC Smart Card Daemon
Requires=pcscd.socket

[Service]
ExecStart=/usr/sbin/pcscd --foreground --auto-exit
ExecReload=/usr/sbin/pcscd --hotplug
StandardOutput=syslog

[Install]
Also=pcscd.socket

File pcscd.socket:
[Unit]
Description=PC/SC Smart Card Daemon Activation Socket

[Socket]
ListenStream=/var/run/pcscd/pcscd.comm

[Install]
WantedBy=sockets.target

These two files are installed in /lib/systemd/system/ on my Debian (testing) system.

systemd main comands


Status

$ systemctl status pcscd.service
pcscd.service - PC/SC Smart Card Daemon
   Loaded: loaded (/lib/systemd/system/pcscd.service)
   Active: inactive (dead) since Mon, 14 Nov 2011 16:33:40 +0100; 17h ago
  Process: 15489 ExecStart=/usr/sbin/pcscd --foreground --auto-exit (code=exited, status=0/SUCCESS)
   CGroup: name=systemd:/system/pcscd.service

$ systemctl status pcscd.socket
pcscd.socket - PC/SC Smart Card Daemon Activation Socket
   Loaded: loaded (/lib/systemd/system/pcscd.socket)
   Active: active (listening) since Mon, 14 Nov 2011 14:49:45 +0100; 19h ago
   CGroup: name=systemd:/system/pcscd.socket

The pcscd socket is configured and active but the pcscd process is not running. After starting a PC/SC application we get:

$ systemctl status pcscd.service
pcscd.service - PC/SC Smart Card Daemon
   Loaded: loaded (/lib/systemd/system/pcscd.service)
   Active: active (running) since Tue, 15 Nov 2011 10:27:39 +0100; 9s ago
 Main PID: 26929 (pcscd)
   CGroup: name=systemd:/system/pcscd.service
    └ 26929 /usr/sbin/pcscd --foreground --auto-exit

Stop

It is possible to stop the running pcscd process.

$ sudo systemctl stop pcscd.service
$ systemctl status pcscd.service
pcscd.service - PC/SC Smart Card Daemon
   Loaded: loaded (/lib/systemd/system/pcscd.service)
   Active: failed since Tue, 15 Nov 2011 10:30:13 +0100; 1s ago
  Process: 26965 ExecStart=/usr/sbin/pcscd --foreground --auto-exit (code=exited, status=1/FAILURE)
   CGroup: name=systemd:/system/pcscd.service

But in general I just kill(1) the pcscd process.

Start

If you start pcscd by hand, for example in debug and foreground mode, the daemon will remove the socket /var/run/pcscd/pcscd.comm on exit. This socket is not recreated automatically by systemd. You need to stop and start the pcscd.socket, using just start is not enough.

$ ls /var/run/pcscd/pcscd.comm 
ls: cannot access /var/run/pcscd/pcscd.comm: No such file or directory
$ sudo systemctl stop pcscd.socket
$ sudo systemctl start pcscd.socket
$ ls /var/run/pcscd/pcscd.comm 
/var/run/pcscd/pcscd.comm

The pcscd process is not started but the socket is now listening.

Migration

I removed the old autostart code in revision 6105. If you have systemd installed on your system I recommend using it to start pcscd. If you do not have systemd installed (maybe you do not use a Linux kernel) then you have to start pcscd at boot (as before version 1.6.0).

systemd availability

systemd is only available with a Linux kernel. systemd is now installed by default in Fedora 14. systemd is provided by Debian but Debian is not just limited to a Linux kernel. Debian also provides Hurd and FreeBSD kernel based Debian systems and systemd is not (yet) available for these kernels.

Major GNU/Linux distributions should provide systemd now. If your distribution do not have systemd you can still use the old way of starting pcscd at boot.

For non-Linux systems I have no auto-start solution. Just start pcscd at boot.

Conclusion

systemd is a nice new system to replace init and a lot more. It is a good piece of code to implement auto start for pcsc-lite.

Thanks to Kalev Lember for pushing the systemd patches.

Saturday, November 5, 2011

Identifying a reader model

This is another proposition I submitted to the PC/SC workgroup for the November 2011 meeting.

I removed the people names from the document and used XXX instead.

Please send/add comments if you have some.

Identifying a reader model




Identifying a reader model

Authors: Ludovic ROUSSEAU
XXX, Xiring
XXX, Gemalto
Version: 1.0, October 2011

The problem

PC/SC v2 Part 10 now allows to use FEATURE_CCID_ESC_COMMAND to send a proprietary command to a reader using the CCID command PC_to_RDR_Escape.

This is fine, but before sending a CCID escape command the application should be sure it is using the correct reader. A command foobar sent to reader A may return the firmware release but if sent to reader B the same command may erase its firmware or may do many other bad things.

PC/SC should provide a way to uniquely identify a reader so that an application will not send commands to readers not designed to support them.

Proposed solution

The USB protocol already provides a way to identify a device: idVendor and idProduct.

We propose to include these 2 fields in the FEATURE_GET_TLV_PROPERTIES TLV response.

Tag name and value

Vendor ID

Tag value:
0x0B
Length:
2 bytes
Value
idVendor USB idVendor

Product ID

Tag value:
0x0C
Length:
2 bytes
Value
idProduct USB idProduct

Code sample

Here is a sample code written in Python using pyscard PC/SC wrapper http://pyscard.sourceforge.net/
#! /usr/bin/env python

from smartcard.System import readers
from smartcard.pcsc.PCSCPart10 import (getFeatureRequest, hasFeature,
    getTlvProperties, FEATURE_CCID_ESC_COMMAND)

# use the first reader
card_connection = readers()[0].createConnection()
card_connection.connect()

# get CCID Escape control code
feature_list = getFeatureRequest(card_connection)

ccid_esc_command = hasFeature(feature_list, FEATURE_CCID_ESC_COMMAND)
if ccid_esc_command is None:
    raise Exception("The reader does not support FEATURE_CCID_ESC_COMMAND")

# get the TLV PROPERTIES
tlv = getTlvProperties(card_connection)

# check we are using a Xiring Leo reader
if tlv['PCSCv2_PART10_PROPERTY_idVendor'] == 0x0F14 \
    and tlv['PCSCv2_PART10_PROPERTY_idProduct'] == 0x0037:

    # proprietary commands for Xiring readers
    version = [ord(c) for c in "VERSION"]
    res = card_connection.control(ccid_esc_command, version)
    print res
    print ''.join([chr(x) for x in res])
else:
    print "Xiring Leo reader not found"
Execution with a Xiring Leo reader:
[86, 69, 82, 32, 32, 80, 75, 48, 50, 46, 49, 49, 0]
VER  PK02.11
Execution with a non Xiring Leo reader:
Xiring Leo reader not found

Questions & Answers

USB readers

For USB devices the idVendor and idProduct are the values from the USB layer.

Non-USB readers

For serial, PCMCIA, ExpressCard, etc. readers the idVendor can be the manufacturer USB ID (if any), and idProduct a product ID managed by the manufacturer.

But non-USB readers may not support the FEATURE_CCID_ESC_COMMAND command. So a non-USB reader may return no value for idVendor and idProduct tags.

Why not use the PC/SC reader name?

Using the PC/SC name is a fragile method. For example the name of a reader may change over time if the manufacturer name changes ("Gemplus" became "Gemalto" for example) and a new driver updates the reader name.

My CCID driver (http://pcsclite.alioth.debian.org/ccid.html) updated reader names from Gemplus to Gemalto a few years ago. This is a real case.

Why not use SCARD_ATTR_VENDOR_NAME?

PC/SC v2 part 3 defines the tag 0x100 "Vendor Name" as "ASCII string".

MSDN documentation for SCardGetAttrib() defines SCARD_ATTR_VENDOR_NAME as "Vendor name."

It looks like the Windows CCID driver uses the USB iManufacturer text field as SCARD_ATTR_VENDOR_NAME. Other drivers may return something else. For example up to release 1.4.5 my CCID driver returned the name of the driver author not the name of the reader manufacturer (because of a misunderstanding of the PC/SC specification).

The content of field is not specified, only its format: ASCII string.

Another problem is that some USB CCID readers use a strange value for the iManufacturer field.

Here is a list of all the iManufacturer values Ludovic has in his reader list: http://pcsclite.alioth.debian.org/ccid/section.html The first column is the number of occurrences of the name in the second column.
Nb iManufacturer value
1
1
6 ACS
1 ASK-RFID
6 ATMEL
1 ActivCard
2 ActivIdentity
2 Aktiv
1 Aktiv Co., ProgramPark
1 Aladdin
1 Athena
2 Athena
2 Atmel
1 Axalto
2 BIFIT
1 BLUTRONICS
5 Broadcom Corp
6 C3PO
3 COVADIS
7 Cherry GmbH
1 Dell
6 Eutron
1 FS
1 FT SCR301
1 Feitian Technologies
1 Free Software Initiative of Japan
2 Fujitsu Siemens Computers
1 GEMPLUS
8 Gemalto
2 Gemalto
1 Gemalto*
12 Gemplus
7 Generic
1 German Privacy Foundation
2 Giesecke & Devrient GmbH
1 GoldKey Security
1 HDZB
1 Hewlett Packard
2 Hewlett-Packard Company
1 KEBTechnology
3 KOBIL
9 KOBIL Systems
1 Kingtrust
1 Lenovo
1 MYSMART
4 Neowave
2 O2
1 OBERTHUR TECHNOLOGIES
2 OCS ID-One Cosmo Card
4 OMNIKEY
9 OMNIKEY AG
1 Panasonic
2 Philips Semiconductors
2 Precise Biometrics
1 REINER SCT
1 RSA
1 Raritan
1 Reiner-SCT
18 SCM Microsystems Inc.
1 SMART
1 SYNNIX
1 Samsung ElectronicsCo., Ltd
1 SchlumbergerSema
1 Secure Device Solutions
1 Sitecom
7 SpringCard
1 THRC
1 TianYu CCID Key
1 Tianyu
3 Todos
1 USB
8 VASCO
1 VMware
1 Validy
1 Winbond
4 XIRING
1 charismathics
3 id3 Semiconductors
1 jNet Technology inc.
1 ubisys

Remarks

The first name is just 3 space characters for ACS ACR 122U reader.

The second name is just 1 space character for the Gemalto Ezio CB+ reader.

The same company uses "ActivCard" and "ActivIdentity".

The same company uses "Aktiv" and "Aktiv Co., ProgramPark".

The ASEDrive IIIe KB reader uses "Athena " with an extra space at the end of the name. But the other readers from the same manufacturer use "Athena" without the extra space.

Feitian uses the product name "FT SCR301" as iManufacturer.

Gemplus uses "GEMPLUS" (all caps) for the GemPC433 SL reader.

Gemplus has been renamed Gemalto. So the new readers now use "Gemalto", but also "Gemalto " (with an extra space character) and even "Gemalto*".

We have 7 "Generic" for 2 different idVendor (0x0BDA and 0x058F).

We have 1 "Hewlett Packard" and 2 "Hewlett-Packard Company".

We have 3 "KOBIL" and 9 "KOBIL Systems".

We have 4 "OMNIKEY" and 9 "OMNIKEY AG".

We have 1 "REINER SCT" and 1 "Reiner-SCT"

Results

The iManufacturer field is not constant for all devices from the same manufacturer.

The iManufacturer is not uniq since the same name "Generic" is used by (at least) 2 manufacturers.

Only the idVendor USB field is correctly specified and uniq.

Why not use SCARD_ATTR_VENDOR_IFD_TYPE?

PC/SC v2 part 3 defines the tag 0x101 "Vendor- specified IFD Type" as "ASCII string".

MSDN for SCardGetAttrib() defines SCARD_ATTR_VENDOR_IFD_TYPE as "Vendor-supplied interface device type (model designation of reader)."

It looks like the Windows CCID driver uses the USB iProduct text field. Other drivers may return something else.

The content of the field is not specified, only its format (ASCII string).

Another problem is that some USB CCID readers use a strange value for the iProduct field.

Here is a list of all the iProduct values Ludovic has in his reader list. The first column is the number of occurrences of the name in the second column.
Nb Name
13 Smart Card Reader USB
5 mIDentity 4smart
5 5880
4 Weneo
4 CCID USB Reader
3 USB SmartCard Reader
3 USB Smart Card Reader
3 USB SMART CARD READER
3 Contactless Reader
2 XI-SIGN USB V2
2 USB2.0-CRW
2 USB Smart Chip Device
2 USB SMART CARD KEYBOARD
2 USB GemPCPinpad SmartCard Reader
2 Smart Enterprise Guardian Secure USB Device
2 Smart Card Reader
2 SCR33x USB Smart Card Reader
2 SCR3310 USB Smart Card Reader
2 SCR331-DI USB Smart Card Reader
2 SCL01x Contactless Reader
2 Prox SU USB PC LinkReader
2 Prox Dual USB PC LinkReader
2 PCSC Smartcard Reader
2 O2Micro CCID SC Reader
2 ICCD Smartcard
2 Ezio Shield
2 EMV Smartcard Reader
2 DIGIPASS KEY 860
2 DIGIPASS KEY 200
2 CryptoIdentity CCID
2 Connectable
2 Card Reader
2 CCID Smart Card Reader
2 ASEDrive CCID
1 uKeyCI800-K18
1 plug'n'crypt CCID token
1 mIDentity XL
1 mIDentity M
1 jToken s1
1 iBank2Key
1 cyberJack pinpad(a)
1 cyberJack RFID basis
1 Virtual USB CCID
1 VaultIC460
1 VaultIC440
1 VaultIC420 Smart Object
1 VEGA-ALPHA
1 USB-Token iBank2key
1 USB Token
1 USB Reader V3
1 TokenA sl vt
1 Token JC
1 Token GEM USB COMBI-M
1 Token GEM USB COMBI
1 TianYu CCID SmartKey
1 SmartTerminal XX7X
1 SmartTerminal XX44
1 SmartTerminal XX1X
1 SmartTerminal ST-2xxx
1 SmartMX Sample
1 SmartCard USB 2A
1 SmartCard Keyboard USB 2A
1 SmartBoard XX44
1 SmartBoard XX33
1 SmartBoard XX1X
1 Smart Token
1 Smart Card Reader Interface
1 Sitecom USB simcard reader MD-010
1 SchlumbergerSema Cyberflex Access
1 STD200
1 SPRx32 USB Smart Card Reader
1 SIM Reader
1 SDI010 Smart Card Reader
1 SCRx31 USB Smart Card Reader
1 SCR35xx v2.0 USB SC Reader
1 SCR35xx USB Smart Card Reader
1 SCR3340 - ExpressCard54 Smart Card Reader
1 SCR3320 - Smart Card Reader
1 SCR3311 USB Smart Card Reader
1 SCL010 Contactless Reader
1 SBV280
1 SA .NET Dual
1 S3FC9UB USB Smart Card II
1 Rutoken lite
1 Rutoken Magistra
1 Rutoken ECP
1 Reflex USB v3
1 RSA SecurID (R) Authenticator
1 Prox'N'Roll
1 Precise 250 MC
1 Precise 200 MC
1 Panasonic USB Smart Card Reader 7A-Smart
1 PIV Token
1 PDT
1 MySMART PAD V2.0
1 Multi-Reader
1 MFP Smart Card Reader
1 LTC3x USB
1 KONA USB SmartCard
1 KOBIL Class 3 Reader
1 KAAN SIM III
1 KAAN Base
1 KAAN Advanced
1 JCOP41V221
1 Integrated Smart Card Reader
1 IDProtect Key v2
1 ID-ONE TOKEN SLIM v2
1 Hybrid Smartcard Reader
1 HP USB Smartcard Reader
1 HP USB Smart Card Keyboard
1 HP USB CCID Smartcard Keyboard
1 Gemplus USB SmartCard Reader 433-Swap
1 GemPC Express
1 GemCore SIM Pro Smart Card Reader
1 GemCore POS Pro Smart Card Reader
1 Gem e-Seal Pro USB Token
1 GEN5XX CCID
1 FT SCR310
1 FSIJ USB Token
1 EasyFinger Ultimate
1 EasyFinger Standard
1 EZIO CB+
1 Digipass 860
1 Dell USB Smartcard Keyboard
1 Dell Smart Card Reader Keyboard
1 DP905
1 DP865
1 DP855
1 DOMINO-Key TWIN
1 DIGIPASS 920
1 D2CIM-DVUSB VM/CCID
1 Crypto Stick v1.2
1 CrazyWriter
1 CSB6 Ultimate
1 CSB6 Secure
1 CSB6 Basic
1 CCID SmartCard Controller
1 CCID Smart Card 301
1 BLUDRIVE II CCID
1 Auriga
1 Activkey Sim
1 ActivCard USB Reader V2
1
1
AT98SC032CT-USB
AT91SO CCID Smart Card Reader
1 AT91SC192192CT-USB ICCD reader
1 APG8201 USB Reader
1 ALYA
1 AGM2 CCID
1 ACR38 USB Reader
1 ACR122U PICC Interface
1 13.56MHz RFID (CCID)

Remarks

We have 13 readers defined as "Smart Card Reader USB". All these readers are from Omnikey.

Kobil uses the same name "mIDentity 4smart" for 5 readers with different idProduct.

Broadcom uses 5880 for 3 different idProduct.

Neowave uses Weneo for 4 readers with different idProduct.

ACS uses "CCID USB Reader" for 4 different readers (with the same idProduct: 0x90CC).

Gemplus/Gemalto uses "USB SmartCard Reader" for 3 readers with different idProduct.

"USB Smart Card Reader" is used by 2 Atmel readers and 1 THRC reader.

C3PO uses "USB SMART CARD READER" for 3 readers with different idProduct and "USB SMART CARD KEYBOARD" for 2 readers with different idProduct.

Oberthur uses "USB Smart Chip Device" for 2 readers with different idProduct.

Gemalto and Tianyu share the same "Smart Card Reader" name.

Results

Some names are too common and not specific to a product. How can we tell what reader is behind the name "USB SmartCard Reader" or "Smart Card Reader USB"?

The iProduct field is not uniq.

Only the idProduct USB field is correctly specified and (often) uniq.

Why an integer and not an string?

An integer is much more easy to compare to a know value than an string in a low level language like C.


Extended APDU support reported by PC/SC

This is a proposition I submitted to the PC/SC workgroup for the November 2011 meeting.

I removed the people names from the document and used XXX instead.

Please send/add comments if you have some.



Extended APDU support reported by PC/SC




Extended APDU support reported by PC/SC

Authors: Ludovic ROUSSEAU
XXX, Xiring
Version: 1.0, October 2011

The problem

More and more cards do support extended APDU. Some card commands may be available only using an extended APDU.

It is not possible for a PC/SC application to know if the connected reader (+ driver) does or does not support extended APDU. The only way is to use SCardTransmit() to send an extended APDU and try to analyze the error code. Analysing an error code is difficult since PC/SC does nor define an error to indicate that the reader does not support extended APDU. So an already existing error code will be returned instead.

It is then hard or impossible for an application to report a clear error to a user like: "your reader does not support extended APDU. Please use another reader model." The error returned by PC/SC may be caused by another problem.

CCID

At the CCID level it is easy to know if a CCID reader does support extended APDU or not by interpreting the dwFeatures field in the USB CCID descriptor. Readers defined as "Short APDU level exchange with CCID" are not able to manage extended APDU. See http://pcsclite.alioth.debian.org/ccid_extended_apdu.html for more details and a list of readers in each categories.

The current proposal is to allow a PC/SC application to access this information at the PC/SC level.

Proposed solution using SCardControl()

Provide a new tag for FEATURE_GET_TLV_PROPERTIES to return the maximal size of data the reader (+ driver) can support.

For a reader supporting the full extended APDU size the value would be 0x10000 (64 kB). This size does not include the APDU header.

Tag name and value

Name:
dwMaxAPDUDataSize
Tag value:
0x0A
Length:
4 bytes
Coding:
as the other multi-bytes values returned by FEATURE_GET_TLV_PROPERTIES
Values:
  • 0: short APDU only
  • 0 < X <= 256: invalid values (RFU)
  • 256 < X <= 0x10000: short and extended APDU of up to X bytes of data
  • 0x10000 < X: invalid values (RFU)

Proposed solution using SCardGetAttrib()


As suggested by XXX I also propose to add a new entry in the table 3-1 in PC/SC part 3, chapter 3.1.1.2 'Enumeration of Device Capabilities'

I think the correct Information class is "Communications" so the tag should be the next free one: 0x0111.

The table should be updated to add a new line containing:
Information Class Data Element Tag Max Length Data Encoding
Communications Max APDU data size 0x0111 4 bytes DWORD

The PC/SC specification does not define the C macro name. But I propose to use:
#define SCARD_ATTR_MAX_APDU_DATA_SIZE
  SCARD_ATTR_VALUE(SCARD_CLASS_COMMUNICATIONS, 0x0111)
XXX from YYY commented this idea with, November 11 2010:
I fully agree that we should find this information in part 3.

However, it is not so nice to do this on Windows as the driver would have to intercept the IOCTL_SMARTCARD_GET_ATTRIBUTE request and treat it locally instead of forward it to SMCLIB via SmartcardDeviceControl (see http://msdn.microsoft.com/en-us/library/ff548899%28v=VS.85%29.aspx). Note that the driver cannot rely on error code returned by SmartcardDeviceControl to process the request as the IRP has already been completed.

That's why I would prefer using a PC/SC V2 feature for that. PC/SC V2 features such as IFD_PIN_PROPERTIES and IFD_DISPLAY_PROPERTIES are also reader capabilities and should be returned via part 3 but PC/SC structures are restricted in Windows to known fields without possibility to extend them easily.

So we have 2 choices:
  • Add this information in part 3 (and be quite inconsistent with IFD_PIN_PROPERTIES and IFD_DISPLAY_PROPERTIES) and do not strictly respect MS rules on PC/SC drivers
  • Add this information to part 10 as a PC/SC V2 feature
What is Microsoft point of view on that?

AFAIK Microsoft never commented on this remark.

This solution would work just fine using pcsc-lite (and without changing pcsc-lite, just the driver).

Since this solution may be difficult to implement on Windows it may not be a so good solution after all and FEATURE_GET_TLV_PROPERTIES should be used instead.

Sample in pseudo code

If an application need to use extended APDU for a card it should first check support of extended APDU and inform the user in case of problem.

if (get dwMaxAPDUDataSize failed)
{
    /* we don't know if extended APDU is supported */
    Shall we continue or abort? Maybe it is safer to continue (as before).
}
else
{
    if (dwMaxAPDUDataSize == 0)
    {
        error("your reader does not support extended APDU.")
        return
    }

    if (dwMaxAPDUDataSize < needed_size)
    {
        error("your reader supports too short extended APDU.")
        error("We need at least %d bytes", dwMaxAPDUDataSize)
        return
    }
}
continue execution

Questions & Answers

On/off state

It is not enough to have a on/off bit to indicate extended APDU support. Some reader may not support a full length extended APDU (64kB) but only a limited length (1kB or 4kB). So the feature must report the maximal size.

Short APDU

This proposal does not try to define what a "short APDU" or an "extended APDU" are. Short and extended APDU are already defined in ISO 7813-3 chapter 12.1.3 (page 33) "Decoding conventions for command APDUs" where cases 1, 2S, 2E, 3S, 3E, 4S and 4E are defined.

Test suite

This proposal does not plan to provide (or extend) a test suite for extended APDU.

Adding extended APDU support in the Microsoft test suite is another subject. I don't think Microsoft is interested in improving the test suite.

Case 4 APDU

The PC/SC specification does not specify if a case 4 APDU is supported or not by PC/SC.

Extended APDU are not restricted to case 4 APDU. But also exist for case 2 and 3. It is another matter to define the behavior of PC/SC with a case 4 APDU (4S or 4E).

Driver support of extended APDU

The driver must also support extended APDU.

Of course the reader and the driver (and the PC/SC middleware) must support extended APDU. The driver will report support of extended APDU only if the reader and the driver both do support extended APDU.

CCID does report extended APDU support

Yes, a CCID reader will report support (or not) of extended APDU. But a PC/SC application do not have access to this information. The purpose of this proposal is to allow a PC/SC application to get this information from the PC/SC layer.

Some non-CCID readers may also support extended APDU. The same mechanism can be used for non-CCID readers. The driver just need to implement the support of dwMaxAPDUDataSize in FEATURE_GET_TLV_PROPERTIES.

Switch the reader in TPDU mode

" In case your reader does not support extended APDU your driver can switch into TPDU mode and provide the APDU to the reader in several TPDUs. "

I do not know any documented/official CCID command to switch a reader from APDU to TPDU. Most readers can't be switched from APDU to TPDU. So this is not an option in most of the cases.

If a reader can be switched from APDU to TPDU and then support extended APDU this should be transparent for the application. It is the job of the driver to do whatever is needed and use dwMaxAPDUDataSize in FEATURE_GET_TLV_PROPERTIES to inform the application that extended APDU are available for this reader.

Use block chaining at the CCID level

" If the reader were a CCID-APDU styled reader, it is the task for the CCID driver to limit the buffers to: dwMaxCCIDMessageLength

All these single buffers can be chained in the CCID protocol, by using the chaining byte. "

CCID block chaining is available only for readers in "Short and Extended APDU level" mode. For readers in "Short APDU level" mode the wLevelParameter parameter of PC_to_RDR_XfrBlock in bChainParameter parameter of RDR_to_PC_DataBlock are RFU and must be 0 (according to CCID v1.1 section 6.1.4 PC_to_RDR_XfrBlock page 30 and 6.2.1 RDR_to_PC_DataBlock page 49).

Maybe the Microsoft CCID driver do use wLevelParameter/bChainParameter even for a "Short APDU level" reader. But this is not CCID compliant.

CCID block chaining is not available for "Short APDU level" readers.

Friday, October 28, 2011

Misc PC/SC proposals

In a previous post PC/SC workgroup, November 2011 meeting and on the MUSCLE mailing list I asked for suggestion to submit at the PC/SC workgoup planned for November 2011. I got some feedback. Here is the proposal I sent to the PC/SC workgroup.

Misc PC/SC proposals


Author: Ludovic Rousseau
Date: October 2011

Introduction

In October 2011 I asked on the MUSCLE mailing list (http://musclecard.com/list.html) what changes where expected by the PC/SC workgroup.

Here is a list of the items.

Changes in PC/SC workgroup documents

The PC/SC workgroup specifications contain a "Revision History" section with a brief description of the changes. It would be even better to have all the changes directly visible within the document.

This can be done using different processes:

PDF with revision marks

When a new document is provided by the PC/SC workgroup a second document with the changes (compared to the previous version of the document) can be provided. This second document is easy to generate using the "compare" feature of MS Word.

Provide the document in ODF format

If providing the second document with the changes is too much work for the process another solution is to provide the document in ODF (Open Document Format) format (in addition to the PDF format). With this format it is easy to use, for example, Libre Office and compare two versions of the same specification document.

Provide the document in .DOC format

If providing the documents in ODF format is too much work for the process another solution is to provide the document in MS .DOC format. I guess the original format of the specification is already .DOC so the only added step is to store the .DOC documents on the PC/SC workgroup web site.

Firewalled pinpad

Some pinpad readers implement a firewall. If a PIN Verify command (INS byte 0x20) is sent using SCardTransmit() the reader will reject it. With a firewalled pinpad the only way to verify a PIN is by using the secure verify PIN feature. The problem is that 2 different readers will return 2 different status word in case of firewall rejection. In the field we already have noted two different Status Word in this case: 0x6985 and 0x6D00.

According to ISO 7816-4 we have:
0x6D00:
Instruction code not supported or invalid
0x69xx:
Command not allowed (further qualification in SW2)
0x6985:
Conditions of use not satisfied

These values are not really correct. Another problem is that it is hard (or impossible) to know if the error is really a invalid INS code or a rejection by the firewall. Another option it to use an not already used value like 0x6404
0x64xx:
State of non-volatile memory is unchanged (further qualification in SW2)
Some special Status Word values are already used (in the field) with a pinpad:
SW Description
0x6400 Timeout
0x6401 Canceled by user
0x6402 PIN mismatch
0x6403 Too short or too long PIN

The PC/SC workgroup should define the status word (SW1 and SW2) to be reported by the reader in such a case. We propose to use 0x6404.

FEATURE_WRITE_DISPLAY

PC/SC v2 part 10 defines FEATURE_WRITE_DISPLAY. But I could not find how to implement it in the driver at the CCID level. I guess some reader manufacturers have implemented it using CCID proprietary extensions.
Proposal:
Document how FEATURE_WRITE_DISPLAY should or could be implemented at the CCID level

FEATURE_GET_KEY

PC/SC v2 part 10 defines FEATURE_GET_KEY. But I could not find how to implement it in the driver at the CCID level. I guess some reader manufacturers have implemented using CCID proprietary extensions.
Proposal:
Document how FEATURE_GET_KEY should or could be implemented at the CCID level

FEATURE_VERIFY_PIN_START

PC/SC v2 part 10 defines FEATURE_VERIFY_PIN_START, FEATURE_GET_KEY_PRESSED and FEATURE_VERIFY_PIN_FINISH. But I could not find how to implement it in the driver at the CCID level. I guess some reader manufacturers have implemented using CCID proprietary extensions.
Proposal:
Document how FEATURE_VERIFY_PIN_START, FEATURE_GET_KEY_PRESSED and FEATURE_VERIFY_PIN_FINISH should or could be implemented at the CCID level
The same issue also exists for FEATURE_MODIFY_PIN_START and FEATURE_MODIFY_PIN_FINISH.

Unblock PIN feature

Add the possibility to unblock a PIN code using a pinpad. The unblock INS code is 0x2C and defined by TS 51.011 EN (http://www.3gpp.org/ftp/Specs/html-info/51011.htm). Some pinpad reader do not accept INS=0x2C for a VERIFY PIN command.

I propose to accept at least:
INS byte Description
0x20 VERIFY command (ISO 7816-4)
0x2C UNBLOCK (3GPP TS 51.011 EN)
Proposal:
Document the minimum set of INS bytes that a pinpad reader shall accept for a secure verify PIN command.

PIN merge feature

Add a 'pin merge' feature in which: part of the PIN is provided by the application and the other part is entered on the pinpad reader. Some readers already allow this: you just put part of the PIN in the APDU -- but some readers seem to overwrite the APDU's PIN buffer with padding bytes.

For eID cards, it happens that a PUK is split between the citizen and the governement. The examples below come from an eID card with ASCII encoded PINs:

E.g. of a 'PIN unblock without PIN change', in this case you can do an SCardControl(ctrl-for-FEATURE_VERIFY_PIN_DIRECT , data) with:

data = 1E 1E 02 00 00 00 00 08 04 00 02 01 16 08 00 00 00 00 00 00 0D 00 00 00
          00 2C 01 81 08 FF FF FF FF 31 32 33 34  (37 bytes)

So the application provides the last part of the PUK (= "1234" in this case) and the pinpad reader should ask the first part of the PUK to the user and fill it in at the location of the FF FF FF FF.

So for ASCII and BCD encoded PINs, this trick works on readers that don't write padding bytes to the PIN buffer (i.e. they should not change the 31 32 33 34 into FF FF FF FF in the above example).

Another example, of a 'PIN unblock with PIN change', in this case you can do an SCardControl(ctrl-for-FEATURE_CHANGE_PIN_DIRECT , data) with

data = 1E 1E 02 00 00 00 08 08 04 03 02 03 16 08 00 00 00 00 00 00 15 00 00 00
          00 2C 00 81 10 FF FF FF FF 31 32 33 34 FF FF FF FF FF FF FF FF  (45 bytes)

Here again, the first FF FF FF FF are for the user's part of the PUK, and the last 8 FF bytes are for the new PIN. Same remarks as above apply.

Conclusion

PC/SC defines some services at the PC/SC layer. This is fine. But the CCID specification does not provide any documentation or specification for these services.

A documentation is needed so that these services can be implemented in a "class" CCID driver.

Updating the CCID specification may be a difficult task. So I propose to host the documentation in the PC/SC workgroup. I do not ask to add the documentation in an existing document, just to host the documentation in a central place.

One easy solution is to host the CCID level programing manual of readers implementing the solutions we described above.

Thursday, October 13, 2011

http://musclecard.com/ is gone (for now)

The domain name musclecard.com has expired. The web site is now a domain parking web site.

Effects

  • The mailing list muscle@lists.musclecard.com is no more working
  • The web site http://musclecard.com/ is unavailable. But the same web site http://linuxnet.com/ is still working

I tried to contact David Corcoran, original author of pcsc-lite and maintainer of the web site. But as expected some of his emails are no more valid. David was not very active on the list since some time now.

New list

I created a new list on the pcsclite project on alioth: pcsclite-muscle

Conclusion


If the domain musclecard.com does not come back we will have to migrate to the new list.
I will keep you informed.

[update]

Oct 16th, 2011

The domain is now back online. It looks like the auto-renew failed due to an old credit card. David Corcoran renewed it for 3 more years. Thanks David!

Tuesday, October 11, 2011

New version of libccid: 1.4.5

I just released a new version of libccid.

Changelog

1.4.5 - 11 October 2011, Ludovic Rousseau
  • Add support of Alcor Micro AU9540, Ubisys 13.56MHz RFID (CCID),
    BIFIT USB-Token iBank2key, BIFIT iBank2Key, Gemalto Ezio Shield
    PinPad reader, Gemalto SA .NET Dual, Precise Sense MC reader (with
    fingerprint), SDS DOMINO-Key TWIN Pro
  • Add support of bPPDUSupport and FEATURE_CCID_ESC_COMMAND
  • SCARD_ATTR_VENDOR_NAME and SCARD_ATTR_VENDOR_IFD_VERSION are not
    the vendor name and version of the driver but of the IFD:
    InterFace Device i.e. the smart card reader. We then return the
    USB iManufacturer string as SCARD_ATTR_VENDOR_NAME and USB
    bcdDevice as SCARD_ATTR_VENDOR_IFD_VERSION
  • reduce binary size bu removing unused features from simclist
  • Fix some warnings reported bu Coverity

Sunday, October 9, 2011

PC/SC workgroup, November 2011 meeting

2 times a year the PC/SC workgroup is having a meeting.

When and Where?

The next meeting is planned on November 15th 2011 during the "Cartes & Identification" international event in Paris, France.

Who?

The members of the PC/SC workgoup are mainly smart card and reader manufacturers.

Core Members:

  • Gemalto
  • Oracle

Associate Members:

  • Advanced Card Systems
  • Athena Smartcard Solutions
  • C3PO S.A.
  • Cherry /ZF Electronics GmbH
  • HID Global
  • Infineon
  • Kobil Systems GmbH
  • NXP Semiconductors
  • O2Micro, Inc.
  • Realtek Semiconductor Corp.
  • Sagem Monetel GmbH
  • SCM Microsystems
  • Siemens
  • Todos
  • Toshiba
  • Xiring

One particularly missing member is Microsoft. Microsoft was a core member for a long time but has now disappeared from the PCSC workgoup list.

Me

Since 1 year I am an invited member of the PC/SC workgroup as a Free Software member and author of pcsc-lite and libccid. In practice I am (just) on one of the PC/SC workgroup mailing list. This list is very quiet since nearly everything is discussed and resolved during the 2 meetings each year.

You

If you are not a member of the PC/SC workgroup you can't change the standard. But you may have good ideas for a new and missing feature.
For example the FEATURE_GET_TLV_PROPERTIES service is something that was added in March 2010 after a proposal I made with the help of Gemalto. So an evolution of the standard is possible.

If, as an PC/SC application author, you think something is missing in the PC/SC standard just tell me. I will try to propose it for inclusion.

Conclusion

Please share your good ideas about the evolution of PC/SC.

Wednesday, October 5, 2011

FEATURE_CCID_ESC_COMMAND

Since revision 5991 my CCID driver does support FEATURE_CCID_ESC_COMMAND and bPPDUSupport.

These two services have been introduced in PC/SC v2 part 10 version 2.02.07 March 2010 and 2.02.08 April 2010.

FEATURE_CCID_ESC_COMMAND

This feature can be used to retrieve the control code to send a CCID escape command (PC_to_RDR_Escape) to the reader using SCardControl().

The value is returned by the CM_IOCTL_GET_FEATURE_REQUEST command. This will return a TLV data stream. The dwControlCode to use is the value corresponding to the tag FEATURE_CCID_ESC_COMMAND (0x13).

Before this mechanism it was possible to use the value IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE but this value is not specified/documented in any official document (AFAIK).

Using FEATURE_CCID_ESC_COMMAND is now portable (everywhere the PC/SC drivers implement it).

bPPDUSupport

The SCardControl() function is quiet limited with the Microsoft CCID driver on Windows. So some smart card reader manufacturers use SCardTransmit() to send commands to the reader (instead of the card).

This mechanism is fragile since the reader must interpret the command and determine if the command if for itself or for the card.

The PC/SC workgroup documented a way to know how the driver is expecting to receive commands for itself.

bPPDUSupport is a tag in the TLV data stream returned by FEATURE_GET_TLV_PROPERTIES. The value is coded as:
  • Bit 0: If set to 1, PPDU is supported over SCardControl() using FEATURE_CCID_ESC_COMMAND
  • Bit 1: If set to 1, PPDU is supported over SCardTransmit()

Implementation in my CCID driver

By default, for security reasons, sending an arbitrary PC_to_RDR_Escape command is forbidden. This can be configured using the ifdDriverOptions setting in the driver Info.plist file.


[...]
    <key>ifdDriverOptions</key>
    <string>0x0000</string>

    <!-- Possible values for ifdDriverOptions
    1: DRIVER_OPTION_CCID_EXCHANGE_AUTHORIZED
        the CCID Exchange command is allowed. You can use it through
        SCardControl(hCard, IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE, ...)

[...]
If the bit 0 of ifdDriverOptions is set then the driver will allow the use of IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE and now also the value associated to FEATURE_CCID_ESC_COMMAND

The driver will always report bPPDUSupport. By default the value is 0x00. But if If the bit 0 of ifdDriverOptions is set then the value of bPPDUSupport will be 0x01 indicating the support of FEATURE_CCID_ESC_COMMAND using dwControlCode and SCardControl().

Sample code

The use of these features may be hard to understand. So a small example can help.

In Python

#! /usr/bin/env python

"""
#   FEATURE_CCID_ESC_COMMAND.py: Unitary test for FEATURE_CCID_ESC_COMMAND
#   Copyright (C) 2011  Ludovic Rousseau
"""

#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 3 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License along
#   with this program; if not, see <http://www.gnu.org/licenses/>.

from smartcard.System import readers
from smartcard.pcsc.PCSCPart10 import (SCARD_SHARE_DIRECT,
    SCARD_LEAVE_CARD, FEATURE_CCID_ESC_COMMAND, getFeatureRequest, hasFeature)


def main():
    """ main """
    card_connection = readers()[0].createConnection()
    card_connection.connect(mode=SCARD_SHARE_DIRECT,
        disposition=SCARD_LEAVE_CARD)

    feature_list = getFeatureRequest(card_connection)

    ccid_esc_command = hasFeature(feature_list, FEATURE_CCID_ESC_COMMAND)
    if ccid_esc_command is None:
        raise Exception("The reader does not support FEATURE_CCID_ESC_COMMAND")

    # proprietary commands for Xiring readers
    version = [ord(c) for c in "VERSION"]
    res = card_connection.control(ccid_esc_command, version)
    print res
    print ''.join([chr(x) for x in res])

    serial = [ord(c) for c in "GET_SN"]
    res = card_connection.control(ccid_esc_command, serial)
    print res
    print ''.join([chr(x) for x in res])

if __name__ == "__main__":
    main()

In C

The C language is much more verbose than Python. I added support of FEATURE_CCID_ESC_COMMAND and bPPDUSupport in scardcontrol.c example code provided with the CCID driver.

The idea is the same as in Python:
  1. get the control code to use using FEATURE_CCID_ESC_COMMAND
  2. use SCardControl() to send a command
The C source code is 817 lines long. It is available online.

Comments

PC/SC now documents a way to send arbitrary proprietary commands to a reader. We now have two questions:

What command should you send?

You should know what you are doing and use the smart card reader user manual. So the command you want to use is documented, but maybe the documentation is not public. In general proprietary commands are not publicly documented.

How to know what reader exactly you are using?

I do not have an answer to this question. Using the PC/SC reader name is fragile. See a previous blog article What is in a PC/SC reader name? The reader name can change over time like with "Gemplus" becoming "Gemalto".

Maybe PC/SC must provide a new mechanism to report the USB VendorID and ProductID so that an application can be sure a specific reader is used.

Conclusion

Having to use proprietary commands is a sign of failure from the PC/SC workgroup. A service is needed but missing from the PC/SC standard. It has then been implemented using a proprietary mechanism (not documented, not portable, not interoperable).

It is a failure because the application is now linked to a particular smart card reader model.