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.