Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SCardTransmit, how to read and write smartcard

I'm working on a printer, trying to read and write a contactless card.

This is the manual of the hardware and software I'm using: manual contactless

The process to ineract with the smart card (read and write in it), if I understood correctly, is:

  1. Establish the Context using SCardEstablishContext()
  2. Connect to the card through the selected reader using SCardConnect()
  3. Talk to the card using SCardTransmit()

Is that correct?

Points 1 and 2 works ok and return 0 (SCARD_S_SUCCESS), but I have problems with SCardTransmit.

  • If I want to read block 5 for example, this is the code I use:

     SCARD_IO_REQUEST pioRecvPci;
    
     DWORD dwActiveProtocol, dwSendLength, dwRecvLength;
     BYTE pbRecvBuffer[16];
     BYTE pbSendBuffer[] = {(BYTE)0xFC, (BYTE)0xB0,(BYTE)0x05, (BYTE)0x00, (BYTE)0x00};
    
     dwSendLength = sizeof(pbSendBuffer);
     dwRecvLength = sizeof(pbRecvBuffer);
    
      SCARD_IO_REQUEST pioSendPci;
    
         pioSendPci.dwProtocol=SCARD_PROTOCOL_T0;
         pioSendPci.cbPciLength= sizeof(pioSendPci);
    
     ret = SCardTransmit(cardHandle,                // SCard API
                            &pioSendPci, 
                            pbSendBuffer, dwSendLength,
              NULL, pbRecvBuffer, &dwRecvLength);
    

    It returns an error code 22.

    If I change SCARD_PROTOCOL_T0 to SCARD_PROTOCOL_T1, it seems to work (I don't know if pbRecvBuffer values are correct): pbRecvBuffer has 2 bytes with values: 6e 00 and ret = 0.

    Have these values sense?

    I read SCardTransmit api (SCardTransmit) and there I understand I have to use protocol T=0, does it mean I have to put SCARD_PROTOCOL_T0 to work? In that case, why I receive an errror 22? What I'm doing wrong?

  • If I want to write in block 5, I follow the same process: SCardEstablishContext, SCardConnect and SCardTransmit. I change pbSendBuffer to: {(BYTE)0xFC, (BYTE)0xD0,(BYTE)0x05, (BYTE)0x00, 0x10};, but I don't understand well where is the data, and what params I should put on SCardTransmit. Could you provide me an example of this?

Thank you very much!

like image 565
A.Vila Avatar asked Sep 19 '25 10:09

A.Vila


1 Answers

I know this post is old but I had the same problem with error code 22 on the transmit function. The problem was related to the protocol used.
And actually the simplest is to use the return from the connect function to the card to determine which protocol structure to use with the transmit function.

I am therefore sharing the piece of code which works well and solves the problem of error code 22. Afterwards it remains to use the correct APDU command to obtain the correct result, depending on the card used. The example in the code should allow you to select the AID of a bank card.

hope this can help those who are facing the same error code 22

// Initialization
LONG responceCardFonc = 0;
SCARDCONTEXT contextManager;
LPCSTR readerName = "";
SCARDHANDLE identConnCard;
DWORD m_dwActiveProtocol;
SCARD_IO_REQUEST protocolStruct;
BYTE apduCommand[] = {0x00,0xA4,0x04,0x00,0x07,0xA0,0x00,0x00,0x00,0x03,0x10,0x10};
DWORD nbDataCommand = sizeof(apduCommand);
BYTE dataRecept[256];
DWORD nbDataRecept = sizeof(dataRecept);
QString stringDisplay;

// Determination Name Reader
readerName = "SCM Microsystems Inc. SCR331-DI Smart Card Reader 0";

// Creating a Context
responceCardFonc = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &contextManager);

// If Context Established
if(responceCardFonc==SCARD_S_SUCCESS)
{
  // Card Connection
  responceCardFonc = SCardConnectA(contextManager,readerName,SCARD_SHARE_SHARED,SCARD_PROTOCOL_Tx,&identConnCard,&m_dwActiveProtocol);

  // If Card Connection Successful
  if(responceCardFonc==SCARD_S_SUCCESS)
  {
    // Determining the Protocol Structure to Use
    if(m_dwActiveProtocol==SCARD_PROTOCOL_T0) protocolStruct = *SCARD_PCI_T0;
    if(m_dwActiveProtocol==SCARD_PROTOCOL_T1) protocolStruct = *SCARD_PCI_T1;

    // Transmission to Card
    responceCardFonc = SCardTransmit(identConnCard,&protocolStruct,apduCommand,nbDataCommand,NULL,dataRecept,&nbDataRecept);

    // If Transmission Successful
    if(responceCardFonc==SCARD_S_SUCCESS)
    {
      // Construct String to Display
      for(int i=0;i<nbDataRecept;i++) stringDisplay += QString::number( dataRecept[i], 16 ).toUpper()+((i<nbDataRecept-1)?" ":"");

      // Display String
      qDebug() << stringDisplay;
    }
    // End - If Transmission Successful
    else qDebug() << "Transmission Error - Error Code ["+QString::number(responceCardFonc)+"]";
  }
  // End - If Card Connection Successful
  else qDebug() << "Card Connection Error on "+(QString)readerName+"\nError Code ["+QString::number(responceCardFonc)+"]";
}
// End - If Context Established
else qDebug() << "Context Creation Error"+QString("\n")+"Code Erreur ["+QString::number(responceCardFonc)+"]";

Of course this piece of code is integrated into a project correctly configured with the “winscard” APIs

like image 163
Juan - 6510866 Avatar answered Sep 21 '25 02:09

Juan - 6510866