Friday, March 27, 2015

Gemalto smart card readers

Now that Gemalto bought SafeNet it has become a big company with a lot of different brands.

Some of the brands in the Gemalto group are used by CCID readers listed in the big matrix. I will only talk about CCID compliant readers. So readers produced before the CCID specification was available (around 2001) are not listed here.

Short history of Gemalto fusions and acquisitions

  • 1926: creation of Schlumberger
  • 1988: creation of Gemplus
  • 2001: Schlumberger buys Sema Group plc and becomes SchlumbergerSema
  • 2004: Axalto is a spin-off of SchlumbergerSema
  • 2006: Axalto and Gemalto merge to become Gemalto
  • 2009: Gemalto buys XIRING’s banking activity
  • 2010: SafeNet buys Aladdin
  • 2010: Gemalto buys Todos AB in Sweden
  • 2015: Gemalto buys SafeNet
I only list the fusions and acquisitions related to smart card reader manufacturers.

VendorID

VendorVendorID# of readers
Total31
Aladdin0x05291
Axalto?1
Gemalto0x08E617
Gemplus0x08E68
SafeNet?1
SchlumbergerSema0x09731
Todos0x0B0C2
Xiring0x0F140

Each USB device is identified by a VendorID.
It looks like Axalto and SafeNet do not have their own VendorID.

Xiring

All the Xiring readers I have in my list are now sold by ingenico Healthcare e-ID (ex Xiring healthcare).
They are available at ingenico technical support page.

So Gemalto bought XIRING’s banking activity but it looks like this division of Xiring had no CCID reader.

Reader list


Aladdin


  1. eToken PRO USB 72K Java (Aladdin_eToken_PRO_USB_72K_Java.txt)


Axalto


  1. Reflex USB v3 (AxaltoV3.txt)


Note that the VendorID used by this reader is 0x04E6 and is the VendorID used by SCM (now Identive) for its readers. I guess the reader is a SCM one rebranded as Axalto.

Gemalto


  1. SA .NET Dual (Gemalto_SA_dotNet_Dual.txt)

  2. Ezio Shield Branch Reader (Gemalto_Ezio_Branch.txt)
  3. Ezio Shield (Gemalto_Ezio_Shield_PinPad.txt)

  4. Ezio Shield (Gemalto_Ezio_Shield.txt)

  5. EZIO CB+ (Gemalto_Ezio_CB+.txt)

  6. ING Shield Pro SC (Gemalto_Ezio_Shield_Secure_Channel.txt)

  7. Ezio Shield Pro SC (Gemalto_Ezio_Shield_Pro_SC.txt)

  8. IDBridge CT30 (Gemalto_IDBridge_CT30.txt)

  9. PDT (Gemalto_PDT.txt)
  10. Hybrid Smartcard Reader (Gemalto_HybridSmartcardReader.txt)
  11. IDBridge K30 (Gemalto_IDBridge_K30.txt)

  12. Smart Enterprise Guardian Secure USB Device (GemaltoSmartEnterpriseGuardian.txt)

  13. USB GemPCPinpad SmartCard Reader (GemPCPinpadv2.txt)

  14. IDBridge K3000 (Gemalto_IDBridge_K3000.txt)

  15. Smart Enterprise Guardian Secure USB Device (Gemalto_SG.txt)

  16. Prox Dual USB PC Link Reader (GemProxDU.txt)

  17. Prox SU USB PC LinkReader (GemProxSU.txt)


Gemplus


  1. Gemplus USB SmartCard Reader 433-Swap (GemPC433_SL.txt)

  2. USB GemPCPinpad SmartCard Reader (GemPCPinpad.txt)

  3. GemCore SIM Pro Smart Card Reader (GemCoreSIMPro.txt)

  4. GemCore POS Pro Smart Card Reader (GemCorePOSPro.txt)
  5. USB Shell Token V2 (GemPCKey.txt)

  6. PC Twin Reader (GemPCTwin.txt)

  7. GemPC Express (GemPC_Express.txt)

  8. Gem e-Seal Pro USB Token (Gem_e-SealPro.txt)

SafeNet


  1. SmartMX Sample (Philips_SmartMX.txt)


Similar remark as for Axalto. Here the iManufacturer is: Philips Semiconductors. The vendorID is 0x04B9 which should be Rainbow Technologies.

SchlumbergerSema


  1. SchlumbergerSema Cyberflex Access (e-gate.txt)

Todos


  1. CX00 (Todos_Cx00.txt)

  2. Argos Mini II (Todos_AGM2_CCID.txt)


Conclusion

