Friday, December 25, 2015

New version of pcsc-lite: 1.8.15

I just released a new version of pcsc-lite 1.8.15.
pcsc-lite is a Free Software implementation of the PC/SC (or WinSCard) API for Unix systems.

Changes:
1.8.15: Ludovic Rousseau
25 December 2015
  • Add support of remove and/or customize PC/SC reader names using
    PCSCLITE_FILTER_IGNORE_READER_NAMES and PCSCLITE_FILTER_EXTEND_READER_NAMES
    See "Remove and/or customize PC/SC reader names"
  • Some other minor improvements and bug corrections

Apple PC/SC: blog articles about missing features

You may have noticed that I wrote 3 blog articles about missing features in the PC/SC layer from Apple.
  1. SCardGetStatusChange() and number of card events
  2. SCardGetStatusChange() and "\\?PnP?\Notification"
  3. add support of TAG_IFD_POLLING_THREAD_WITH_TIMEOUT

This is because Apple replaced pcsc-lite by something else in Yosemite (10.10) and improved it in El Capitan (10.11). I imagine that Apple is still working on this software and it is the good time to propose to Apple to implement features that are present in PC/SC on GNU/Linux and Windows but not (yet) on Mac OS X.

If you think these features are useful you should open bug reports at https://bugreport.apple.com. This will indicate that a feature is important for many users, and not just me. If more users create a bug report then priority for Apple to do something will be higher.

Of course, I would be happy to help Apple implement the missing features.

OS X El Capitan missing feature: add support of TAG_IFD_POLLING_THREAD_WITH_TIMEOUT

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

This is not a bug since this feature was never present in any PC/SC from Apple.

com.apple.ifdreader.slotd does not support TAG_IFD_POLLING_THREAD_WITH_TIMEOUT  and friends

The equivalent of pcscd on Mac OS X since Yosemite (10.10) is com.apple.ifdreader.slotd. See "OS X Yosemite and smart cards status". This process is in charge of loading the smart card reader driver. The API between pcscd or com.apple.ifdreader.slotd and the driver is defined in IFDHandler API.

The IFDHandler API evolved during the development of pcsc-lite and the CCID driver to support new features. Apple forked pcsc-lite in 2002 (see "Evolution of Apple pcsc-lite (from Jaguar to Mavericks)") and never merged back the changes I made in pcsc-lite and the IFDHandler API since that time.

Card status polling

In the early versions of pcsc-lite (when the smart card readers where using a RS 232 serial port because USB was not invented yet) the card state (card present or card absent) was checked using a regular polling (every 200 ms) of the reader. Every 200 ms a command is sent to the reader to know if a card is present or not.

The problem is that pcscd is then continuously running (and pcscd was reported by the powertop tool as one of the processes that prevent the CPU to sleep and consume less power)

Another problem is that you have to wait up to 200 ms to detect that a card has been inserted or removed in a reader.

Polling replaced

The CCID specification provides a way to indicate that a card event occurred. This mechanism uses an USB interrupt end point. See "New CCID 1.4.0 and card movement notification mechanism" for more details.

The new mechanism, introduced in the pcsc-lite and the CCID driver 2010, allows to let libusb-1.0 notify the driver that a card event occurred. The change was introduced in the CCID driver version 1.4.0 (with the update from libusb-0.1 to libusb-1.0) and in pcsc-lite 1.6.2 released at the same time.

The mechanism uses the IFDHandler function IFDHGetCapabilities to request the driver about three features:

This allows pcscd to delegate to the driver the cart event management. pcscd will call a function in the driver that will block until a card event occurs or the timeout expires.

Benefits to implement it

If such a mechanism is implemented by Apple in com.apple.ifdreader.slotd we could have, at least, three benefits.
  1. better reactivity when a smart card is inserted (or removed)
  2. lower CPU power consumption
  3. far less log messages when you debug a smart card driver (mostly useful to smart card reader driver developers ☺)

See also

Apple bug report #24009313 "PC/SC: com.apple.ifdreader.slotd does not support TAG_IFD_POLLING_THREAD_WITH_TIMEOUT and friends"

Closed by Apple on 19th January 2016 as a duplicate of 17534485.

Sample code

I do not provide code sample. It is an internal implementation issue with no impact on the PC/SC API.

Known workaround

None known. It is not an PC/SC API issue.

Monday, December 21, 2015

Remove and/or customize PC/SC reader names

The need

In some cases you need to control the smart card reader names reported by PC/SC.

For real examples see some requests sent on the Pcsclite-muscle mailing list: "Possibility to disable Reader Interface?", "Deny card access for one application" and "Dynamically disable/enable specific card reader".

Ignore some readers

For example imagine you have a laptop with 2 integrated smart card readers:
  • Broadcom Corp 5880 [Contacted SmartCard] (0123456789ABCD)
  • Broadcom Corp 5880 [Contactless SmartCard] (0123456789ABCD)
One reader is contactless but you do not use it. The other is a contact reader and should be the only one used but the users of the laptop.
To ease the life of the users you do not want them to have to select the contact reader each time an application has to use a reader and ask the user to select one.

Since the readers are integrated into the laptop you can't easily unplug the reader you don't want to use. You need a solution to ignore unwanted readers at the PC/SC level.

Extend reader names

In this use case you use a remote desktop solution (RDP) to access a Windows server from your GNU/Linux laptop. Your company has equipped users with the same laptop model. So at the PC/SC level all the readers have the same name and this PC/SC name is forwarded to Windows through RDP.

Now imagine a bogus application on the Windows server (not too hard to imagine a bogus application on Windows ☺) that uses the PC/SC reader name to identify a user. Since every user is using the same laptop model they will all have the same PC/SC reader name in Windows. And the bogus Windows application is broken ☹ and can't be used.

The proposed solution

To enable these two features you need to configure pcsc-lite with --enable-filter.

Ignore some readers

If the environment variable PCSCLITE_FILTER_IGNORE_READER_NAMES is defined then it contains a list of patterns separated by the character ":".
If a pattern is found in a PC/SC reader name then this reader is ignored and will not be reported by SCardListReaders() or any other PC/SC calls.

In the example described above you would define PCSCLITE_FILTER_IGNORE_READER_NAMES as: "Contactless".

Extend reader names

To differentiate the PC/SC reader names one idea is to use the host name of the system. If the IT department is doing correctly his job every laptop should have a different host name.

