Important!

Blog moved to https://blog.apdu.fr/

I moved my blog from https://ludovicrousseau.blogspot.com/ to https://blog.apdu.fr/ . Why? I wanted to move away from Blogger (owne...

Friday, February 14, 2014

New version of pcsc-lite: 1.8.11

I just released a new version of pcsc-lite 1.8.11.

No major changes except polkit support (pushed by RedHat).

Changes:
pcsc-lite-1.8.11: Ludovic Rousseau
14 February 2014
  • Add polkit support. See doc/README.polkit
  • /etc/reader.conf: CHANNELID and DEVICENAME are both optional but not at the same time
  • Some other minor improvements and bug corrections

New version of libccid: 1.4.15

I just released a version 1.4.15 of libccid the free software CCID class smart card reader driver.

Changes:
1.4.15 - 14 February 2014, Ludovic Rousseau
  • Add support of
    • DUALi DRAGON NFC READER
    • Feitian bR301
    • Gemalto CR30 reader in serial communication
    • Gemalto Ezio Shield Pro SC
    • IIT E.Key Almaz-1C
  • PIN_MODIFY_STRUCTURE & PIN_VERIFY_STRUCTURE: Fix calculation of the command length after pcsc-lite 1.8.9 (October 2013) changed the PCSC/reader.h header
  • Add specific PIN min (0) & max (25) sizes for SmartTerminal ST-2xxx
  • Do not get the data rates if bNumDataRatesSupported = 0
  • Support Gemalto features for pinpad readers MinimumPINSize, MaximumPINSize and bEntryValidationCondition are fetched from the reader firmware
  • disable (broken) pinpad for Fujitsu SmartCase KB SCR eSIG
  • examples/scardcontrol.c:
    • Parse codes returned by a pinpad (as SW1/SW2)
      Known codes for now are:
      • 0x9000: Success
      • 0x6400: Timeout
      • 0x6401: Cancelled by user
      • 0x6402: PIN mismatch
      • 0x6403: Too short or too long PIN
    • Retrieve min and max PIN sizes from the driver
    • Retrieve bEntryValidationCondition from the driver
  • be more strict for bInterfaceClass = 255 by also checking extra_length
  • some minor bugs removed

Sunday, February 9, 2014

CCID descriptor statistics: dwDataRate

Article from the serie "CCID descriptor statistics"

The dwDataRate field is a number value from the CCID USB descriptor:
Default ICC I/O data rate in bps. This is an integer value

Example: 9600 bps is encoded as the integer value 9600. (00002580h)

dwDataRate#%
10752 bps9938.98 %
9600 bps6224.41 %
12903 bps249.45 %
10753 bps197.48 %
9946 bps103.94 %
9909 bps83.15 %
12407 bps51.97 %
4032 bps41.57 %
10080 bps31.18 %
106000 bps31.18 %
12902 bps31.18 %
2688 bps20.79 %
5376 bps20.79 %
8065 bps20.79 %
9924 bps20.79 %
10573 bps10.39 %
12672 bps10.39 %
13440 bps10.39 %
20112 bps10.39 %
9677 bps10.39 %
9910 bps10.39 %


The default data rate is the data rate used before a new data rate is selected by the reader and/or the driver.


Most of the values are around 9600 bps which is the historical data rate value.

The 3 readers with dwDataRate = 106000 bauds are contactless readers.

CCID descriptor statistics: bNumDataRatesSupported

Article from the serie "CCID descriptor statistics"

The bNumDataRatesSupported field is a number value from the CCID USB descriptor:
The number of data rates that are supported by the CCID.

If the value is 00h, all data rates between the default data rate dwDataRate and the maximum data rate dwMaxDataRate are supported. Those values comply with § 1.2 and with all clock frequencies supported by the reader. See offset 18 and GET_CLOCK_FREQUENCIES § 5.3.2.

bNumDataRatesSupported#%
0 (will use whatever is returned)18171.26 %
53207.87 %
106155.91 %
172.76 %
041.57 %
441.57 %
541.57 %
1131.18 %
12731.18 %
5220.79 %
720.79 %
820.79 %
1510.39 %
1910.39 %
25410.39 %
310.39 %
4010.39 %
4510.39 %
5710.39 %