After so much fusion and acquisitions in the smart card industry it may be difficult to know where to get manufacturer support for a given reader.

Gemalto provides a drivers support page where you can find most of the "Gemalto" readers.

Tuesday, March 24, 2015

Change syslog logging level on Yosemite

In "Debug a smart card application on Yosemite" we have seen how Apple provides a way to get the ATR and exchanged APDU from the com.apple.ifdreader process (new on Yosemite).

syslog(3)

In some cases you need more than just ATR and APDU. That is why my CCID driver also uses syslog() to log debug messages.

According to syslog(3) manual page syslog() prototype is: void syslog(int priority, const char *message, ...);

The priority parameter is used to tell if the syslog message is important or not. For example messages of level LOG_EMERG are "A panic condition. This is normally broadcast to all users."

You can use the syslog(1) command line tool to log a message. To log an emergency message just do:
$ syslog -s -l 0 Read http://ludovicrousseau.blogspot.fr/
  • -s to send a message
  • -l 0 to use level 0 i.e. Emergency

You should see a message broadcasted in every Terminal console and a message in /var/log/system.log. You can use the Console application to read the /var/log/system.log file.

By default messages with level Info (6) or Debug (7) are just ignored.

Logging low level messages

To log messages of level Info and Debug from the CCID driver you need to tell syslog to accept them. We could change the global configuration to accept debug messages from every running process but that may generate a lot of noise. Each process has its own syslog filter. We will use that feature instead.

First step is to get the process identification (PID) of the com.apple.ifdreader process. I use something like:
$ ps -Aww | grep com.apple.ifdreader
28775 ??         0:00.74 /System/Library/CryptoTokenKit/com.apple.ifdreader.slotd/Contents/MacOS/com.apple.ifdreader
28803 ttys000    0:00.00 grep com.apple.ifdreader

In my case the PID is 28775.

You can see the syslog filter for the process using:
$ syslog -c 28775
Process 28775 syslog filter mask: Off

Change the filter using:
$ sudo syslog -c 28775 -d
-d indicates: set the filter level to cause to log messages from Emergency up to Debug.

And verify the filter has changed:
$ syslog -c 28775 
Process 28775 syslog filter mask: Emergency - Debug

Displaying logs

You can use the Console application to display the logs.

You can also use a command line program with:
$ syslog -w -k Sender com.apple.ifdreader
This will continuously display the log messages from com.apple.ifdreader as they are generated by the driver.

Conclusion

Apple removed the ability to run pcscd in foreground mode from the console on Yosemite because pcscd has been replaced by something different (See "OS X Yosemite and smart cards status").

As we have seen in this article it is still possible to log messages from a smart card reader driver. Using syslog may even be easier to use than restarting the pcscd process.

Thursday, February 26, 2015

Some PC/SC bugs of Yosemite 10.10 fixed in 10.10.2

The 10.10.2 release of Yosemite solves some of the PC/SC bugs introduced in 10.10 and I reported in "OS X Yosemite and smart cards: known bugs".

I updated the main article with the list and also each individual bug documentation.

Maybe the 10.10.3 release will solve the other PC/SC bugs.

Monday, February 23, 2015

Debug a smart card application on Yosemite

In the previous article "Debug a smart card reader driver on Yosemite" I wrote about how to get some log from a new version of my CCID driver.

APDU logging from Apple

After I wrote the previous article Dustin N. told me that Apple now provides a logging facility for APDUs.

SmartCardServices.7

The SmartCardServices manpage says (online HTML version at SmartCardServices):

SMARTCARDSERVICES(7) BSD Miscellaneous Information Manual SMARTCARDSERVICES(7)

NAME

SmartCardServices — overview of smart card support

DESCRIPTION

The SmartCardServices is a set of components which add native support for smart cards
to operating system. Supported smart cards appear as separate keychains.

USB SMART CARD READER DRIVERS

OS X has built-in support for USB CCID class-compliant smart card readers. For other
readers, install the reader driver in /usr/libexec/SmartCardServices/drivers. Each driver
is a bundle. The bundle contains an XML file Info.plist which contains the device’s USB vendor ID and product ID. For detailed description of plist format and how to write driver, see <http://pcsclite.alioth.debian.org/api/group__IFDHandler.html>

SMART CARD APDU LOGGING