If the environment variable PCSCLITE_FILTER_EXTEND_READER_NAMES is defined then it contains a string that will be added at the end of the PC/SC reader names.
The computer host name is available in the variable $HOSTNAME. If you want to have a space character between the PC/SC reader name and host name you define PCSCLITE_FILTER_EXTEND_READER_NAMES as:
" $HOSTNAME".

Setup

The Debian init script for pcscd contains:

NAME=pcscd
# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME

You then just have to create a file /etc/default/pcscd containing:
PCSCLITE_FILTER_IGNORE_READER_NAMES="Contactless"
PCSCLITE_FILTER_EXTEND_READER_NAMES=" $HOSTNAME"
And you are good to go.

GNU/Linux systems using systemd will need a different configuration. The systemd configuration is left as an exercise for the reader.

Conclusion

These new features will be provided in the next version of pcsc-lite.

If you have another special feature request for pcsc-lite, please do not hesitate to contact me.

Thanks

Thanks to Sparkasse Pforzheim Calw for the patch.

Saturday, December 19, 2015

OS X El Capitan missing feature: SCardGetStatusChange() and "\\?PnP?\Notification"

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

SCardGetStatusChange() does not support "\\?PnP?\Notification"

SCardGetStatusChange() does not support the special reader name "\\?PnP?\Notification".

This is not a bug since this feature was never present in any PC/SC from Apple.

From the Doxygen documentation of pcsc-lite:
To wait for a reader event (reader added or removed) you may use the special reader name "\\?PnP?\Notification".
If a reader event occurs the state of this reader will change and the bit SCARD_STATE_CHANGED will be set.
With this feature it is possible to detect that a smart card reader has been added or removed to the system without polling with calls to SCardListReaders() in a loop.

This is used by my tools pcsc_scan from the pcsc-tools package.

See also

Apple bug report #23966225 "PC/SC SCardGetStatusChange() and "\\?PnP?\Notification""

Sample code

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

int main(void)
{
    SCARDCONTEXT hContext;
    LPSTR mszReaders;
    DWORD err = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL,
        &hContext);
    if (err != SCARD_S_SUCCESS)
    {
        printf("ScardEstablishedContext: 0x%08x\n",err);
        return -1;
    }

    SCARD_READERSTATE rgReaderStates[1];
    rgReaderStates[0].szReader = "\\\\?PnP?\\Notification";
    rgReaderStates[0].dwCurrentState = SCARD_STATE_UNAWARE;
    rgReaderStates[0].dwEventState = SCARD_STATE_UNKNOWN;

    err = SCardGetStatusChange(hContext, 10, rgReaderStates, 1);
    printf("SCardGetStatusChange: %s (0x%08X)\n", pcsc_stringify_error(err),
        err);
    printf("dwEventState: %X\n", rgReaderStates[0].dwEventState);

    if (rgReaderStates[0].dwEventState & SCARD_STATE_UNKNOWN)
        printf("\\\\?PnP?\\Notification is NOT supported\n");
    else
        printf("\\\\?PnP?\\Notification IS supported\n");

    SCardReleaseContext(hContext);

    return 0;
}

Result (on El Capitan)

$ CFLAGS="-framework PCSC" make main
cc -framework PCSC    main.c   -o main
$ ./main
SCardGetStatusChange: Command successful. (0x00000000)
dwEventState: 6
\\?PnP?\Notification is NOT supported
The returned value for dwEventState is 6 and correspond to SCARD_STATE_CHANGED (2) + SCARD_STATE_UNKNOWN (4). PC/SC indicates that the reader "\\?PnP?\Notification" is unknown.

Note that SCardGetStatusChange() returns SCARD_S_SUCCESS and also waited for the indicated time, here 10 ms but you can increase the value to make the test more explicit.
The command should have returned immediately (or have returned SCARD_E_TIMEOUT). Yes, it is a bug in the PC/SC layer.

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
$ ./main
SCardGetStatusChange: Command timeout. (0x8010000A)
dwEventState: 0
\\?PnP?\Notification IS supported
Here the command returns after the delay has expired because no reader has been connected or removed. The returned value is SCARD_E_TIMEOUT.
If a reader is connected or removed during the delay (here 10 ms) the command would have indicated SCARD_STATE_CHANGED for this reader.

Known workaround

None known.
Maybe Apple will add support of "\\?PnP?\Notification" one day.

Thursday, December 17, 2015

OS X El Capitan missing feature: SCardGetStatusChange() and number of card events

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

SCardGetStatusChange() and number of card events

SCardGetStatusChange() does not return the number of card events in the upper word of dwEventState.

This is not a bug since I don't think this feature was every present in the PC/SC from Apple. It is a feature request and not a bug report.

From the Doxygen documentation of pcsc-lite:
dwEventState also contains a number of events in the upper 16 bits (dwEventState & 0xFFFF0000). This number of events is incremented for each card insertion or removal in the specified reader. This can be used to detect a card removal/insertion between two calls to SCardGetStatusChange().
This behaviour is also present in PC/SC on Windows.

It is the only way to know that the card has been removed from a reader and inserted again while no call to SCardGetStatusChange() was running. Potentially the inserted card is not the same as the removed card so the PC/SC application may have to build a new applicative context for the new card.

See also

Apple bug report #23937633 "PC/SC SCardGetStatusChange() and number of card events"

Sample code

Using the Python PC/SC wrapper PySCard to have a shorter code.

#! /usr/bin/env python

from smartcard.scard import *
from smartcard.pcsc.PCSCExceptions import *


def parseEventState(eventstate):
    stateList = list()
    states = {SCARD_STATE_IGNORE: "Ignore",
              SCARD_STATE_CHANGED: "Changed",
              SCARD_STATE_UNKNOWN: "Unknown",
              SCARD_STATE_UNAVAILABLE: "Unavailable",
              SCARD_STATE_EMPTY: "Empty",
              SCARD_STATE_PRESENT: "Present",
              SCARD_STATE_ATRMATCH: "ATR match",
              SCARD_STATE_EXCLUSIVE: "Exclusive",
              SCARD_STATE_INUSE: "In use",
              SCARD_STATE_MUTE: "Mute"}
    for state in states:
        if eventstate & state:
            stateList.append(states[state])
    return stateList

hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER)
if hresult != SCARD_S_SUCCESS:
    raise EstablishContextException(hresult)

hresult, readers = SCardListReaders(hcontext, [])
if hresult != SCARD_S_SUCCESS:
    raise ListReadersException(hresult)
print 'PC/SC Readers:', readers

readerstates = {}
for reader in readers:
    readerstates[reader] = (reader, SCARD_STATE_UNAWARE)
