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

Tuesday, January 6, 2015

OS X Yosemite bug: SCARD_E_PROTO_MISMATCH not returned

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

SCARD_E_PROTO_MISMATCH not returned by SCardConnect()

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

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

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

See also

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

Sample code

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

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

int main(int argc, const char * argv[]) {
    SCARDCONTEXT hContext;
    LPSTR mszReaders;
    DWORD err = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
    if (err != SCARD_S_SUCCESS) {
        printf("ScardEstablishedContext : %08x\n",err);
  return -1;
    }

 DWORD cchReaders = 0;
 err = SCardListReaders(hContext, "SCard$AllReaders", NULL, &cchReaders);
 if (err != 0) {
  printf("ScardListReaders : %08x\n",err);
  return -1;
 }
 mszReaders = calloc(cchReaders, sizeof(char));
 if (!mszReaders) {
  printf("calloc\n");
  return -1;
 }
 err = SCardListReaders(hContext,"SCard$AllReaders", mszReaders, &cchReaders);
 if (err != SCARD_S_SUCCESS) {
  printf("ScardListReaders : %08x\n",err);
  return -1;
 }

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

 SCARDHANDLE hCard;
 DWORD dwActiveProtocol;
 err = SCardConnect(hContext, mszReaders, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol);
 if (err != SCARD_S_SUCCESS) {
  printf("SCardConnect: 0x%08x\n",err);
  return -1;
 }

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

    return 0;
}

Result (on Yosemite)

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

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

0x80100016 is SCARD_E_NOT_TRANSACTED.

Expected result (on Mavericks)

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

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

0x8010000f is SCARD_E_PROTO_MISMATCH.

Known workaround

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

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

Update

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