vsmartcard icon indicating copy to clipboard operation
vsmartcard copied to clipboard

vsmartcard: messaging inconsistency on different platforms

Open martinpaljak opened this issue 10 months ago • 12 comments

I've successfully integrated jcardsim with vsmartcard on windows/mac/linux, with a "blue-eyed implementation", where a single simulator instance is exposed to a single reader, and can be used via the PC/SC interface. All is fine.

But trying to make the implementation more robust and most importantly, with the assumption that the single PC/SC interface is not the only interface towards the simulator (for example, to enforce a "contact interface" and "contactless interface" distinction that run commands interleaved in isolated sessions, even on different vsmartcard "ports"), things break.

For this I would need to lock the simulator for an "adapter" (that enforces a specific protocol towards the simulator like T=1 or T=CL), and this is where troubles arise:

  • on Linux (Debian 12), the "virtual card" received proper "powerup" and "powerdown" messages, that allow to lock the simulator for the adapter session just fine.
  • on macOS (15.5), there are RESET messages followed by APDU-s, with a POWERDOWN after 5 seconds of no use.
  • on Windows (11), there are RESET messages followed by APDU-s and no POWERDOWN

So there's no clean "start of session" and "end of session" markers on non-linux.

I'm thinking of making a hack around it (for Windows) by detecting successful applet selection and/or opportunistic locking with a 3 second timeout or something similar, but eventually it would be nice if the behaviour of vsmartcard could be harmonized across platforms, as much as possible. It might also help to transmit more "metadata" from the PC/SC side towards the virtual card, like the protocol being connected with (T=0/T=1) or if possible, exclusive access flags (also transactions from PC/SC level)

The 1-per-second ATR polling seems something that might be nice to reduce, if feasible.

martinpaljak avatar Jun 29 '25 07:06 martinpaljak

Your problem sounds interesting and I think it cannot be solved with out-of-the box mechanisms from PC/SC. I assume you would like to distinguish between different clients that are either connecting to the driver via SCardConnect/SCardEstablishChontext. If you look at the PC/SC API from pcsc-lite (Linux/macOS), you see that there is no data supplied which identifies the client handles. The driver is only meant to pass through commands from pcsc-lite, which also handles the logic when Power-on/off or reset is sent. Without access to the core components, there is not much harmonization that can be done.

You could, however, easily introduce additional commands to mark new connections explicitly. Using SCardControl, you can pass any information from the PC/SC client to the driver at any time. You could, for example, pass the SCARDCONTEXT and SCARDHANDLE: If you see any new combination here that should allow detecting a new connection pretty much on all platforms. You can also send some "initialization command" via this interface to trigger re-initialization for the simulator explicitly. On Linux/macOS, you would have to edit IFDHControl; on Windows you need to double check, but I guess it would be in ProcessIoControl. In the interface between vicc and vpcd, you would have to define a new command, which starts with 00 01 XX. Everything from 05 to FF is currently free to use.

Regarding the polling, I am not aware of any "liveliness detection" of an internet connection other than actually sending some command. That's why we still stick to explicit testing the connection between vpcd/vicc rather than signaling in case of a state change.

frankmorgner avatar Jun 29 '25 10:06 frankmorgner

Not exactly - I'm OK with PC/SC doing the access multiplexing either with exclusive mode opening or begin/end transaction (there is just a single active "serial connection" to the "secure element" in the end) for as long as the virtual (vicc) part receive reliable "start of session" indicators from vsmartcard, both on macos and windows, like I do receive on linux.

I do know that PC/SC and multiple applications and resulting "sessions" is a bit tricky to get "right", especially given the "looks a lot alike" but "differs quite a lot in implementation" when you look behind the SCard* API on different platforms (and their revisions)

The main promise of vsmartcard, for me, is "works with existing native PC/SC applications without any changes" (in fact most target software I would label as "unmodifiable"), so the SCardControl tricks don't apply, AFAIU ?

Given that macOS uses the open source CCID driver, I believe that is a bit easier to fix than the windows part (it seems there is no "powerup" message due to how cryptotokenkit handles ccid devices), but I leave this ticket here for the reference until no workarounds are needed to make multiple clients reliable from a "vicc" side.

I "solved" the issue by creating opportunistic "open session on first incoming reset" for vsmartcard client.

So for a single jcardsim "virtual card" (JVM + Simulator instance) I can create two vsmartcard TCP clients, one for "reader slot 1" where it is always a contactless card from javacard perspective and "reader slot 2" where it is always a contact card from javacard applet POV. And run it on Windows without worrying too much of synchronizing access externally. But with a delay.

https://github.com/martinpaljak/jcardsim/blob/next/simulator/src/main/java/pro/javacard/jcardsim/adapters/AbstractTCPAdapter.java#L116-L119