hresult, newstates = SCardGetStatusChange(hcontext, 0, readerstates.values())
if hresult != SCARD_S_SUCCESS:
    raise BaseSCardException(hresult)
print newstates
for readerState in newstates:
    readername, eventstate, atr = readerState
    readerstates[readername] = (readername, eventstate)

print "Move the smart card"

ok = True
while ok:
    try:
        hresult, newstates = SCardGetStatusChange(hcontext, INFINITE, newstates)
        if hresult != SCARD_S_SUCCESS and hresult != SCARD_E_TIMEOUT:
            raise BaseSCardException(hresult)
    except KeyboardInterrupt:
        ok = False
    for readerState in newstates:
        readername, eventstate, atr = readerState
        states = parseEventState(eventstate)
        print states, hex(eventstate)

hresult = SCardReleaseContext(hcontext)
print "SCardReleaseContext()", SCardGetErrorMessage(hresult)
if hresult != SCARD_S_SUCCESS:
    raise ReleaseContextException(hresult)

Result (on El Capitan)

$ ./SCardGetStatusChange.py
PC/SC Readers: ['Gemalto PC Twin Reader']
[('Gemalto PC Twin Reader', 18, [])]
Move the smart card
['Changed', 'Present'] 0x22
['Empty', 'Changed'] 0x12
['Changed', 'Present'] 0x22
['Empty', 'Changed'] 0x12
^C['Empty', 'Changed'] 0x12
SCardReleaseContext() Command successful.

For the tests I insert and remove the card 2 times.

Then press Control-C and insert the card to quit the program.

Expected result (on Debian)

$ ./SCardGetStatusChange.py 
PC/SC Readers: ['Gemalto PC Twin Reader 00 00']
[('Gemalto PC Twin Reader 00 00', 18, [])]
Move the smart card
['Changed', 'Present'] 0x10022
['Empty', 'Changed'] 0x20012
['Changed', 'Present'] 0x30022
['Empty', 'Changed'] 0x40012
^C['Empty', 'Changed'] 0x40012
SCardReleaseContext() Command successful.

The change is the value eventstate displayed (in hexadecimal).

On Debian the high word (upper 16 bits) takes the values 1, 2, 3 and 4.

If the value change from 0x10022 to 0x30022, the reader state is the same (SCARD_STATE_CHANGED and SCARD_STATE_PRESENT) but you know that the card has been removed and inserted.

Known workaround

None known.

Tuesday, December 15, 2015

OS X El Capitan bug: SCardBeginTransaction() returns different error codes than on GNU/Linux and Windows

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

SCardBeginTransaction() returns different error codes than on GNU/Linux and Windows

I found 2 cases in which SCardBeginTransaction() on El Capitan returns error codes that are different than on GNU/Linux and Windows.

SCardBeginTransaction() returns SCARD_W_RESET_CARD after a card change

On El Capitan SCardBeginTransaction() returns SCARD_W_RESET_CARD if the card has been removed and inserted again in the reader.

On GNU/Linux and Windows SCardBeginTransaction() returns SCARD_W_REMOVED_CARD instead.

SCardBeginTransaction() returns SCARD_W_UNPOWERED_CARD after a card is unpowered

The same function SCardBeginTransaction() returns SCARD_W_UNPOWERED_CARD on Mac OS X El Capitan if the card has been powered off by another application.

On GNU/Linux and Windows SCardBeginTransaction() returns SCARD_W_RESET_CARD instead.

See also

Apple bug report #23900844 "PC/SC SCardBeginTransaction() returns different error codes than on GNU/Linux and Windows"

Sample code

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

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

#define pcsc_error(fct) printf(fct ": %s 0x%08lX\n", pcsc_stringify_error(err), (long)err)

int main(void)
{
 LPSTR mszReaders;
 DWORD err, cchReaders = 0;
 SCARDCONTEXT hContext = 0;
 SCARDHANDLE hCard = 0;

 err = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
 if (err != SCARD_S_SUCCESS) {
  pcsc_error("ScardEstablishedContext");
  return -1;
 }

 err = SCardListReaders(hContext, NULL, NULL, &cchReaders);
 if (err != 0) {
  pcsc_error("ScardListReaders");
  return -1;
 }
 mszReaders = calloc(cchReaders, sizeof(char));
 if (!mszReaders) {
  printf("calloc\n");
  return -1;
 }
 err = SCardListReaders(hContext,NULL, mszReaders, &cchReaders);
 if (err != SCARD_S_SUCCESS) {
  pcsc_error("ScardListReaders");
  return -1;
 }

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

 DWORD dwActiveProtocol;
 err = SCardConnect(hContext, mszReaders, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol);
    if (err != SCARD_S_SUCCESS) {
        pcsc_error("SCardConnect");
        return 0;
    }

 printf("Remove and insert the card. Then press enter\n");
 getchar();

 err = SCardBeginTransaction(hCard);
 if (err != SCARD_S_SUCCESS)
  pcsc_error("SCardBeginTransaction");

 err = SCardDisconnect(hCard, SCARD_LEAVE_CARD);
 if (err != SCARD_S_SUCCESS)
  pcsc_error("SCardDisconnect");

 SCardReleaseContext(hContext);

 return 0;
}

Reset program

Using the Python PC/SC wrapper PySCard to have a shorter code.

#! /usr/bin/env python

from smartcard.System import readers
from smartcard.scard import SCARD_UNPOWER_CARD, SCARD_RESET_CARD

reader = readers()[0]
print "Using:", reader

connection = reader.createConnection()
#connection.connect(disposition=SCARD_RESET_CARD)
connection.connect(disposition=SCARD_UNPOWER_CARD)

If you modify the reset program to use disposition=SCARD_RESET_CARD then SCardBeginTransaction() will return SCARD_W_RESET_CARD as is also the case on GNU/Linux and Windows.

Result (on El Capitan)

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

$ ./main
Using reader: Gemalto PC Twin Reader
Remove and insert the card. Then press enter

SCardBeginTransaction: Card was reset. 0x80100068

In case of unpower (instead of card removal) by a second application:
$ ./main
Using reader: Gemalto PC Twin Reader
Remove and insert the card. Then press enter

SCardBeginTransaction: Card is unpowered. 0x80100067

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

$ ./main
Using reader: Gemalto PC Twin Reader 00 00
Remove and insert the card. Then press enter

SCardBeginTransaction: Card was removed. 0x80100069

In case of unpower:
$ ./main
Using reader: Gemalto PC Twin Reader 00 00
Remove and insert the card. Then press enter

SCardBeginTransaction: Card was reset. 0x80100068

