This is part of the series: "OS X Yosemite and smart cards: known bugs".
If you use NULL for
SCardTransmit
SCardTransmit() fails to detect wrong value forpioSendPci
parameter.If you use NULL for
pioSendPci
parameter then you get a crash (Segmentation fault: 11) of the application instead of getting the error 0x80100004
that is SCARD_E_INVALID_PARAMETER
.See also
Apple bug report #19231406 "PC/SC function SCardTransmit: pioSendPci not checked".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
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_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol);
unsigned char cmd[] = {0, 0, 0, 0, 0};
unsigned char resp[255];
DWORD resp_len = sizeof resp;
err = SCardTransmit(hCard, NULL, cmd, sizeof cmd, NULL, resp, &resp_len);
if (err != SCARD_S_SUCCESS) {
printf("ScardTransmit : %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
Segmentation fault: 11
$ lldb ./main
(lldb) target create "./main"
Current executable set to './main' (x86_64).
(lldb) r
Process 6169 launched: './main' (x86_64)
Reader : Gemalto PC Twin Reader
Process 6169 stopped
* thread #1: tid = 0x7472a, 0x0000000100004b6d PCSC`__SCardTransmit_block_invoke + 17, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
frame #0: 0x0000000100004b6d PCSC`__SCardTransmit_block_invoke + 17
PCSC`__SCardTransmit_block_invoke + 17:
-> 0x100004b6d: movl (%rax), %edx
0x100004b6f: leaq 0x6901(%rip), %rsi ; "proto"
0x100004b76: movq %r14, %rdi
0x100004b79: callq 0x10000b0c2 ; symbol stub for: xpc_dictionary_set_uint64
Expected result (on Debian)
CFLAGS=`pkg-config --cflags libpcsclite` LDFLAGS=`pkg-config --libs libpcsclite` make main
$ ./main
Reader : Gemalto PC Twin Reader (70D7E2EE) 00 00
ScardTransmit : 80100004
ConversionConversion EmoticonEmoticon