It is possible to turn on logging for smart cards. Logging is turned on by setting global preference:
sudo defaults write /Library/Preferences/com.apple.security.smartcard Logging -bool yes
After a smart card reader is connected (or after reboot) all operations including contents of sent and received APDU messages are then logged into system log. Logging uses facility com.apple.security.smartcard.log so it is possible to set up filtering of these logs into custom targets (see asl.conf(5)) Note that logging setting is one-shot; it must be turned on by the command above to start logging again with a new reader. This is to avoid security risk that logging is turned on indefinitely.

SEE ALSO

sc_auth(8), defaults(1), asl.conf(5)

Mac OS X August 5, 2014 Mac OS X

Configuration


As documented the activation of APDU logging is easy. Just do (on 1 line):
$ sudo defaults write /Library/Preferences/com.apple.security.smartcard Logging -bool yes

A new file /Library/Preferences/com.apple.security.smartcard.plist will be created.

You can display the .plist file using Xcode for example. But you can't edit it directly with Xcode since the file can only be updated by root.
$ ls -l /Library/Preferences/com.apple.security.smartcard.plist
-rw-r--r--  1 root  wheel  55 23 fév 10:09 /Library/Preferences/com.apple.security.smartcard.plist

You can get the logging status using:
$ defaults read /Library/Preferences/com.apple.security.smartcard Logging
1
You do not need to be root to read the logging status.

First time only

As indicated in the manpage documentation, you can note that the logging activation is only one shoot. Once the logging state has been read and activated by com.apple.ifdreader then the value is reset to no logging.

To see that just do:
  1. Activate logging
    $ sudo defaults write /Library/Preferences/com.apple.security.smartcard Logging -bool yes
  2. Read logging state
    $ defaults read /Library/Preferences/com.apple.security.smartcard Logging
    1
  3. Plug in a USB reader
  4. Read logging state again
    $ defaults read /Library/Preferences/com.apple.security.smartcard Logging
    0

This is very smart idea. It will prevent you from forgeting to disable logging after use. You can be sure that the logging will be disabled after a reboot or at the next USB reader connection and no secret PIN code will be stored in your log file without you explicitly requesting it.

Sample output

As in "Debug a smart card reader driver on Yosemite" I used a combination of lwatch and ansi2html. If the file foo contains the log lines I use the combination:
$ lwatch -i - < foo | ansi2html -i

$ syslog -w -k Sender com.apple.ifdreader
Feb 23 19:54:49 iMac-de-Ludovic.local com.apple.ifdreader[586] <Notice>: logging slot 'Gemalto PC Twin Reader'
Feb 23 19:54:53 iMac-de-Ludovic.local com.apple.ifdreader[586] <Notice>: card in
Feb 23 19:54:53 iMac-de-Ludovic.local com.apple.ifdreader[586] <Notice>: ATR:3b fa 94 00 00 81 31 20 43 80 65 a2 01 01 01 3d 72 d6 43 21
Feb 23 19:54:58 iMac-de-Ludovic.local com.apple.ifdreader[586] <Notice>: unpower
Feb 23 19:54:59 iMac-de-Ludovic.local com.apple.ifdreader[586] <Notice>: ATR:3b fa 94 00 00 81 31 20 43 80 65 a2 01 01 01 3d 72 d6 43 21
Feb 23 19:54:59 iMac-de-Ludovic.local com.apple.ifdreader[586] <Notice>: T=1
Feb 23 19:54:59 iMac-de-Ludovic.local com.apple.ifdreader[586] <Notice>: APDU ->:00 a4 04 00 0a a0 00 00 00 62 03 01 0c 06 01
Feb 23 19:54:59 iMac-de-Ludovic.local com.apple.ifdreader[586] <Notice>: APDU <-:90 00
Feb 23 19:54:59 iMac-de-Ludovic.local com.apple.ifdreader[586] <Notice>: APDU ->:00 00 00 00
Feb 23 19:54:59 iMac-de-Ludovic.local com.apple.ifdreader[586] <Notice>: APDU <-:48 65 6c 6c 6f 20 77 6f 72 6c 64 21 90 00
Feb 23 19:55:04 iMac-de-Ludovic.local com.apple.ifdreader[586] <Notice>: unpower
Feb 23 19:55:07 iMac-de-Ludovic.local com.apple.ifdreader[586] <Notice>: card out

You can see that the card in inserted at 19:54:53, the log is "card in" And 5 seconds later the card is power off, the log line is "unpower". This is what I already explained in "OS X Yosemite bug: SCardTransmit returns SCARD_W_UNPOWERED_CARD".

Security

Since you need to have the administration privilege (be root) to edit the file /Library/Preferences/com.apple.security.smartcard.plist the situation is not less secure than what I presented in "Debug a smart card reader driver on Yosemite" since you also needed to have the same administration privilege (be root) to edit the driver configuration file /usr/libexec/SmartCardServices/drivers/ifd-ccid.bundle/Contents/Info.plist.