Known workaround

None known.

I have not checked the same code on Mavericks (OS X 10.9) to see if it is a regression or not.
I guess the behaviour changed in Yosemite with the rewrite of PC/SC (see OS X Yosemite and smart cards status)

Wednesday, December 9, 2015

OS X El Capitan and smart card source code

Apple released the source code of the open source components they use in El Capitan (OS X 10.11 released in September 2015). The components are available at OS X 10.11 Source.



As I did for Yosemite in "OS X Yosemite and smart card source code" I will document what I found.

The smart card related components are:

See "OS X El Capitan and smart cards status" for a general discussion of the changes in El Capitan.

General remark

Apple published the source code at the same time they published the 2nd minor version of El Capitan: 10.11.2. Maybe Apple wanted to fix the most serious bugs before publishing the source code. Or maybe they had not enough free time before today?

SecurityTokend

The version did not changed from 55108 in Yosemite to 55108 in El Capitan.

It is surprising to see a Tokend related component. CDSA (and then tokend) has been deprecated in 2011.

Maybe Apple forgot to remove this component?

SmartcardCCID

The version did not changed from 55008 in Yosemite to 55008 in El Capitan.

The CCID driver has not changed between Yosemite and El Capitan. This is what I already found in "OS X El Capitan and smart cards status".

SmartCardServices

The version did not changed from 55111 in Yosemite to 55111 in El Capitan.

SmartCardServices is the component providing pcsc-lite. For Yosemite Apple rewrote the complete PC/SC stack and replaced pcsc-lite by something else. So this component is not used in El Capitan.

Maybe Apple forgot to remove this component?

Conclusion

No change at all since Yosemite in the Open Source components related to smart card.

The PC/SC layer changed. Apple fixed some bugs between Yosemite and El Capitan, see "OS X Yosemite and smart cards: known bugs". But Apple still does not provide the source code of this component.

Components not used any more in El Capitan are still provided in OS X 10.11 Source. It looks like Apple forgot to clean the list of the components used in El Capitan.

Thursday, November 26, 2015

OS X El Capitan bug: PC/SC not usable after fork()

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

PC/SC is not unusable after fork()

SCardEstablishContext() returns SCARD_E_NO_SERVICE if called after fork(2) on El Capitan.

I can agree that if you mix PC/SC calls from before and after the fork(2) call you can have problems, as in OS X Yosemite bug: PC/SC functions crash after a fork(2). But if you start all the PC/SC calls in the same (child) process I expected it to work.

From the fork(2) manpage I read:

CAVEATS
There are limits to what you can do in the child process. To be totally safe you should restrict yourself to only executing async-signal safe operations until such time as one of the exec functions is called. All APIs, including global data symbols, in any framework or library should be assumed to be unsafe after a fork() unless explicitly documented to be safe or async-signal safe. If you need to use these frameworks in the child process, you must exec. In this situation it is reasonable to exec yourself.

I expect Apple to just close this bug as it it the documented behaviour.

It is not a bug but a feature ☹.

See also

Apple bug report #23669488 "PC/SC is not unusable after fork()"

Bug closed by Apple. See Update bellow.

Sample code


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

int main(void)
{
    int pid = fork();
    if (0 == pid)
    {
        /* son process */

        SCARDCONTEXT hContext;
        DWORD err = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL,
            &hContext);
        if (err != SCARD_S_SUCCESS) {
            printf("ScardEstablishedContext: %s (0x%08lx)\n",
                pcsc_stringify_error(err), (long)err);
            return -1;
        }
        else
            printf("OK\n");

        SCardReleaseContext(hContext);
    }
    else
        /* give some time to the son */
        sleep(1);

    return 0;
}


Result (on El Capitan)

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

$ ./main
ScardEstablishedContext: Service not available. (0x8010001d)

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

$ ./main
OK

Known workaround

None known.

Update 8th December 2015

As expected Apple closed the bug with:
As documented in the quoted fork man page excerpt, it is quite expected that PC/SC does not work in forked child.

Monday, November 23, 2015

OS X El Capitan bug: SCardConnect() returns SCARD_E_PROTO_MISMATCH instead of SCARD_E_SHARING_VIOLATION

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

SCardConnect() returns SCARD_E_PROTO_MISMATCH instead of SCARD_E_SHARING_VIOLATION

SCardConnect() returns the wrong error code on El Capitan.

If you use SCardConnect() to connect a reader that is already used by another application in exclusive mode (SCARD_SHARE_EXCLUSIVE) you should get the SCARD_E_SHARING_VIOLATION error. Instead you get a (surprising) SCARD_E_PROTO_MISMATCH error.

See also

Apple bug report #23646838 "SCardConnect() returns SCARD_E_PROTO_MISMATCH instead of SCARD_E_SHARING_VIOLATION".

Bug closed by Apple on 10th Dec 2015 because it is a duplicate of #22575831.

Sample code

The 2 programs are written in Python and use the PySCard wrapper so the code is much shorter than if written in C-language.

File lock.py:
#! /usr/bin/env python

from smartcard.System import readers
from smartcard.scard import SCARD_SHARE_EXCLUSIVE

reader = readers()[0]
print "Using:", reader

connection = reader.createConnection()
connection.connect(mode=SCARD_SHARE_EXCLUSIVE)

import time
time.sleep(10)

File connect.py:
#! /usr/bin/env python

from smartcard.System import readers

reader = readers()[0]
print "Using:", reader

connection = reader.createConnection()
connection.connect()

You need to execute the 2 programs in 2 different terminals. The execution of lock.py will lock the reader for 10 seconds. The execution of connect.py will try to connect, and get the error if lock.py is still running.

Result (on El Capitan)

$ ./lock.py
Using: Gemalto PC Twin Reader

In another terminal:
$ ./connect.py
Using: Gemalto PC Twin Reader
Traceback (most recent call last):
  File "./connect.py", line 9, in 
    connection.connect()
  File "/Library/Python/2.7/site-packages/pyscard-1.9.0-py2.7-macosx-10.10-intel.egg/smartcard/CardConnectionDecorator.py", line 54, in connect
    self.component.connect(protocol, mode, disposition)
  File "/Library/Python/2.7/site-packages/pyscard-1.9.0-py2.7-macosx-10.10-intel.egg/smartcard/pcsc/PCSCCardConnection.py", line 128, in connect
    SCardGetErrorMessage(hresult))
smartcard.Exceptions.CardConnectionException: Unable to connect with protocol: T0 or T1. Card protocol mismatch.

Expected result (on Debian)