And a 3 second (feels empirically sufficient) idle timeout

https://github.com/martinpaljak/jcardsim/blob/next/simulator/src/main/java/com/licel/jcardsim/base/SimulatorSession.java#L94-L100

martinpaljak avatar Jun 29 '25 16:06 martinpaljak

@frankmorgner maybe a "ping" or "nop" command can be created instead of (ab)using "atr"?

martinpaljak avatar Jun 29 '25 16:06 martinpaljak

A ping followed by an ACK would be possible, but in my opinion it is not worth the optimization. The size of a transmit only matters if it leads to more fragmentation. on the network channel An ATR is quite small, which can likely be transmitted in a single package, just like a smaller ACK.

frankmorgner avatar Jun 30 '25 18:06 frankmorgner

When talking about "sessions", there is

  1. clients connecting to a card (SCardConnect/SCardDisconnect)
  2. clients requesting exclusive access to a token (SCardBeginTransaction/SCardEndTransaction)
  3. cards deleting volatile information (power on/off or warm/cold reset)
  4. card capabilities of handling multiple logical channels
  5. card lifecycle (creation -> per-personalized -> personalized -> usage -> deletion)

In the simulator, you are trivially getting markers for the third and fourth kind of session, but from your heuristics, I assume you would like to catch the first case (by actively ignoring long running client processes), right?

frankmorgner avatar Jul 02 '25 09:07 frankmorgner

4 and 5 are outside of scope of "vsmartcard PC/SC connector" context. 2 would be lovely to have, 3 should be a must, as should be 1 tbh. I'd also like to get the protocol SCardConnect is called with ("virtual pps?") if possible (to differentiate between t0/t1)

martinpaljak avatar Jul 02 '25 10:07 martinpaljak

Maybe @LudovicRousseau can give some information on whether SCardConnect/SCardDisconnect and/or SCardBeginTransaction/SCardEndTransaction can be detected by a reader driver. I am not aware of any marker that could be used here. The RPC-based split between pcsc-lite and libpcsclite.so doesn't even allow looking at file descriptors or PIDs to check for the PC/SC client. The same holds on Windows, where the usermode driver runs seperated from the PC/SC client.

The third (3) kind of session is what is working reliably and what you seem to be using to guess the first (1) kind of session with. I don't think this will be very reliable, because a PIN entry may take very long and also on the PKCS#11 level you may have a some open "session" (type 5, more or less) that is attributed to a single client which may sleep for a longer time.

Maybe you could also use SCardGetStatusChange and check for either SCARD_STATE_EXCLUSIVE or SCARD_STATE_INUSE to detect a new client (first kind of session). I think this can be monitored in the vpcd driver code itself (on all platforms) and can then be propagated to the virtual card (i.e. the simulator).

frankmorgner avatar Jul 10 '25 15:07 frankmorgner

On pcsc-lite the driver function IFDHSetProtocolParameters() will be called when an application calls SCardConnect(). The protocol requested by the application is available in the parameter Protocol (oh, so surprising).

Of course, the requested protocol must be reported in the ATR. Or pcsc-lite will report an error without even talking to the driver.

@martinpaljak I am not sure to understand what you want to do. You want to have the same card simulator accessible from two different PC/SC readers?

LudovicRousseau avatar Jul 11 '25 12:07 LudovicRousseau

@LudovicRousseau yes. Think of it as a mobile phone - there is contactless interface that works when you tap the phone somewhere, and contact interface used by the apps. Would love to have a solid indicator in vsmartcard when to "lock" the virtual card for a given reader session.

martinpaljak avatar Jul 11 '25 12:07 martinpaljak

forwarding requests from IFDHSetProtocolParameters() from vpcd to vicc would be easily implemented and seems like a good indicator for detecting new client connections. However, that may still lead to a conflict when two clients have shared access to a single reader, then a new connection is detected even though the old one is not yet terminated.

frankmorgner avatar Jul 16 '25 12:07 frankmorgner

IFDHSetProtocolParameters() is called only if the protocol is not already set. https://github.com/LudovicRousseau/PCSC/blob/master/src/winscard.c#L368

If a new client calls SCardConnect() with the same protocol then IFDHSetProtocolParameters() wil not be called again and the driver have no way to know another application is using the card.

@martinpaljak if you give access to your simulated smart card from 2 interfaces (contact & contactless) then the card is visible/accessed from 2 different readers? No? So you can know which reader is used and differentiate the accesses?

LudovicRousseau avatar Jul 16 '25 12:07 LudovicRousseau

@LudovicRousseau yes, two different readers (well, actually only one is pc/sc via vsmartcard, other is direct java, but the setup could/should work via pc/sc as well).

martinpaljak avatar Jul 16 '25 13:07 martinpaljak