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

Reply via email to