$ ./lock.py 
Using: Gemalto PC Twin Reader 00 00

In another terminal:
$ ./connect.py
Using: Gemalto PC Twin Reader 00 00
Traceback (most recent call last):
  File "./connect.py", line 16, in 
    connection.connect()
  File "/usr/lib/python2.7/dist-packages/smartcard/CardConnectionDecorator.py", line 54, in connect
    self.component.connect(protocol, mode, disposition)
  File "/usr/lib/python2.7/dist-packages/smartcard/pcsc/PCSCCardConnection.py", line 128, in connect
    SCardGetErrorMessage(hresult))
smartcard.Exceptions.CardConnectionException: Unable to connect with protocol: T0 or T1. Sharing violation.

Discussion

The correct error code (Sharing violation) is returned if you run a second lock.py in another terminal.

The difference between lock.py and connect.py is that lock.py uses an exclusive connection (SCARD_SHARE_EXCLUSIVE) and connect.py uses a (default value) shared connection (SCARD_SHARE_SHARED).

I also get the correct error code (Sharing violation) if I try to connect in exclusive mode while a PC/SC transaction is running.

Known workaround

None known.

The error SCARD_E_PROTO_MISMATCH returned by SCardConnect() may in fact indicates a SCARD_E_SHARING_VIOLATION in some cases in El Capitan.

Update: 27th September 2016

This bug is fixed in macOS Sierra 10.12.0.

Tuesday, November 17, 2015

OS X El Capitan bug: Connecting a CT700 Gemalto smart card reader renders PC/SC useless

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

Connecting a CT700 Gemalto smart card reader renders PC/SC useless

The CCID driver provided by Apple do not work with the Gemalto CT700 smart card reader. This reader was previously named Gemalto GemPC Pinpad.

This is not really Apple fault since I maintain the CCID diver. So you can say this is my fault.

The problem was not easy to identify since the CCID driver is located in /usr/libexec/SmartCardServices/drivers/ and this directory is protected by System Integrity Protection (SIP) and can't be changed easily.

After I could enable some logs I get:
12/11/2015 15:18:47,192 com.apple.ifdreader[2100]: ifdhandler.c:83:CreateChannelByNameOrChannel() Lun: 0, device: Gemalto USB GemPCPinpad SmartCard Reader
12/11/2015 15:18:47,192 com.apple.ifdreader[2100]: ccid_usb.c:233:OpenUSBByName() Reader index: 0, Device: Gemalto USB GemPCPinpad SmartCard Reader
12/11/2015 15:18:47,192 com.apple.ifdreader[2100]: ccid_usb.c:281:OpenUSBByName() Using: /usr/local/libexec/SmartCardServices/drivers/ifd-ccid.bundle/Contents/Info.plist
12/11/2015 15:18:47,193 com.apple.ifdreader[2100]: ccid_usb.c:299:OpenUSBByName() ifdManufacturerString: Ludovic Rousseau (ludovic.rousseau@free.fr)
12/11/2015 15:18:47,193 com.apple.ifdreader[2100]: ccid_usb.c:300:OpenUSBByName() ifdProductString: Generic CCID driver
12/11/2015 15:18:47,193 com.apple.ifdreader[2100]: ccid_usb.c:301:OpenUSBByName() Copyright: This driver is protected by terms of the GNU Lesser General Public License version 2.1, or (at your option) any later
12/11/2015 15:18:48,196 com.apple.ifdreader[2100]: ccid_usb.c:426:OpenUSBByName() Checking device: 20/14
12/11/2015 15:18:48,196 com.apple.ifdreader[2100]: ccid_usb.c:488:OpenUSBByName() Trying to open USB bus/device: 20/14
12/11/2015 15:18:48,197 com.apple.ifdreader[2100]: ccid_usb.c:589:OpenUSBByName() Found Vendor/Product: 08E6/3478 (Gemalto USB GemPCPinpad SmartCard Reader)
12/11/2015 15:18:48,197 com.apple.ifdreader[2100]: ccid_usb.c:591:OpenUSBByName() Using USB bus/device: 20/14
12/11/2015 15:18:48,197 com.apple.ifdreader[2100]: ccid_usb.c:1142:ControlUSB() request: 0x03
12/11/2015 15:18:48,200 com.apple.ifdreader[2100]: receive: 01 2A 00 00 01 38 00 00 09 3D 00 00 34 43 00 00 61 51 00 00 01 54 00 00 8E 5B 00 00 CE 64 00 00 02 70 00 00 12 7A 00 00 02 7E 00 00 69 86 00 00 97 98 00 00 C3 A2 00 00 03 A8 00 00 1B B7 00 00 73 CB 00 00 03 D2 00 00 04 E0 00 00 24 F4 00 00 04 FC 00 00 D1 0C 01 00 05 18 01 00 2D 31 01 00 85 45 01 00 06 50 01 00 36 6E 01 00 E7 96 01 00 07 A4 01 00 07 C0 01 00 48 E8 01 00 08 F8 01 00 09 30 02 00 5A 62 02 00 0B 8B 02 00 0B A0 02 00 0E 48 03 00 0F 80 03 00 90 D0 03 00 16 40 05 00 20 A1 07 00 
12/11/2015 15:18:48,200 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 10753 bps
12/11/2015 15:18:48,200 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 14337 bps
12/11/2015 15:18:48,200 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 15625 bps
12/11/2015 15:18:48,200 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 17204 bps
12/11/2015 15:18:48,200 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 20833 bps
12/11/2015 15:18:48,200 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 21505 bps
12/11/2015 15:18:48,200 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 23438 bps
12/11/2015 15:18:48,200 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 25806 bps
12/11/2015 15:18:48,201 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 28674 bps
12/11/2015 15:18:48,201 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 31250 bps
12/11/2015 15:18:48,201 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 32258 bps
12/11/2015 15:18:48,201 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 34409 bps
12/11/2015 15:18:48,201 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 39063 bps
12/11/2015 15:18:48,201 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 41667 bps
12/11/2015 15:18:48,201 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 43011 bps
12/11/2015 15:18:48,201 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 46875 bps
12/11/2015 15:18:48,201 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 52083 bps
12/11/2015 15:18:48,201 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 53763 bps
12/11/2015 15:18:48,201 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 57348 bps
12/11/2015 15:18:48,201 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 62500 bps
12/11/2015 15:18:48,201 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 64516 bps
12/11/2015 15:18:48,201 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 68817 bps
12/11/2015 15:18:48,201 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 71685 bps
12/11/2015 15:18:48,201 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 78125 bps
12/11/2015 15:18:48,201 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 83333 bps
12/11/2015 15:18:48,201 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 86022 bps
12/11/2015 15:18:48,201 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 93750 bps
12/11/2015 15:18:48,201 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 104167 bps
12/11/2015 15:18:48,201 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 107527 bps
12/11/2015 15:18:48,201 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 114695 bps
12/11/2015 15:18:48,201 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 125000 bps
12/11/2015 15:18:48,201 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 129032 bps
12/11/2015 15:18:48,201 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 143369 bps
12/11/2015 15:18:48,201 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 156250 bps
12/11/2015 15:18:48,201 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 166667 bps
12/11/2015 15:18:48,201 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 172043 bps
12/11/2015 15:18:48,201 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 215054 bps
12/11/2015 15:18:48,201 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 229391 bps
12/11/2015 15:18:48,201 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 250000 bps
12/11/2015 15:18:48,201 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 344086 bps
12/11/2015 15:18:48,201 com.apple.ifdreader[2100]: ccid_usb.c:1122:get_data_rates() declared: 500000 bps
12/11/2015 15:18:48,216 com.apple.ifdreader[2100]: NotifySlotChange: 50 02 
12/11/2015 15:18:48,217 com.apple.ifdreader[2100]: -> 000000 65 00 00 00 00 00 00 00 00 00 
12/11/2015 15:18:48,219 com.apple.ifdreader[2100]: <- 000000 81 00 00 00 00 00 00 02 00 00 
12/11/2015 15:18:48,219 com.apple.ifdreader[2100]: -> 000000 65 00 00 00 00 00 01 00 00 00 
12/11/2015 15:18:48,221 com.apple.ifdreader[2100]: <- 000000 81 00 00 00 00 00 01 02 00 00 
12/11/2015 15:18:48,224 com.apple.ifdreader[2100]: ccid.c:383:ccid_open_hack_post() Using lang: (null)
12/11/2015 15:18:49,268 com.apple.ifdreader[2100]: -> 000000 6B A5 00 00 00 00 02 00 00 00 B2 A0 00 4D 4C 45 6E 74 65 72 20 50 49 4E 20 20 20 20 20 20 20 4E 65 77 20 50 49 4E 20 20 20 20 20 20 20 20 20 43 6F 6E 66 69 72 6D 20 50 49 4E 20 20 20 20 20 50 49 4E 20 4F 4B 20 20 20 20 20 20 20 20 20 20 49 6E 63 6F 72 72 65 63 74 20 50 49 4E 21 20 20 54 69 6D 65 20 4F 75 74 20 20 20 20 20 20 20 20 2A 20 72 65 74 72 69 65 73 20 6C 65 66 74 20 20 49 6E 73 65 72 74 20 43 61 72 64 20 20 20 20 20 43 61 72 64 20 45 72 72 6F 72 20 20 20 20 20 20 50 49 4E 20 62 6C 6F 63 6B 65 64 20 20 20 20 20 
12/11/2015 15:18:49,371 com.apple.ifdreader[2100]: ccid_usb.c:784:ReadUSB() read failed (20/14): -7 Operation timed out
12/11/2015 15:18:49,371 com.apple.ifdreader[2100]: ccid.c:436:ccid_open_hack_post() Failed to load l10n strings
12/11/2015 15:18:49,371 com.apple.ifdreader[2100]: -> 000000 6B 01 00 00 00 00 03 00 00 00 6A 
12/11/2015 15:18:54,372 com.apple.ifdreader[2100]: ccid_usb.c:745:WriteUSB() write failed (20/14): -7 Operation timed out
12/11/2015 15:18:54,372 com.apple.ifdreader[2100]: ccid.c:219:set_gemalto_firmware_features() GET_FIRMWARE_FEATURES failed: 612, len=21
12/11/2015 15:18:54,372 com.apple.ifdreader[2100]: ifdhandler.c:167:CreateChannelByNameOrChannel() failed

