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 https://blog.apdu.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.

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 <https://pcsclite.apdu.fr/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?

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.

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 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".

[UPDATE 2]

You can change the log level of the com.apple.ifdreader process. See "Change syslog logging level on Yosemite".

OS X Yosemite bug: SCardTransmit returns SCARD_W_UNPOWERED_CARD

This is part of 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"

The bug has been closed by Apple on 8th April 2015 as fixed in 10.10.3.

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 terminal 2nd 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 terminal 2nd 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.

Update

This bug is now fixed in Mac OS X Yosemite 10.10.3.

PCSC sample in Common Lisp

To continue the list of PC/SC wrapper initiated in 2010 with "PC/SC sample in different languages" I now present (or not) a PC/SC sample in Common Lisp.

YstokCard - smart card API

The project is hosted at http://lisp.ystok.ru/ycard/

" YstokCard is a portable Common Lisp library dealing with smart cards.
It allows a Lisp program to interact to integrated chip cards (ICC) and interface devices (IFD, card readers).

Memory cards can securely store relatively small amounts of data. Applications usually require certain conditions to be fulfilled before access to the data is possible, such as a PIN verification or authentication of the card.

Processor cards provide environment for the secure execution of programs. This makes smart cards good candidates for the entire security sector. Additionally, they have a well-established format and are convenient for manual use and handling.

YstokCard can be useful for programming both memory-based and file-based card applications. "

Basic features

  • Class hierarchy for cards and devices.
  • Conventions and macros for defining new card and device types.
  • ATR (Answer-To-Request) converting and analysis.
  • Calls to Smart Card Resource Manager (winscard.dll on Windows, libpcsclite.so on Linux).
  • Helpers like run-length-coding (RLC) etc.

Installation

I tried to install the wrapper on my Debian system with some documentation from the wrapper author himself: Dmitry Ivanov.

I failed to install the wrapper :-(. I am no more a Lisp user and I did not want to invest too much time in setting a working configuration.

Here is the documentation I got from Dmitry Ivanov in case you want to try by yourself:
The wrapper will not work with CLISP but only with:

Build/install means compile and load into a running Lisp system. The
procedure is not a simple "apt-get" call but consists of the manual
operations.

  1. Download zip/tgz bundles for all the dependencies.
  2. Extract all the files.
  3. Load ASDF package manager into the running lisp image by means of
  4. Load all the unzipped ASD-files, i.e. project files, e.g.
    (load "ystok-ffc.asd")
    (load "ystok-library.asd")
    (load "ystokcard.asd")
  5. Evaluate
    (asdf:operate 'asdf:load-op 'ystokcard).

Source code

Since I failed to install the Common Lisp wrapper I could not really write the sample code and test it.

Writing the sample source code is then left as an exercise to the reader :-)

Conclusion

I am sorry I can't really help you on this Common Lisp PC/SC wrapper.

If you are a Common Lisp user I imagine you will succeed in installing the wrapper correctly and using it for your project.

Even if I failed to install it myself I wanted to let you know that a Common Lisp wrapper exist for PC/SC.

PCSC sample in PHP5

In PC/SC sample in different languages I "promised" to give the implementation of the same sample program in many different programming languages.

SCardSCR

In a previous article "PCSC sample in PHP" I wrote about SCardSCR.

SCardSCR is a project for Windows by Johann Dantant. The project web site is no more available because the domain name www.waazaa.org do not exist any more.

A user reported the problem to me and asked where the web site was available. I used a web search service to find were the project SCardSCR had been moved but I found a new PHP PC/SC wrapper instead.

PC/SC for PHP

PC/SC for PHP is the continuation of SCardSCR by Marco Schuster and Johannes Findeisen and is licensed under the PHP license:
This code is licensed under the terms of the PHP License version 3.01. PCSC-Lite is licensed in a way where it is possible to integrate it native in the PHP environment.

The project is hosted at http://hanez.org/pcsc-for-php.html and is also available at http://pecl.php.net/package/pcsc.

From the project About section:
This is the only extension for using PC/SC based smart cards with PHP. It is a wrapper to the wonderful and free project PCSC-Lite which is the middleware to access a smart card using SCard API (PC/SC). Since PCSC-Lite is compatible to the winscard API it should be possible to compile this extension using a Windows(R) operating system. Currently I only take focus on Linux environments.

Thanks are going to Johann Dantant! He provides a PC/SC extension for PHP since 2005 and I reused some of his code. He allowed me to relicense these parts under the terms of the PHP license so I could integrate PCSC-Lite natively into PHP. You find his work here.
Latest version is 0.3 released 2014-04-23

