Important!

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

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

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