And on any new CCID reader connected I get:
12/11/2015 15:24:42,414 com.apple.ifdreader[2100]: ifdhandler.c:83:CreateChannelByNameOrChannel() Lun: 0, device: Gemalto PC Twin Reader
12/11/2015 15:24:42,414 com.apple.ifdreader[2100]: ccid_usb.c:233:OpenUSBByName() Reader index: 0, Device: Gemalto PC Twin Reader
12/11/2015 15:24:42,414 com.apple.ifdreader[2100]: ccid_usb.c:274:OpenUSBByName() USB driver with index 0 already in use
12/11/2015 15:24:42,414 com.apple.ifdreader[2100]: ifdhandler.c:117:CreateChannelByNameOrChannel() failed

This is because the initialisation of the CT700 failed but did not correctly reset a reader structure at index 0.

This problem has been fixed upstream in the CCID driver but is not yet available in a stable driver version.

See also

Apple bug report #23515984 "Connecting a CT700 Gemalto smart card reader renders PC/SC useless"

Known workaround

None known.

Do not use this reader on El Capitan until Gemalto or Apple provides a solution.

Update: 27th September 2016

This bugs is fixed upstream in CCID driver version 1.4.22.
So this bug is fixed in macOS Sierra as a side effect of the CCID driver upgrade to version 1.4.24.

OS X El Capitan and smart cards: known bugs

El Capitan: OS X 10.11

In Yosemite (OS X 10.10) Apple rewrote a large part of the smart card infrastructure and introduced many bugs. I made a list in "OS X Yosemite and smart cards: known bugs".

I propose to maintain a similar lists for smart card bugs found in El Capitan10.11.x.

The bugs I find in El Capitan may also be present in Yosemite. The bugs may not be specific to El Capitan.

Bug list

  1. PC/SC is not unusable after fork()
  2. SCardBeginTransaction() returns different error codes than on GNU/Linux and Windows

Fixed in 10.11.5

  1. OS X El Capitan and CCID driver upgrades
    see OS X El Capitan 10.11.5 and CCID driver fix

Fixed in 10.12.0 (Sierra)

  1. Connecting a CT700 Gemalto smart card reader renders PC/SC useless
  2. SCardGetAttrib() returns SCARD_E_NOT_TRANSACTED when it should not
  3. SCardConnect() returns SCARD_E_PROTO_MISMATCH instead of SCARD_E_SHARING_VIOLATION
  4. SCardGetAttrib() returns SCARD_E_NOT_TRANSACTED instead of SCARD_E_INSUFFICIENT_BUFFER

Fixed in 10.13.0 (High Sierra)

  1. SCARD_W_RESET_CARD not returned by SCardTransmit()