Since the project is hosted inside the PECL (PHP Extension Community Library) I guess/hope the "PC/SC for PHP" project will not disapear soon. From http://pecl.php.net/
PECL is a repository for PHP Extensions, providing a directory of all known extensions and hosting facilities for downloading and development of PHP extensions.

API

The API is documented at PC/SC for PHP - An extension for PHP using the winscard PC/SC API.

I note some missing PC/SC features:

Bug

I had to patch the code to add support of T=0 cards.
Index: pcsc.c
===================================================================
--- pcsc.c (révision 335717)
+++ pcsc.c (copie de travail)
@@ -590,7 +590,7 @@ PHP_FUNCTION(scard_list_readers)
    Return a handle to the card */
 PHP_FUNCTION(scard_connect)
 {
-  DWORD dwPreferredProtocol = SCARD_PROTOCOL_T1; 
+  DWORD dwPreferredProtocol = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1; 
   DWORD dwCurrentProtocol;
   SCARDHANDLE hCard = 0;
   LONG rc = 0;

Installation

The installation on Debian is quiet easy.

I had to install the Debian packages:
  • php-pear to get the pecl(1) command
  • php5-dev to get the phpize(1) command (prepare a PHP extension for compiling)

$ sudo pecl install pcsc-alpha
downloading pcsc-0.3.tgz ...
Starting to download pcsc-0.3.tgz (8,939 bytes)
.....done: 8,939 bytes
4 source files, building
running: phpize
Configuring for:
PHP Api Version:         20131106
Zend Module Api No:      20131226
Zend Extension Api No:   220131226
building in /tmp/pear/temp/pear-build-rootMiAGhV/pcsc-0.3
running: /tmp/pear/temp/pcsc/configure
checking for grep that handles long lines and -e... /bin/grep
checking for egrep... /bin/grep -E
checking for a sed that does not truncate output... /bin/sed

[...]

libtool: finish: PATH="/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/sbin" ldconfig -n /tmp/pear/temp/pear-build-rootMiAGhV/pcsc-0.3/modules
----------------------------------------------------------------------
Libraries have been installed in:
   /tmp/pear/temp/pear-build-rootMiAGhV/pcsc-0.3/modules

If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR'
flag during linking and do at least one of the following:
   - add LIBDIR to the `LD_LIBRARY_PATH' environment variable
     during execution
   - add LIBDIR to the `LD_RUN_PATH' environment variable
     during linking
   - use the `-Wl,-rpath -Wl,LIBDIR' linker flag
   - have your system administrator add LIBDIR to `/etc/ld.so.conf'

See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
----------------------------------------------------------------------

Build complete.
Don't forget to run 'make test'.

running: make INSTALL_ROOT="/tmp/pear/temp/pear-build-rootMiAGhV/install-pcsc-0.3" install
Installing shared extensions:     /tmp/pear/temp/pear-build-rootMiAGhV/install-pcsc-0.3/usr/lib/php5/20131226/
Installing header files:          /tmp/pear/temp/pear-build-rootMiAGhV/install-pcsc-0.3/usr/include/php5/
running: find "/tmp/pear/temp/pear-build-rootMiAGhV/install-pcsc-0.3" | xargs ls -dils
305074  4 drwxr-xr-x 3 root root  4096 janv. 11 14:21 /tmp/pear/temp/pear-build-rootMiAGhV/install-pcsc-0.3
305078  4 drwxr-xr-x 4 root root  4096 janv. 11 14:21 /tmp/pear/temp/pear-build-rootMiAGhV/install-pcsc-0.3/usr
305082  4 drwxr-xr-x 3 root root  4096 janv. 11 14:21 /tmp/pear/temp/pear-build-rootMiAGhV/install-pcsc-0.3/usr/include
305083  4 drwxr-xr-x 2 root root  4096 janv. 11 14:21 /tmp/pear/temp/pear-build-rootMiAGhV/install-pcsc-0.3/usr/include/php5
276538  4 -rw-r--r-- 1 root root  1238 janv. 11 14:21 /tmp/pear/temp/pear-build-rootMiAGhV/install-pcsc-0.3/usr/include/php5/php_pcsc.h
305079  4 drwxr-xr-x 3 root root  4096 janv. 11 14:21 /tmp/pear/temp/pear-build-rootMiAGhV/install-pcsc-0.3/usr/lib
305080  4 drwxr-xr-x 3 root root  4096 janv. 11 14:21 /tmp/pear/temp/pear-build-rootMiAGhV/install-pcsc-0.3/usr/lib/php5
305081  4 drwxr-xr-x 2 root root  4096 janv. 11 14:21 /tmp/pear/temp/pear-build-rootMiAGhV/install-pcsc-0.3/usr/lib/php5/20131226
276304 60 -rwxr-xr-x 1 root root 60896 janv. 11 14:21 /tmp/pear/temp/pear-build-rootMiAGhV/install-pcsc-0.3/usr/lib/php5/20131226/pcsc.so

Build process completed successfully
Installing '/usr/lib/php5/20131226/pcsc.so'
Installing '/usr/include/php5/php_pcsc.h'
install ok: channel://pecl.php.net/pcsc-0.3
configuration option "php_ini" is not set to php.ini location
You should add "extension=pcsc.so" to php.ini

I had to edit the file /etc/php5/cli/php.ini to change the enable_dl definition:
; Whether or not to enable the dl() function.  The dl() function
; does NOT work properly in multithreaded servers, such as IIS or Zeus,
; and is automatically disabled on them.
; http://php.net/enable-dl
;enable_dl = Off
enable_dl = On

Source code

<?php

if (!extension_loaded('pcsc')) {
  dl('pcsc.so');
}

# Get a PC/SC context
$context = scard_establish_context();
//var_dump($context);

# Get the reader list
$readers = scard_list_readers($context);
//var_dump($readers);

# Use the first reader
$reader = $readers[0];
echo "Using reader: ", $reader, "\n";

# Connect to the card
$connection = scard_connect($context, $reader);
//var_dump($connection);

# Select Applet APDU
$CMD = "00A404000AA00000006203010C0601";
$res = scard_transmit($connection, $CMD);
var_dump($res);

# test APDU
$CMD = "00000000";
$res = scard_transmit($connection, $CMD);
var_dump($res);
echo pack("H*", $res), "\n";

# Release the PC/SC context
scard_release_context($context);

?>

Output

$ php sample.php 
Using reader: Gemalto PC Twin Reader 00 00
string(4) "9000"
string(28) "48656C6C6F20776F726C64219000"
Hello world!�

Conclusion

I have only tested the wrapper using the command line php5 program. I guess the wrapper should also be available from a PHP script in a HTML page hosted by a web server. In that case the PC/SC commands are executed on the server. I don't know what it can be used for. In general you want to use the smart card on the client side.

Happy hacking with this PHP PC/SC wrapper.

OS X Yosemite bug: T=0 is used instead of T=1 on dual protocol cards

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

SCardConnect(..., SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, ...)

SCardConnect() has changed its preferred protocol on Yosemite.

If a smart card can do both protocols T=0 and T=1 it is possible to let SCardConnect() select the active protocol. T=1 has some advantages over T=0 (transparent support of extended APDU for example) so it is a good idea for a PC/SC layer to prefer T=1 over T=0.

On Mavericks (Mac OS X 10.9) the T=1 protocol was preferred over T=0. On Yosemite this has changed and T=0 is preferred now.

It is not really a bug since by using SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1 the application explicitly let the PC/SC layer to select the protocol. But it is a change compared to the previous OS X version and can be considered a regression.

I guess the behaviour change is due to the major rewrite of the PC/SC layer in Yosemite. See "OS X Yosemite and smart cards status".

ATR parsing

You can use my online ATR (Answer To Reset) parsing tool at Smart card ATR parsing. For my tests I use a smart card with the ATR: 3B D6 18 00 80 B1 80 6D 1F 03 80 51 00 61 10 30 9E. You can see the ATR parsing results at http://smartcard-atr.appspot.com/parse?ATR=3BD6180080B1806D1F038051006110309E.

In the case of my smart card you can see from the parsing results that both protocols are supported:
[...]
TD(1) = 0x80 Y(i+1) = b1000, Protocol T=0
----
TD(2) = 0xB1 Y(i+1) = b1011, Protocol T=1
[...]


See also

Apple bug report #19384330 "PC/SC SCardConnect(): T=0 is used instead of T=1 on dual protocol cards". Closed by Apple, 9th January 2015, as a duplicated of #18567029.

Sample code

The sample code does:
  1. connect using SCardConnect(..., SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, ...)
  2. display the protocol selected by SCardConnect()
  3. display the ATR so you can feed it to Smart card ATR parsing

#include <stdio.h>
#include <stdlib.h>
#include <string.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: 0x%08x\n",err);
  return -1;
 }

 printf("Prococol: ");
 switch(dwActiveProtocol)
 {
  case SCARD_PROTOCOL_T0:
   printf("SCARD_PROTOCOL_T0\n");
   break;
  case SCARD_PROTOCOL_T1:
   printf("SCARD_PROTOCOL_T1\n");
   break;
  default:
   printf("unknown\n");
 }

 char name[100];
 DWORD len = sizeof name;
 DWORD dwState, dwProtocol;
 unsigned char atr[MAX_ATR_SIZE];
 DWORD atr_len = sizeof atr;
 err = SCardStatus(hCard, name, &len, &dwState, &dwProtocol, atr, &atr_len);
 if (err != SCARD_S_SUCCESS) {
  printf("SCardStatus: 0x%08x\n",err);
  return -1;
 }
 printf("ATR: ");
 for (int i=0; i<atr_len; i++)
  printf("%02X ", atr[i]);
 printf("\n");

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

    return 0;
}