This field is used to retrieve the list of all the data rates supported by the reader. The driver then select the best (fastest) data rate to use with the card according to the card ATR TA1 byte.

The longer the list, the better because it will give more choice for the driver to select the best data rate.

CCID descriptor statistics: bNumClockSupported

Article from the serie "CCID descriptor statistics"

The bNumClockSupported field is a number value from the CCID USB descriptor:
The number of clock frequencies that are supported by the CCID. If the value is 00h, the supported clock frequencies are assumed to be the default clock frequency defined by dwDefaultClock and the maximum clock frequency defined by dwMaximumClock.

The reader must implement the command PC_to_RDR_SetDataRateAndClockFrequency if more than one clock frequency is supported.

bNumClockSupported#%
0 (will use whatever is returned)19074.80 %
13814.96 %
4187.09 %
041.57 %
520.79 %
210.39 %
610.39 %


This field is not use by my CCID driver. The vast majority of readers have the "Automatic ICC clock frequency change according to parameters" bit set in dwFeatures. So the clock selection is made by the reader itself.

Saturday, February 8, 2014

PCSC API spy, on Mac OS X

In a previous article "PCSC API spy, third try" I described a way to get a nice log of all the PC/SC calls made by an application. The example was using an application on GNU/Linux. A version for Mac OS X was planned but not yet available at that time.

I now realise I finished the Mac OS X version of pcsc-spy but have not yet blogged about it. It is time to fix this.

Installation

pcsc-spy is part of (the official) pcsc-lite. You can get it from the PCSC lite project web page. The latest version of pcsc-lite as I write this blog entry is 1.8.10.

$ curl -O https://alioth.debian.org/frs/download.php/file/3963/pcsc-lite-1.8.10.tar.bz2
$ tar xjf pcsc-lite-1.8.10.tar.bz2
$ cd pcsc-lite-1.8.10/
$ ./configure
[...]
$ cd src/spy
$ make
$ make framework

Now you can find a PCSC.framework directory that is the equivalent of libpcscspy.so on GNU/Linux.

The installation is not automatic but very easy. You copy the PCSC.framework directory in /tmp

$ cp -a PCSC.framework /tmp

Copy the official PCSC.framework (binary only) in /tmp

$ cp /System/Library/Frameworks/PCSC.framework/PCSC /tmp

Since we use the temporary directory /tmp the log/debug files will be automatically erased on the next system boot. No side effect.

Execution

In a Terminal application window (shell) run the pcsc-spy command:

$ ./pcsc-spy

In another Terminal application windows run the application you want to debug:

$ DYLD_FRAMEWORK_PATH=/tmp pcsctest

MUSCLE PC/SC Lite Test Program

Testing SCardEstablishContext    : Command successful.
Testing SCardGetStatusChange 
Please insert a working reader   : Command successful.
Testing SCardListReaders         : Command successful.
Reader 01: Feitian bR301 00 00
Enter the reader number          : 1
Waiting for card insertion         
                                 : Command successful.
Testing SCardConnect             : Command successful.
Testing SCardStatus              : Command successful.
Current Reader Name              : Feitian bR301 00 00
Current Reader State             : 0x34
Current Reader Protocol          : 0x0
Current Reader ATR Size          : 12 (0xc)
Current Reader ATR Value         : 3B A7 00 40 18 80 65 A2 08 01 01 52 
Testing SCardDisconnect          : Command successful.
Testing SCardReleaseContext      : Command successful.
Testing SCardEstablishContext    : Command successful.
Testing SCardGetStatusChange 
Please insert a working reader   : Command successful.
Testing SCardListReaders         : Command successful.
Reader 01: Feitian bR301 00 00
Enter the reader number          : 1
Waiting for card insertion         
                                 : Command successful.
Testing SCardConnect             : Command successful.
Testing SCardStatus              : Command successful.
Current Reader Name              : Feitian bR301 00 00
Current Reader State             : 0x34
Current Reader Protocol          : 0x0
Current Reader ATR Size          : 12 (0xc)
Current Reader ATR Value         : 3B A7 00 40 18 80 65 A2 08 01 01 52 
Testing SCardDisconnect          : Command successful.
Testing SCardReleaseContext      : Command successful.

PC/SC Test Completed Successfully !