Feature list

  1. SCardGetStatusChange() and number of card events
  2. SCardGetStatusChange() and "\\?PnP?\Notification"
  3. add support of TAG_IFD_POLLING_THREAD_WITH_TIMEOUT

Conclusion

Apple still has some PC/SC bugs to fix.

OS X El Capitan bug: SCARD_W_RESET_CARD not returned by SCardTransmit()

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

SCARD_W_RESET_CARD not returned by SCardTransmit()

SCardTransmit() do not work correctly on El Capitan (and maybe also on Yosemite but that is untested).

When an application calls SCardTransmit() after the card has been reseted the returned value should be SCARD_W_RESET_CARD to indicate that the card has been reseted.
What happens on El Capitan is that the SCardTransmit() returns SCARD_S_SUCCESS but the card answer will (in general) be incorrect since the card has been reseted.

The error SCARD_W_RESET_CARD is returned from the next SCardTransmit() call.

This behaviour can confuse applications since the SCardTransmit() that should fail just works but with a (possibly) wrong answer from the card.

See also

Apple bug report #23574394 "SCARD_W_RESET_CARD not returned by SCardTransmit()"

Sample code

For the example I used a smart card with a test JavaCard applet loaded. The idea is to send commands to the applet. If the command is send before the applet is selected (after a reset) then the command will fail.

I used my test applet installed in the card.

The 2 programs are written in Python and use the PySCard wrapper so the code is much shorter than if written in C-language.

Looping program


#! /usr/bin/env python

from smartcard.System import readers
from smartcard.util import toBytes

# define the APDUs used in this script
SELECT = toBytes("00 A4 04 00 06 A0 00 00 00 18 FF")
COMMAND = toBytes("80 34 00 0E 0E")

# use the 1st available reader
reader = readers()[0]
print "Using:", reader

connection = reader.createConnection()
connection.connect()

data, sw1, sw2 = connection.transmit(SELECT)

while True:
    data, sw1, sw2 = connection.transmit(COMMAND)
    print data
    print "Command: %02X %02X" % (sw1, sw2)

Reset program


#! /usr/bin/env python

from smartcard.System import readers
from smartcard.scard import SCARD_RESET_CARD

reader = readers()[0]
print "Using:", reader

connection = reader.createConnection()
connection.connect(disposition=SCARD_RESET_CARD)

Expected result (on Debian)

$ ./loop.py
Using: Gemalto PC Twin Reader 00 00
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
Command: 90 00
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
Command: 90 00
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
Command: 90 00
Traceback (most recent call last):
  File "./loop2.py", line 20, in 
    data, sw1, sw2 = connection.transmit(COMMAND)
  File "/usr/lib/python2.7/dist-packages/smartcard/CardConnectionDecorator.py", line 82, in transmit
    return self.component.transmit(bytes, protocol)
  File "/usr/lib/python2.7/dist-packages/smartcard/CardConnection.py", line 144, in transmit
    data, sw1, sw2 = self.doTransmit(bytes, protocol)
  File "/usr/lib/python2.7/dist-packages/smartcard/pcsc/PCSCCardConnection.py", line 198, in doTransmit
    SCardGetErrorMessage(hresult))
smartcard.Exceptions.CardConnectionException: Failed to transmit with protocol T0. Card was reset.

In another terminal I run the reset program:
$ ./reset.py
Using: Gemalto PC Twin Reader

Result (on El Capitan)

$ ./loop.py
Using: Gemalto PC Twin Reader
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
Command: 90 00
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
Command: 90 00
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
Command: 90 00
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
Command: 90 00
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
Command: 90 00
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
Command: 90 00
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
Command: 90 00
[]
Command: 69 85
Traceback (most recent call last):
  File "./loop2.py", line 20, in 
    data, sw1, sw2 = connection.transmit(COMMAND)
  File "/Library/Python/2.7/site-packages/pyscard-1.9.0-py2.7-macosx-10.10-intel.egg/smartcard/CardConnectionDecorator.py", line 82, in transmit
    return self.component.transmit(bytes, protocol)
  File "/Library/Python/2.7/site-packages/pyscard-1.9.0-py2.7-macosx-10.10-intel.egg/smartcard/CardConnection.py", line 142, in transmit
    data, sw1, sw2 = self.doTransmit(bytes, protocol)
  File "/Library/Python/2.7/site-packages/pyscard-1.9.0-py2.7-macosx-10.10-intel.egg/smartcard/pcsc/PCSCCardConnection.py", line 205, in doTransmit
    SCardGetErrorMessage(hresult))
smartcard.Exceptions.CardConnectionException: Failed to transmit with protocol T0. Card was reset.

Results interpretation

In the two executions you see mostly the same results. The loop program runs and at one point it fails and returns with the error "Card was reset."

The difference is that on El Capitan, just before returning with the error code, the program returned an error from the card "69 85". This is because the applet is not selected so the command is no more understood by the card. And the applet is no more selected because the card has been reseted.

The last command before the error should never have been sent to the card. That is the problem on El Capitan.

Known workaround

None known.

Update: 26 September 2017

This bug is now fixed in macOS 10.13.0 High Sierra

Sunday, November 8, 2015

New version of pcsc-tools: 1.4.25

I just released a new version of pcsc-tools, a suite of tools for PC/SC.

Changes:
1.4.25 - 8 November 2015, Ludovic ROUSSEAU
  • 44 new ATRs
  • ATR_analysis: fix the update of the local cache

Wednesday, October 21, 2015

New version of libccid: 1.4.21

I just released a version 1.4.21 of libccid the Free Software CCID class smart card reader driver.

Direct download here.