Result (on Yosemite)

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

$ ./main
Reader : Gemalto PC Twin Reader
Prococol: SCARD_PROTOCOL_T0
ATR: 3B D6 18 00 80 B1 80 6D 1F 03 80 51 00 61 10 30 9E

T=0 (SCARD_PROTOCOL_T0) has been selected.

Expected result (on Mavericks)

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

$ ./main
Reader : Gemplus GemPC Twin 00 00
Prococol: SCARD_PROTOCOL_T1
ATR: 3B D6 18 00 80 B1 80 6D 1F 03 80 51 00 61 10 30 9E

T=1 (SCARD_PROTOCOL_T1) has been selected.

Known workaround

Force the use of T=1 only on dual protocol cards it you really want to use T=1 instead of T=0.

You have to parse the ATR to know if the card supports T=0 and/or T=1. This is not an easy task. Maybe it is simpler to first call SCardConnect(..., SCARD_PROTOCOL_T1, ...) and if that fails call SCardConnect(..., SCARD_PROTOCOL_T0, ...).

Note that in case of protocol not supported the error returned is SCARD_E_NOT_TRANSACTED on Yosemite but SCARD_E_PROTO_MISMATCH on Mavericks. See OS X Yosemite bug: SCARD_E_PROTO_MISMATCH not returned.