In the first Terminal window you will get the colorfull (oh yeah!) log output:
SCardEstablishContext
 i dwScope: SCARD_SCOPE_SYSTEM (0x00000002)
 o hContext: 0x0103253B
 => Command successful. (SCARD_S_SUCCESS [0x00000000])  [0.000000722]
SCardGetStatusChange
 i hContext: 0x0103253B
 i dwTimeout: 0xFFFFFFFF (4294967295)
 i cReaders: 0
 => Command successful. (SCARD_S_SUCCESS [0x00000000])  [0.000000044]
SCardListReaders
 i hContext: 0x0103253B
 i mszGroups: (null)
 o pcchReaders: 0x00000015
 o mszReaders: NULL
 => Command successful. (SCARD_S_SUCCESS [0x00000000])  [0.000000059]
SCardListReaders
 i hContext: 0x0103253B
 i mszGroups: (null)
 o pcchReaders: 0x00000015
 o mszReaders: Feitian bR301 00 00
 o mszReaders: 
 => Command successful. (SCARD_S_SUCCESS [0x00000000])  [0.000000042]
SCardGetStatusChange
 i hContext: 0x0103253B
 i dwTimeout: 0xFFFFFFFF (4294967295)
 i cReaders: 1
 i szReader: Feitian bR301 00 00
 i  dwCurrentState: SCARD_STATE_EMPTY (0x00000010)
 i  dwEventState: SCARD_STATE_IGNORE, SCARD_STATE_CHANGED, SCARD_STATE_UNKNOWN, SCARD_STATE_UNAVAILABLE, SCARD_STATE_EXCLUSIVE, SCARD_STATE_INUSE, SCARD_STATE_EMPTY, SCARD_STATE_MUTE, SCARD_STATE_PRESENT, SCARD_STATE_UNPOWERED, SCARD_STATE_ATRMATCH (0x00007FFF)
 i  Atr length: 0x00000012 (18)
 i  Atr: 00 00 00 00 68 70 E7 0D 01 00 00 00 01 00 00 00 00 00
 o szReader: Feitian bR301 00 00
 o  dwCurrentState: SCARD_STATE_EMPTY (0x00000010)
 o  dwEventState: SCARD_STATE_CHANGED, SCARD_STATE_PRESENT (0x00000022)
 o  Atr length: 0x0000000C (12)
 o  Atr: 3B A7 00 40 18 80 65 A2 08 01 01 52
 => Command successful. (SCARD_S_SUCCESS [0x00000000])  [0.000000163]
SCardConnect
 i hContext: 0x0103253B
 i szReader Feitian bR301 00 00
 i dwShareMode: SCARD_SHARE_SHARED (0x00000002)
 i dwPreferredProtocols: 0x00000003 (T=0, T=1)
 i phCard 0x00007FFF (32767)
 i pdwActiveProtocol 0x00000000 (0)
 o phCard 0x0001616A (90474)
 o dwActiveProtocol: T=0 (0x00000001)
 => Command successful. (SCARD_S_SUCCESS [0x00000000])  [0.000411198]
SCardStatus
 i hCard: 0x0001616A
 i pcchReaderLen 0x00000034 (52)
 i pcbAtrLen 0x00000021 (33)
 o cchReaderLen 0x00000014 (20)
 o mszReaderName Feitian bR301 00 00
 o dwState 0x00000034 (52)
 o dwProtocol 0x00000001 (1)
 o bAtrLen 0x0000000C (12)
 o bAtr 3B A7 00 40 18 80 65 A2 08 01 01 52
 => Command successful. (SCARD_S_SUCCESS [0x00000000])  [0.000000473]
SCardDisconnect
 i hCard: 0x0001616A
 i dwDisposition: SCARD_UNPOWER_CARD (0x00000002)
 => Command successful. (SCARD_S_SUCCESS [0x00000000])  [0.000594971]
SCardReleaseContext
 i hContext: 0x0103253B
 => Command successful. (SCARD_S_SUCCESS [0x00000000])  [0.000000209]
SCardEstablishContext
 i dwScope: SCARD_SCOPE_SYSTEM (0x00000002)
 o hContext: 0x01035D3C
 => Command successful. (SCARD_S_SUCCESS [0x00000000])  [0.000000541]