Changes:
1.4.21 - 21 October 2015, Ludovic Rousseau
  • Add support of
    • ACS ACR1252 Dual Reader
    • Chicony HP USB Smartcard CCID Keyboard JP
    • Chicony HP USB Smartcard CCID Keyboard KR
    • FT ePass2003Auto
    • Feitian bR301 BLE
    • Feitian iR301 (ProductID 0x0619)
    • Feitian iR301 (ProductID 0x061C)
    • Identiv @MAXX ID-1 Smart Card Reader
    • Identiv @MAXX Light2 token
    • Identiv CLOUD 2980 F Smart Card Reader
    • Identiv Identiv uTrust 4701 F Dual Interface Reader
    • Identiv SCR3500 A Contact Reader
    • Identiv SCR3500 B Contact Reader
    • Identiv SCR35xx USB Smart Card Reader
    • Identiv uTrust 2900 R Smart Card Reader
    • Identiv uTrust 2910 R Smart Card Reader
    • Identiv uTrust 2910 R Taglio SC Reader
    • Identiv uTrust 3512 SAM slot Token
    • Identiv uTrust 3522 embd SE RFID Token
    • Identiv uTrust 3700 F CL Reader
    • Identiv uTrust 3701 F CL Reader
    • Identive Identive CLOUD 4000 F DTC
    • Liteon HP SC Keyboard - Apollo (Liteon)
    • Liteon HP SC Keyboard - Apollo JP (Liteon)
    • Liteon HP SC Keyboard - Apollo KR (Liteon)
    • Nitrokey Nitrokey HSM
    • Nitrokey Nitrokey Pro
    • Nitrokey Nitrokey Start
    • Rocketek RT-SCR1
    • VASCO DIGIPASS 875
    • WatchCNPC USB CCID Key
  • Remove support of
    • Crypto Stick Crypto Stick v1.4 is an old version of Nitrokey Nitrokey Pro
    • Free Software Initiative of Japan Gnuk Token is an old version of Nitrokey Nitrokey Start
    • Add Feitain R502 dual interface (composite) reader on Mac OS X
    • display a human readable version of the error code returned by libusb
    • Mac OS X: wait until libusb/the reader is ready
    • some minor bugs fixed

    Sunday, October 11, 2015

    My blog Google+ page

    You are now more than 200 to follow my blog Google+ page at https://plus.google.com/u/0/b/105951035108309096272/105951035108309096272/posts



    Comments

    I disabled comments on the blog in 2013. See why at "Comments are now disabled". Technical questions should go on the MUSCLE mailing list.

    The goal of the Google+ page is to allow you to leave comments about my blog articles.

    If you just want to know when a new article is available maybe you should subscribe to my blog RSS feed instead. It looks like many people are doing that because I have much more readers of my blog than subscribers of my blog Google+ page.

    Conclusion

    Feel free to leave comments related to the articles on Google+.

    If you want to contact me directly you should use email instead of comments. You can reach me at ludovic.rousseau@free.fr or ludovic.rousseau@gmail.com.

    Saturday, October 3, 2015

    Evolution of the number of CCID readers

    Regularly I add support of new smart card readers in the list of CCID devices. I wanted to know how regularly I did that over the lifetime of the project (more than 12 years now).
    So I extracted some numbers from the CCID driver git repository to generate a graphic.

    Graph




    I am really surprised by the linearity of the curve.



    The linear correlation equation is (according to Numbers): y = 1.132e-6 x -159.63
    That is a growth rate of 1.132x10-6 readers per second or 36.7 readers per year.


    The curve is even better approximated by a polynomial equation in x2. The coefficient of determination R2 is then equal to 0.9949 (closer to 1.0) instead of 0.9753 for the linear correlation.



    Accidents

    I note 3 "accidents" or fast evolutions:



    Conclusion

    The number of supported CCID readers continues to grow. I do not expect the growth rate to decrease.

    I guess some very old smart card reader models are no more sold. And are, or not, replaced by new newer models.
    You can list the readers sorted by "seniority" using the Readers sorted by 'release' field page and discover the first 7 readers included in version 0.1.0 of the driver.

    Friday, October 2, 2015

    OS X El Capitan and smart cards status

    El Capitan (OS X 10.11) is now out since 30th September, 2015.

    As I did with the previous major versions of Mac OS X Yosemite, Mavericks, Mountain Lion (and Lion) I will list changes in El Capitan regarding the smart card world.


    API Differences between 10.10 and 10.11

    The differences are listed in the developer page OS X El Capitan v10.11. The page only document big changes. The smart card changes are not listed there :-)

    A complete list of API changes is at OS X v10.11 API Diffs. Regarding the smart card world we have:
    The CryptoTokenKit API has changed. Some methods have been modified, some methods have been added.

    I note two sets of new methods: TKSmartCardPIN* and TKSmartCardUserInteractionFor*. It looks like Apple wants to provide a nice User eXperience regarding PIN management.

    I hope Apple will provide more documentation than the .h header file and some code samples.
    I will try to rebuild my Crypto Token Kit Objective-C and Swift examples on El Capitan to check if they still work.

    PC/SC

    Since Yosemite (10.10) the PC/SC layer is no more a fork of pcsc-lite. So comparing versions with pcsc-lite is useless.

    $ cat /System/Library/Frameworks/PCSC.framework/Versions/A/Resources/version.plist 
    <?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>BuildAliasOf</key>
     <string>CryptoTokenKit</string>
     <key>BuildVersion</key>
     <string>13</string>
     <key>CFBundleShortVersionString</key>
     <string>8.0</string>
     <key>CFBundleVersion</key>
     <string>1</string>
     <key>ProjectName</key>
     <string>SmartCardServices</string>
     <key>SourceVersion</key>
     <string>79001001000000</string>
    </dict>
    </plist>
    


    The BuildVersion changed from 1 on Yosemite to 13 on El Capitan, and SourceVersion changed from 22020004000000 to 79001001000000. I have no idea what the SourceVersion "number" is.

    It looks like Apple made 12 builds of the PC/SC framework since Yosemite 10.10.

    Bugs fixed

    At least one bug remains: PC/SC functions crash after a fork(2). But this bug may be hard to fix.

    I updated my blog article OS X Yosemite and smart cards: known bugs.

    Maybe new bugs will be found on El Capitan. But I have not yet found any after just a few hours of tests.

    CCID driver

    Driver version 1.4.14.
    No change since Yosemite.

    $ grep -A 1 CFBundleShortVersionString /usr/libexec/SmartCardServices/drivers/ifd-ccid.bundle/Contents/Info.plist
     <key>CFBundleShortVersionString</key>
     <string>1.4.14</string>
    

    New driver location

    The System Integrity Protection (SIP) introduced in El Capitan impose that custom PC/SC drivers are now installed in /usr/local/libexec/SmartCardServices/drivers/.

    Only the CCID driver provided by Apple is still in /usr/libexec/SmartCardServices/drivers/.

    Tokend

    Because of SIP, the tokend needs to be installed in /Library/Security/tokend/ now instead of /System/Library/Security/tokend/.

    The tokend and CDSA are still usable. I just fixed the PKCS11.tokend so that it looks for PKCS#11 libraries in /usr/local/lib/pkcs11/ if /usr/lib/pkcs11/ does not exist (as it is the case on El Capitan because of SIP again).

    Conclusion

    Most of the remaining PC/SC bugs fixed.
    tokend still usable.
    Some new Crypto Token Kit methods.