Conclusion

Apple provides a nice way to get the card ATR, APDU sent to the card and response from a smart card reader.

Maybe I should add a similar feature in pcsc-lite for GNU/Linux. What do you think?

Thursday, February 19, 2015

Using cron on Mac OS X

This article is not about smart card. I wrote it to remember how to do and, possibly, help other Mac OS X users.

Mac OS X is a Unix system and so can be used as a Unix system with all the normal commands and services found on a Unix system.

I discovered recently that every thing was installed to use cron on my Mavericks (10.9) system.

cron - daemon to execute scheduled commands

The goal of cron is to run commands periodically. For example your can start a backup command or a Jenkins job on a regular schedule.

Mail configuration

cron sends its output and error messages by email. So you need to have your email configured correctly.

Sending an email

By default email is already working on Mac OS X for a local delivery. You can check it using:
$ date | mail -s test rousseau
Of course you use your own login name instead of rousseau.

This command will send the time and date in an email to rousseau with subject "test".

You should not have any output from the command unless you get an error.

If your mail server require an user authentication you may need to configure your Postfix local configuration.

Reading an email

The same command mail can be used to read emails stored locally.
$ mail
Mail version 8.1 6/6/93.  Type ? for help.
"/var/mail/rousseau": 1 message 1 new
>N  1 rousseau@iMac-de-Lud  Sun Feb 15 13:30  14/538   "test"
? press Enter
Message 1:
From rousseau@iMac-de-Ludovic.local  Sun Feb 15 13:30:01 2015
X-Original-To: rousseau
Delivered-To: rousseau@iMac-de-Ludovic.local
To: rousseau@iMac-de-Ludovic.local
Subject: test
Date: Sun, 15 Feb 2015 13:30:01 +0100 (CET)
From: rousseau@iMac-de-Ludovic.local (Ludovic Rousseau)

Dim 15 fév 2015 13:30:01 CET

? d
? q
$

Here we can read our test email. Then delete it using the "d" command and quit using the "q" command.

Redirecting your emails

Maybe you do not read your email using the mail command on your Mac, me neither. You can redirect your emails using the standard Unix way: a ~/.forward file. This file should contain the email you want to redirect your emails to:
$ cat ~/.forward
ludovic.rousseau@free.fr

Test again to send you an email and check the redirection is working.

Cron configuration

cron uses a crontab to store the user configuration. Each user has its own crontab configuration. Use the shell command crontab to edit the configuration.

vi

crontab uses the editor configured in the EDITOR environment variable or vi by default.

The problem with vi (or vim) is that vi exits with a return value that is considered as an error by crontab:
$ crontab -e
crontab: "vi" exited with status 1
And all your edition is lost.

A solution found at "Error adding cronjobs in Mac OS X Lion" is to use nano instead of vi:
$ EDITOR=nano crontab -e

But I do not like nano and really prefer vim. So another way to solve that is to create a file (you may use the TextEdit graphical application to edit the file but take care to use the Text and not RTF format). I named my file crontab so that vim will do syntax colorization for me.
$ cat Documents/crontab 
# Every hour
0 * * * * echo "pouet"

Then install it using:
$ crontab Documents/crontab

Check your configuration has been accepted using:
$ crontab -l
# Every hour
0 * * * * echo "pouet"

Read the crontab section 5 manual page (man 5 crontab) to know the format to use.

Conclusion

No need to install a graphical tool to periodically run a command on Mac OS X.

Mac OS X is and stays a Unix system under the graphical interface.

Friday, February 13, 2015

Debug a smart card reader driver on Yosemite

Since Mac OS X Yosemite (10.10) the pcscd command is no more present. See "OS X Yosemite and smart cards status" for more details.

The problem is that I used this command to get some debug log from my CCID smart card driver. See "pcscd debug output on Mac OS X". Unfortunately this technique is no more available.

com.apple.ifdreader

The /System/Library/CryptoTokenKit/com.apple.ifdreader.slotd/Contents/MacOS/com.apple.ifdreader father process is by process 1. Process 1 is launchd "System wide and per-user daemon/agent manager".

If I start the command from a Terminal I get no error message, the command does not return but in the /var/log/system.log file I find:
Feb 10 14:49:57 imac com.apple.ifdreader[37446]: assertion failed: 14C109: libxpc.dylib + 34612 [876216DC-D5D3-381E-8AF9-49AE464E5107]: 0x2d
Feb 10 14:49:57 imac com.apple.ifdreader[37446]: Bogus event on event stream listener.

