[Pcsclite-muscle] Asynchronous PCSC API

Ludovic Rousseau ludovic.rousseau at gmail.com
Sat Jan 29 07:44:26 PST 2022


Hello,

Le mer. 26 janv. 2022 à 13:26, Frank Morgner <frankmorgner at gmail.com> a écrit :
>
> Last time I tested, SCardCancel didn't abort *anything* on Windows; it
> didn't even cancel the command for entering the PIN on the reader's
> PIN pad. Back then, I've also tried stopping the calling process (and
> invalidating the scardcontext), but still the PIN pad reader was
> waiting for the PIN until the timeout was reached. As you can see,
> this is not only a software limitation, but also a limitation in
> hardware.

It should be possible to cancel a verify PIN (PC_to_RDR_Secure) using
the CCID command PC_to_RDR_Abort.
" This command is used with the Control pipe Abort request to tell the
CCID to stop any
current transfer at the specified slot and return to a state where the
slot is ready to
accept a new command pipe Bulk-OUT message. "

But since the Windows CCID driver does not even support verify PIN I
am not surprised it is also not possible to cancel it :-)

My CCID driver does not use PC_to_RDR_Abort either.
But that would be a technically interesting project to support
SCardCancel() for SCardControl() and SCardTransmit().


Ievgenii, Regarding SCardConnect(), I tried your sample code on Windows 10.
I note that ScardConnect() is NOT canceled by SCardCancel().

The output I have is:
$ ./cardlock "Alcor Micro USB Smart Card Reader 0"
connecting...
beginning transaction...
status check
status check
status check
status check
status check
status check
status check
status check
status check
status check
status check
status check
status check
status check
status check

And in another window:
$ ./cardlock_cancel.exe "Alcor Micro USB Smart Card Reader 0"
connecting...
cancelling
done
/home/Ludovic/cardlock/cardlock_cancel.c:29 - 0x80100002

The SCardConnect() in cardlock_cancel does return only after the
process cardlock has been manually interrupted (by control-C).
The error code 0x80100002 is SCARD_E_CANCELLED but the cancellation is
NOT working. You get the return value SCARD_E_CANCELLED but only after
the reader has been unlocked by the termination of the ./cardlock
process.

Be careful with your CHECK() macro.
in:
#define CHECK(rv) \
 if (rv != SCARD_S_SUCCESS) printf("%d\n", rv);
rv will be evaluated twice: in the if() and in the printf(). if "rv"
is a function then the function will be called twice.

I guess this is NOT what you want.
Instead use something like:
#define CHECK(cmd) \
 DWORD rv = cmd; \
 if (rv != SCARD_S_SUCCESS) printf("%d\n", rv);

I then tried the same code on GNU/Linux and I have a behavior a bit different.
$ ./cardlock_cancel "Alcor Micro AU9540 00 00"
connecting...
cancelling
done
connected
disconnected

SCardConnect() is still NOT cancelled. But SCardConnect() *succeeds*
when the process ./cardlock is terminated instead of returning
SCARD_E_CANCELLED.
Since SCardConnect() succeeds the program continues with
SCardDisconnect() instead of exiting.

I could modify pcsc-lite to make SCardConnect() cancellable using SCardCancel().
But your code (or any code using this behavior) would then not work on
Windows nor macOS.
So I am not sure it is a good idea.

Any thoughts?

Regards,

-- 
 Dr. Ludovic Rousseau



More information about the pcsclite-muscle mailing list