SCardGetStatusChange
 i hContext: 0x01035D3C
 i dwTimeout: 0xFFFFFFFF (4294967295)
 i cReaders: 0
 => Command successful. (SCARD_S_SUCCESS [0x00000000])  [0.000000033]
SCardListReaders
 i hContext: 0x01035D3C
 i mszGroups: (null)
 o pcchReaders: 0x00000015
 o mszReaders: NULL
 => Command successful. (SCARD_S_SUCCESS [0x00000000])  [0.000000034]
SCardListReaders
 i hContext: 0x01035D3C
 i mszGroups: (null)
 o pcchReaders: 0x00000015
 o mszReaders: Feitian bR301 00 00
 o mszReaders: 
 => Command successful. (SCARD_S_SUCCESS [0x00000000])  [0.000000039]
SCardGetStatusChange
 i hContext: 0x01035D3C
 i dwTimeout: 0xFFFFFFFF (4294967295)
 i cReaders: 1
 i szReader: Feitian bR301 00 00
 i  dwCurrentState: SCARD_STATE_EMPTY (0x00000010)
 i  dwEventState: SCARD_STATE_CHANGED, SCARD_STATE_PRESENT (0x00000022)
 i  Atr length: 0x0000000C (12)
 i  Atr: 3B A7 00 40 18 80 65 A2 08 01 01 52
 o szReader: Feitian bR301 00 00
 o  dwCurrentState: SCARD_STATE_EMPTY (0x00000010)
 o  dwEventState: SCARD_STATE_CHANGED, SCARD_STATE_PRESENT (0x00000022)
 o  Atr length: 0x0000000C (12)
 o  Atr: 3B A7 00 40 18 80 65 A2 08 01 01 52
 => Command successful. (SCARD_S_SUCCESS [0x00000000])  [0.000000129]
SCardConnect
 i hContext: 0x01035D3C
 i szReader Feitian bR301 00 00
 i dwShareMode: SCARD_SHARE_SHARED (0x00000002)
 i dwPreferredProtocols: 0x00000003 (T=0, T=1)
 i phCard 0x0001616A (90474)
 i pdwActiveProtocol 0x00000001 (1)
 o phCard 0x00011242 (70210)
 o dwActiveProtocol: T=0 (0x00000001)
 => Command successful. (SCARD_S_SUCCESS [0x00000000])  [0.000411238]
SCardStatus
 i hCard: 0x00011242
 i pcchReaderLen 0x00000034 (52)
 i pcbAtrLen 0x00000021 (33)
 o cchReaderLen 0x00000014 (20)
 o mszReaderName Feitian bR301 00 00
 o dwState 0x00000034 (52)
 o dwProtocol 0x00000001 (1)
 o bAtrLen 0x0000000C (12)
 o bAtr 3B A7 00 40 18 80 65 A2 08 01 01 52
 => Command successful. (SCARD_S_SUCCESS [0x00000000])  [0.000000465]
SCardDisconnect
 i hCard: 0x00011242
 i dwDisposition: SCARD_UNPOWER_CARD (0x00000002)
 => Command successful. (SCARD_S_SUCCESS [0x00000000])  [0.000594863]
SCardReleaseContext
 i hContext: 0x01035D3C
 => Command successful. (SCARD_S_SUCCESS [0x00000000])  [0.000000369]

Results sorted by total execution time
total time: 4.221649 sec
1.189834 sec (  2 calls) 28.18% SCardDisconnect
0.822436 sec (  2 calls) 19.48% SCardConnect
0.001263 sec (  2 calls)  0.03% SCardEstablishContext
0.000938 sec (  2 calls)  0.02% SCardStatus
0.000578 sec (  2 calls)  0.01% SCardReleaseContext
0.000369 sec (  4 calls)  0.01% SCardGetStatusChange
0.000174 sec (  4 calls)  0.00% SCardListReaders

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

Raw log file

If you want to store a log file for a later analysis or if you want to send me a log trace it is better to store the log in raw format. You can do that (as on GNU/Linux) by doing:

$ 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

Documentation

The documentation is included with the pcsc-lite source code and is also available online at pcsc-spy.1 manpage.

Conclusion

It is easy to generate a nice PC/SC log on Mac OS X.