So I think some parameters and/or context is missing.

The process is started by launchd. The configuration file is /System/Library/LaunchDaemons/com.apple.ifdreader.plist. It contains:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
 <key>Label</key>
 <string>com.apple.ifdreader</string>
 <key>RunAtLoad</key>
 <false/>
 <key>EnablePressuredExit</key>
 <true/>
 <key>POSIXSpawnType</key>
 <string>Adaptive</string>
 <key>ProgramArguments</key>
 <array>
  <string>/System/Library/CryptoTokenKit/com.apple.ifdreader.slotd/Contents/MacOS/com.apple.ifdreader</string>
 </array>
 <key>LaunchEvents</key>
 <dict>
  <key>com.apple.iokit.matching</key>
  <dict>
   <key>com.apple.ctk.ifdreader.device</key>
   <dict>
    <key>IOMatchLaunchStream</key>
    <true/>
    <key>IOProviderClass</key>
    <string>IOUSBDevice</string>
   </dict>
  </dict>
 </dict>
</dict>
</plist>

Restarting com.apple.ifdreader

After you changed the driver configuration it may be needed to restart the com.apple.ifdreader process.

First you need to stop the process. You can use:
$ sudo killall -SIGKILL -m .*com.apple.ifdreader

Then you need to restart it. Since most smart card reader are USB devices you just need to plug your USB reader and com.apple.ifdreader is (re)started automatically.

Send logs using syslog(3)

If printf(3) can't be used to log messages then the normal option for a daemon is to use syslog(3).

I modified my CCID driver to log messages using syslog(3). This feature will be available in the CCID driver versions 1.4.19 and later.

Get syslog logs

Now that the messages from the CCID driver are sent somewhere we must get them.

We have two options on Mac OS X: a graphical application or a command line tool.

Console application

Apple provides the Console application in /Applications/Utilities/Console.app.
The application icon is:

The application is easy to use. You can filter the output to only have logs from ifdreader.


syslog -k Sender com.apple.ifdreader

Another opiont is to use the command line tool syslog(1).

$ syslog -w -k Sender com.apple.ifdreader

Arguments:
  • -w
    The -w option causes syslog to wait for new messages. By default, syslog
    prints the last 10 messages, then waits for new messages to be added to
    the data store.
  • -k
    The -k option may be followed by one, two, or three arguments. A single
    argument causes a match to occur if a message has the specified key,
    regardless of value. If two arguments are specified, a match occurs when
    a message has exactly the specified value for a given key. For example,
    to find all messages sent by the portmap process:
    syslog -k Sender portmap

Sample output

I used lwatch to add colors and ansi2html to convert the ANSI color codes to HTML.

