Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Provide notification about and handle card resets by other contexts
Most of the cards supported by OpenSC do not support the "logout" method required to deauthenticate a card. This means that the only way to deauthenticate the card without removing it from reader is to reset it. This is done for example by Windows minidriver when asked to deauthenticate such card (strictly speaking by Windows Base CSP if minidriver is unable to do a logout on its own). And Windows libraries (like WinHTTP used by IE and WebDAV client) usually prefer to deauthenticate card after only a few seconds of inactivity, while keeping PIN in cache for future operations. Now, if the card is reset its state is lost for all other users, too. Currently, "other user" usually means PKCS#11 library, which will break in this case, since it doesn't know that the card is no longer authenticated. Also for at least some cards (for example OpenPGP card and cards having multiple applets) all operations will fail as card needs specific post-reset initialization. This all means that we need to catch card resets by other contexts in reader backends and provide higher layers with this information so they can decide what to do when it happens. A SC_READER_CARD_RESET reader flag was added for this. Unfortunately, when exactly the card reset is announced to PC/SC client isn't well defined in PC/SC specification and implementations do it differently. This means that we need to be prepared to receive "card reset" error code on both transaction begin and individual card operations. Windows is special here, since SCardBeginTransaction() is documented to return success even if the card has been reset, but at least Vista returns SCARD_E_INVALID_VALUE in this case instead, needing a second check what has actually happened via SCardStatus(). sc_lock() function gains new "resetok" parameter. When set it means to continue operation even if the card was reset as long as the card wasn't reset between individual operations. Basically, with this option set it would be OK for card to be reset either during locking attempt or before first operation like transmit completes successfully. If this happens no SC_READER_CARD_RESET will be set since it is only for card resets which are not retried automatically. Currently, such automatic retry on first operation (as opposed to locking) is disabled due to lack of support for it in higher layers but it will be easy to reenable it once callers (sc_single_transmit() and sc_sm_single_transmit()) are adapted accordingly. For compatibility, all existing users call sc_lock() function with "resetok" parameter unset, but in future it might be possible to set this parameters in places where this is determined to be safe. Examples here would be card probing, very first operation during initialization and operations on cards that do not have any state which is cleared by reset. This all applies to PC/SC reader type. CT-API reader backend doesn't handle card locking at all, while OpenCT reader backend will need to be adapted for this semantics for card resets by other contexts to be handled correctly (if that is possible at all since it looks like OpenCT doesn't provide card reset notification). For now, PKCS#11 library does full card detachment + reattachment when it receives card reset notification (this means that for example on Firefox the user is prompted to type his PIN again). Note this is still better that the old behavior of simply being stuck in non-working state until application restart (or card reinsertion). In future, it might be possible to teach the PKCS#11 library to handle card reset gracefully. Best solution would be to have a ability to reinitialize card after reset without detaching and reattaching it. This will need first an implementation of such operation in all card drivers which will need keeping enough card state to know what needs to be set again in card in at least some of them. Such state will then need to be shared between contexts accessing the same card (even from different processes) to avoid different context having a different view of card, so it's no trivial task. Other option would be to reload necessary card state at the beginning of every transaction (after the card was locked), but this might not be viable for every card type. Minidriver have a bit different requirements so it will be adapted to handle card resets in next commits. Signed-off-by: Maciej S. Szmigiero <[email protected]>
- Loading branch information