Friday, December 12, 2014

OS X Yosemite bug: SCardGetAttrib

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

SCardGetAttrib

SCardGetAttrib() do not work any more on Yosemite.

The function returns with 8010000c that is SCARD_F_INTERNAL_ERROR.

See also

"Problem With SCardGetAttrib on Mac OS X 10.10 (Yosemite)" at https://smartcardservices.macosforge.org/trac/ticket/139.

Apple bug report #19231112 "PC/SC function SCardGetAttrib is broken on Yosemite".
#19231112 closed as duplicate of #16366962.

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 SCARD_ATTR_VALUE(Class, Tag) ((((ULONG)(Class)) << 16) | ((ULONG)(Tag)))
#define SCARD_CLASS_ICC_STATE       9   /**< ICC State specific definitions */
#define SCARD_ATTR_ATR_STRING SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0303) /**< Answer to reset (ATR) string. */

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);
    } else {
        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_RAW, &hCard, &dwActiveProtocol);
        if (err != SCARD_S_SUCCESS) {
            printf("ScardConnect : %08x\n",err);
        } else {
            DWORD dwAtrLen = 32;
            err = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, NULL, &dwAtrLen);
            printf("ATR LENGTH : %1d\n", dwAtrLen);
            if (err != SCARD_S_SUCCESS) {
                printf("SCardGetAttrib : %08x\n",err);
            } else {
                printf("ATR LENGTH %d\n", dwAtrLen);
                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
ATR LENGTH : 32
SCardGetAttrib : 80100001

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
Reader : Gemalto PC Twin Reader (70D7E2EE) 00 00
ATR LENGTH : 20
ATR LENGTH 20

Known workaround

None known.

Update

This bug is now fixed in Mac OS X El Capitan 10.11.0.