Feb 13 14:04:02 iMac-de-Ludovic.local com.apple.ifdreader[6581] <Warning>: 08676368 ifdhandler.c:96:CreateChannelByNameOrChannel() Lun: 0, device: Gemalto PC Twin Reader
Feb 13 14:04:02 iMac-de-Ludovic.local com.apple.ifdreader[6581] <Warning>: 00000110 ccid_usb.c:283:OpenUSBByName() Using: /usr/libexec/SmartCardServices/drivers/ifd-ccid-test-test.bundle/Contents/Info.plist
Feb 13 14:04:02 iMac-de-Ludovic.local com.apple.ifdreader[6581] <Warning>: 00000637 ccid_usb.c:301:OpenUSBByName() ifdManufacturerString: Ludovic Rousseau (ludovic.rousseau@free.fr)
Feb 13 14:04:02 iMac-de-Ludovic.local com.apple.ifdreader[6581] <Warning>: 00000089 ccid_usb.c:302:OpenUSBByName() ifdProductString: Generic CCID driver
Feb 13 14:04:02 iMac-de-Ludovic.local com.apple.ifdreader[6581] <Warning>: 00000075 ccid_usb.c:303:OpenUSBByName() Copyright: This driver is protected by terms of the GNU Lesser General Public License version 2.1, or (at your option) any later
Feb 13 14:04:02 iMac-de-Ludovic.local com.apple.ifdreader[6581] <Warning>: 00177567 ccid_usb.c:595:OpenUSBByName() Found Vendor/Product: 08E6/3437 (Gemalto PC Twin Reader)
Feb 13 14:04:02 iMac-de-Ludovic.local com.apple.ifdreader[6581] <Warning>: 00000078 ccid_usb.c:597:OpenUSBByName() Using USB bus/device: 253/6
Feb 13 14:04:02 iMac-de-Ludovic.local com.apple.ifdreader[6581] <Warning>: 00000063 ccid_usb.c:649:OpenUSBByName() bNumDataRatesSupported is 0
Feb 13 14:04:02 iMac-de-Ludovic.local com.apple.ifdreader[6581] <Warning>: 00010058 commands.c:997:CmdEscapeCheck error on byte 10
Feb 13 14:04:02 iMac-de-Ludovic.local com.apple.ifdreader[6581] <Warning>: 00000082 ccid.c:215:set_gemalto_firmware_features() GET_FIRMWARE_FEATURES failed: 612, len=0
Feb 13 14:04:02 iMac-de-Ludovic.local com.apple.ifdreader[6581] <Warning>: 00000067 ifdhandler.c:375:IFDHGetCapabilities() tag: 0xFAD, Gemalto PC Twin Reader (lun: 0)
Feb 13 14:04:02 iMac-de-Ludovic.local com.apple.ifdreader[6581] <Warning>: 00000072 ifdhandler.c:375:IFDHGetCapabilities() tag: 0x7A007, Gemalto PC Twin Reader (lun: 0)
Feb 13 14:04:02 iMac-de-Ludovic.local com.apple.ifdreader[6581] <Warning>: 00000072 ifdhandler.c:375:IFDHGetCapabilities() tag: 0xFAE, Gemalto PC Twin Reader (lun: 0)
Feb 13 14:04:02 iMac-de-Ludovic.local com.apple.ifdreader[6581] <Warning>: 00000095 ifdhandler.c:463:IFDHGetCapabilities() Reader supports 1 slot(s)
Feb 13 14:04:02 iMac-de-Ludovic.local com.apple.ifdreader[6581] <Warning>: 00001257 ifdhandler.c:1139:IFDHPowerICC() action: Reset, Gemalto PC Twin Reader (lun: 0)
Feb 13 14:04:09 iMac-de-Ludovic.local com.apple.ifdreader[6581] <Warning>: 06859987 ifdhandler.c:1139:IFDHPowerICC() action: Reset, Gemalto PC Twin Reader (lun: 0)

ATR and APDU logging

Using pcscd it was possible to log APDU sent to the card and the response from the card. This service is now missing since pcscd is no more present.

I added a new option to the CCID driver to log this information. Since it is a sensitive information (you can see the PIN code sent to the card for example) you need the administrative privilege and edit the driver configuration file Info.plist. The configuration file should be /usr/libexec/SmartCardServices/drivers/ifd-ccid.bundle/Contents/Info.plist.

The new option value is 0x0080. You should have some thing like:
   <key>ifdDriverOptions</key>
   <string>0x0080</string>

