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.

Wednesday, January 14, 2015

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.

Sunday, January 11, 2015

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.