Update

This bug is now fixed in Mac OS X Yosemite 10.10.2.

OS X Yosemite bug: SCARD_E_PROTO_MISMATCH not returned

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

SCARD_E_PROTO_MISMATCH not returned by SCardConnect()

In case of card communication protocol not supported, SCardConnect() returns the error SCARD_E_NOT_TRANSACTED on Yosemite but the error code is SCARD_E_PROTO_MISMATCH on Mavericks (and also on pcsc-lite on GNU/Linux).

This is a regression from Mavericks. I guess the same problem is also present with SCardReconnect().

SCARD_E_NOT_TRANSACTED should not be the error code for any error. SCARD_E_PROTO_MISMATCH is the correct error code to return in this case.

See also

Apple bug report #19384251 "PC/SC: SCARD_E_PROTO_MISMATCH not returned by SCardConnect()". Closed by Apple, 9th January 2015, as a duplicated of #18689292.

Sample code

The sample code uses SCardConnect(.., SCARD_PROTOCOL_T1, ..) to force the use of T=1. If you insert a T=0 only card you will get an error code from SCardConnect().

#include <stdio.h>
#include <stdlib.h>
#include <string.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_T1, &hCard, &dwActiveProtocol);
 if (err != SCARD_S_SUCCESS) {
  printf("SCardConnect: 0x%08x\n",err);
  return -1;
 }

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

    return 0;
}

Result (on Yosemite)

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

$ ./main
Reader : Gemalto PC Twin Reader
SCardConnect: 0x80100016

0x80100016 is SCARD_E_NOT_TRANSACTED.

Expected result (on Mavericks)

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

$ ./main
Reader : Gemplus GemPC Twin 00 00
SCardConnect: 0x8010000f

0x8010000f is SCARD_E_PROTO_MISMATCH.

Known workaround

You should expect the error SCARD_E_NOT_TRANSACTED instead of SCARD_E_PROTO_MISMATCH on Yosemite.

On Yosemite it is no more possible to decide if SCARD_E_NOT_TRANSACTED is returned because the requested protocol is not supported or because another error has occurred.

Update

This bug is now fixed in Mac OS X Yosemite 10.10.2.