Hi everybody,
Playing with opensc and the dnie driver I found a weird behavior. After some
tests I opened the following issue in opensc github:
https://github.com/OpenSC/OpenSC/issues/475
It seems that opensc in the method sc_reset finally sends a SCardReconnect with
SCARD_UNPOWER_CARD or SCARD_RESET_CARD (depending the do_cold_reset parameter).
But at the end of the sc_reset function opensc performs the following:
/* pcsc_reconnect unlocks card... try to lock it again if it was locked
*/
if(old_locked)
r = pcsc_lock(reader);
If the connection was previously locked, after the reconnect, it adds a lock
again (SCardBeginTransaction is called again inside pcsc_lock). My impression
is that this extra call adds one more lock in the pcsc (rContext->LockCount)
which is never released, and this ends in the complete lock of the card until
the current process finishes (no other process can access the card in shared
mode). Every call to pcsc_reset in opensc seems to add a lost lock in pcsc (and
the dnie driver calls to this reset).
I have done some little test with pcsc (with the little sample.c copied below)
and it seems that SCardReconnect does not lose the locks (in any case:
SCARD_SHARE_SHARED or SCARD_SHARE_EXCLUSIVE, SCARD_UNPOWER_CARD or
SCARD_RESET_CARD). But, just to be sure, can anybody confirm that
SCardReconnect maintains the locks (transactions)? Is the extra call done in
opensc to SCardBeginTransaction needed?
Thanks in advance!
#include <winscard.h>
#include <stdio.h>
#define CHECK_RV(method, rv) if (rv != SCARD_S_SUCCESS) { \
printf("%s: %s (0x%lX)\n", method, pcsc_stringify_error(rv), rv); \
return rv; \
}
int main() {
SCARDCONTEXT hContext;
SCARDHANDLE hCard;
DWORD dwActiveProtocol;
LONG rv;
SCARD_IO_REQUEST pioSendPci;
BYTE pbRecvBuffer[258];
DWORD dwRecvLength;
BYTE serial_cmd[] = { 0x90, 0xB8, 0x00, 0x00, 0x07 }; // serial number apdu
int i;
// establish the context
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
CHECK_RV("SCardEstablishContext", rv);
// connect to my reader
// SCARD_SHARE_SHARED or SCARD_SHARE_EXCLUSIVE
rv = SCardConnect(hContext, "Broadcom Corp 5880 [Contacted SmartCard] (0123456789ABCD) 00 00",
SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol);
CHECK_RV("SCardConnect", rv);
// just start a transaction
rv = SCardBeginTransaction(hCard);
CHECK_RV("SCardBeginTransaction", rv);
// send apdu to get the serial number => DNIe is T0
dwRecvLength = sizeof(pbRecvBuffer);
rv = SCardTransmit(hCard, SCARD_PCI_T0, serial_cmd, sizeof(serial_cmd), NULL, pbRecvBuffer, &dwRecvLength);
CHECK_RV("SCardTransmit", rv);
printf("response: ");
for (i = 0; i < dwRecvLength; i++) {
printf("%02X ", pbRecvBuffer[i]);
}
printf("\n");
// perform the reconnect
// SCARD_SHARE_SHARED or SCARD_SHARE_EXCLUSIVE
// SCARD_UNPOWER_CARD or SCARD_RESET_CARD
rv = SCardReconnect(hCard, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1,
SCARD_RESET_CARD, &dwActiveProtocol);
CHECK_RV("SCardReconnect", rv);
// send apdu to get the serial number => DNIe is T0
dwRecvLength = sizeof(pbRecvBuffer);
rv = SCardTransmit(hCard, SCARD_PCI_T0, serial_cmd, sizeof(serial_cmd), NULL, pbRecvBuffer, &dwRecvLength);
CHECK_RV("SCardTransmit", rv);
printf("response: ");
for (i = 0; i < dwRecvLength; i++) {
printf("%02X ", pbRecvBuffer[i]);
}
printf("\n");
// end the transaction
rv = SCardEndTransaction(hCard, SCARD_LEAVE_CARD);
CHECK_RV("SCardEndTransaction", rv);
// disconnect
rv = SCardDisconnect(hCard, SCARD_UNPOWER_CARD);
CHECK_RV("SCardDisconnect", rv);
// release
rv = SCardReleaseContext(hContext);
CHECK_RV("SCardReleaseContext", rv);
return rv;
}
_______________________________________________
Pcsclite-muscle mailing list
[email protected]
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pcsclite-muscle