You will get something like:
Feb 13 15:17:04 iMac-de-Ludovic.local com.apple.ifdreader[11365] <Warning>: 00000076 ifdhandler.c:463:IFDHGetCapabilities() Reader supports 1 slot(s)
Feb 13 15:17:11 iMac-de-Ludovic.local com.apple.ifdreader[11365] <Warning>: 06637507 ifdhandler.c:1139:IFDHPowerICC() action: Reset, Gemalto PC Twin Reader (lun: 0)
Feb 13 15:17:11 iMac-de-Ludovic.local com.apple.ifdreader[11365] <Error>: 00055035 commands.c:249:CmdPowerOn Card absent or mute
Feb 13 15:17:11 iMac-de-Ludovic.local com.apple.ifdreader[11365] <Critical>: 00000171 ifdhandler.c:1206:IFDHPowerICC() PowerUp failed
Feb 13 15:17:15 iMac-de-Ludovic.local com.apple.ifdreader[11365] <Warning>: 04106934 ifdhandler.c:1139:IFDHPowerICC() action: Reset, Gemalto PC Twin Reader (lun: 0)
Feb 13 15:17:15 iMac-de-Ludovic.local com.apple.ifdreader[11365] <Error>: 00055041 commands.c:249:CmdPowerOn Card absent or mute
Feb 13 15:17:15 iMac-de-Ludovic.local com.apple.ifdreader[11365] <Critical>: 00000184 ifdhandler.c:1206:IFDHPowerICC() PowerUp failed
Feb 13 15:17:17 iMac-de-Ludovic.local com.apple.ifdreader[11365] <Warning>: 02376603 ifdhandler.c:1139:IFDHPowerICC() action: Reset, Gemalto PC Twin Reader (lun: 0)
Feb 13 15:17:17 iMac-de-Ludovic.local com.apple.ifdreader[11365] <Error>: 00055065 commands.c:249:CmdPowerOn Card absent or mute
Feb 13 15:17:17 iMac-de-Ludovic.local com.apple.ifdreader[11365] <Critical>: 00000146 ifdhandler.c:1206:IFDHPowerICC() PowerUp failed
Feb 13 15:17:19 iMac-de-Ludovic.local com.apple.ifdreader[11365] <Warning>: 01725812 ifdhandler.c:1139:IFDHPowerICC() action: Reset, Gemalto PC Twin Reader (lun: 0)
Feb 13 15:17:19 iMac-de-Ludovic.local com.apple.ifdreader[11365] <Warning>: ATR: 3B FA 94 00 00 81 31 20 43 80 65 A2 01 01 01 3D 72 D6 43 21 
Feb 13 15:17:23 iMac-de-Ludovic.local com.apple.ifdreader[11365] <Warning>: 03997665 ifdhandler.c:682:IFDHSetProtocolParameters() protocol T=1, Gemalto PC Twin Reader (lun: 0)
Feb 13 15:17:23 iMac-de-Ludovic.local com.apple.ifdreader[11365] <Warning>: 00000099 ifdhandler.c:2073:extra_egt() Extra EGT patch applied
Feb 13 15:17:23 iMac-de-Ludovic.local com.apple.ifdreader[11365] <Warning>: 00040776 ifdhandler.c:1286:IFDHTransmitToICC() Gemalto PC Twin Reader (lun: 0)
Feb 13 15:17:23 iMac-de-Ludovic.local com.apple.ifdreader[11365] <Warning>: APDU: 00 A4 04 00 0A A0 00 00 00 62 03 01 0C 06 01 
Feb 13 15:17:23 iMac-de-Ludovic.local com.apple.ifdreader[11365] <Warning>: SW: 90 00 
Feb 13 15:17:23 iMac-de-Ludovic.local com.apple.ifdreader[11365] <Warning>: 00015578 ifdhandler.c:1286:IFDHTransmitToICC() Gemalto PC Twin Reader (lun: 0)
Feb 13 15:17:23 iMac-de-Ludovic.local com.apple.ifdreader[11365] <Warning>: APDU: 00 00 00 00 
Feb 13 15:17:23 iMac-de-Ludovic.local com.apple.ifdreader[11365] <Warning>: SW: 48 65 6C 6C 6F 20 77 6F 72 6C 64 21 90 00 
Feb 13 15:17:24 iMac-de-Ludovic.local com.apple.ifdreader[11365] <Warning>: 01039858 ifdhandler.c:1139:IFDHPowerICC() action: PowerDown, Gemalto PC Twin Reader (lun: 0)

You can note that the card power up failed 3 times.

The log criticality is available. The default level is <Warning> but can be <Error> or <Critical>.

Conclusion

Getting debug logs of the PC/SC layer is sometimes important to find a problem. I had to modify my CCID driver to add a new log mechanism that works on Yosemite.

[UPDATE]

The ATR and APDU logging is no more needed. See "Debug a smart card application on Yosemite".

Monday, February 9, 2015

OS X Yosemite bug: SCardTransmit returns SCARD_W_UNPOWERED_CARD

This is part if the series: "OS X Yosemite and smart cards: known bugs".

SCardTransmit

SCardTransmit() do not work reliably any more on Yosemite. In some cases using 2 PC/SC applications the functions returns SCARD_W_UNPOWERED_CARD (or 0x0x80100067).

Interpretation

My interpretation is that Apple tried to implement a card auto power off mechanism. I added this feature in pcsc-lite version 1.6.5 from 2010. See "Card auto power on and off".

The card auto power off feature is visible with some smart card readers, like the Gemalto PC Twin (renamed PC USB TR and then renamed IDBridge CT30).


The reader has a LED in it. If the LED blinks then the reader is powered.  If the LED is ON then the smart card is powered.

On Mavericks (and the previous versions of Mac OS X) when you insert a card the LED is ON (unless the reader driver is not found) and stays ON until you remove the card.
On Yosemite when you insert a smart card the LED is ON and after 5 seconds the LED blinks.  This indicates that the card is powered for 5 seconds and then the card is powered off. Great.

Bug

The problem is that the Apple code is bogus. When 2 PC/SC applications are using the smart smart card at the same time the 5 seconds delay before powering off the card is started when the first application releases the card, even if the second application still has an access to the smart card.
After the 5 seconds delay the second application will get a SCARD_W_UNPOWERED_CARD error on the next SCardTransmit() call.

It looks like Apple forgot to power off the card only if NO other PC/SC application is using the card, not just after the first SCardDisconnect().

The sleep(5) in the sample code is important. This is the delay needed for the PC/SC layer to decide to power off the card. You can also remove this delay and wait before you press enter to continue the first execution.

See also

Apple bug report #19764910 "PC/SC: SCardTransmit returns SCARD_W_UNPOWERED_CARD"

Sample code

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#ifdef __APPLE__
#include <PCSC/winscard.h>
#include <PCSC/wintypes.h>
#else
#include <winscard.h>
#endif

int main(int argc, const char * argv[]) {
    SCARDCONTEXT hContext;
    LPSTR mszReaders;
    DWORD err = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
    if (err != SCARD_S_SUCCESS) {
        printf("ScardEstablishedContext : %08x\n",err);
  return -1;
    }

 DWORD cchReaders = 0;
 err = SCardListReaders(hContext, "SCard$AllReaders", NULL, &cchReaders);
 if (err != 0) {
  printf("ScardListReaders : %08x\n",err);
  return -1;
 }
 mszReaders = calloc(cchReaders, sizeof(char));
 if (!mszReaders) {
  printf("calloc\n");
  return -1;
 }
 err = SCardListReaders(hContext,"SCard$AllReaders", mszReaders, &cchReaders);
 if (err != SCARD_S_SUCCESS) {
  printf("ScardListReaders : %08x\n",err);
  return -1;
 }

 printf("Reader : %s\n", mszReaders);

 SCARDHANDLE hCard;
 DWORD dwActiveProtocol;
 err = SCardConnect(hContext, mszReaders, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol);
 if (err != SCARD_S_SUCCESS) {
  printf("SCardConnect : %08x\n",err);
  return -1;
 }

 unsigned char cmd[] = {0, 0, 0, 0, 0};
 unsigned char resp[255];
 DWORD resp_len;
 SCARD_IO_REQUEST *pci;

 if (SCARD_PROTOCOL_T0 == dwActiveProtocol)
  pci = SCARD_PCI_T0;
 else
  pci = SCARD_PCI_T1;

 resp_len = sizeof resp;
 err = SCardTransmit(hCard, pci, cmd, sizeof cmd, NULL, resp, &resp_len);
 if (err != SCARD_S_SUCCESS) {
  printf("ScardTransmit: %08x\n",err);
  return -1;
 }
 printf("SCardTransmit: %0X\n", err);

 if (1 == argc)
 {
  printf("Run the second instance\n");
  getchar();
 }

 resp_len = sizeof resp;
 err = SCardTransmit(hCard, pci, cmd, sizeof cmd, NULL, resp, &resp_len);
 if (err != SCARD_S_SUCCESS) {
  printf("ScardTransmit: %08x\n",err);
  return -1;
 }
 printf("SCardTransmit: %0X\n", err);

 SCardDisconnect(hCard, SCARD_LEAVE_CARD);
 SCardReleaseContext(hContext);

 if (argc > 1)
 {
  /* The sleeping time is important here */
  sleep(5);
  printf("Continue the first instance\n");
 }

    return 0;
}

Result (on Yosemite)

$ CFLAGS="-framework PCSC" make main
cc -framework PCSC    main.c   -o main

Since this sample code needs two programs you need to have two Terminal windows opened.
In the first terminal you run ./main and in the second terminal you run ./main a (with an argument).
Once the second execution has finished you press enter in the first terminal to continue the execution of the first program.

1st terminal2nd terminal
$ ./main
Reader : Gemalto PC Twin Reader
SCardTransmit: 0
Run the second instance
$ ./main a
Reader : Gemalto PC Twin Reader
SCardTransmit: 0
SCardTransmit: 0
Continue the first instance
ScardTransmit: 80100067

Expected result (on Debian)

$ CFLAGS=`pkg-config --cflags libpcsclite` LDFLAGS=`pkg-config --libs libpcsclite` make main
cc -pthread -I/usr/include/PCSC    -lpcsclite    main.c   -o main

1st terminal2nd terminal
$ ./main
Reader : Gemalto PC Twin Reader
SCardTransmit: 0
Run the second instance
$ ./main a
Reader : Gemalto PC Twin Reader
SCardTransmit: 0
SCardTransmit: 0
Continue the first instance
ScardTransmit: 0

Known workaround

None known.

One very bad (and untested) solution would be to create an application that sends an APDU (with no side effect) every 3 or 4 seconds so that the 5 seconds delay never occurs. But that is a very very bad solution. And it may be difficult or impossible to find an APDU that would be safe to send at any time.