Search code examples
c++apduomnikey

How can I send APDU command using C++?


I want to make software that connecting to an HID OMNIKEY 3128 smart card "Aviator chip", I have succeed to connect this device using an API function “SCardConnect”, but according to developer guideline (Page 17) https://www.hidglobal.com/doclib/files/resource_files/plt-03099_a.3_-_omnikey_sw_dev_guide.pdf I must change a voltage sequence to solve Read/Write problem, and this done by sending an APDU command, “How can I send this commands using c++, is there any API function to do that like a SCardConnect?


Solution

  • Disclaimer first: I did not use the PC/SC API before but became curious with your question as it is remotely related to a project I did long ago. - Thus, the following is untested and should be taken with a grain of salt :-)

    If I understand page 26 in your linked document correctly, the functions to be used are either (preferably) SCardTransmit or SCardControl.

    A sample, how to transmit an APDU command can be found, e.g. on https://ludovicrousseau.blogspot.com/2010/04/pcsc-sample-in-c.html. It is worth reading descriptions given there. The relevant parts mainly boil down to:

    // dwActiveProtocol is result of SCardConnect
    SCARD_IO_REQUEST pioSendPci = dwActiveProtocol == SCARD_PROTOCOL_T1 ? *SCARD_PCI_T1 : *SCARD_PCI_T0;
    BYTE pbRecvBuffer[258];
    BYTE cmd[] = { 0x00, 0xA4, 0x04, 0x00,
                   0x0A, 0xA0, 0x00, 0x00,
                   0x00, 0x62, 0x03, 0x01,
                   0x0C, 0x06, 0x01 }; // this is just an example, not the right command (yet, see below).
    dwRecvLength = sizeof(pbRecvBuffer);
    LONG rv = SCardTransmit(hCard, &pioSendPci, cmd, sizeof(cmd), NULL, pbRecvBuffer, &dwRecvLength);
    

    Now, the question is, how to compose cmd. Here, the C# examples on https://github.com/hidglobal/HID-OMNIKEY-Sample-Codes might be helpful. Specifically, you should look at SetVoltageSequence() and VoltageSequence.SetApdu(). If I understand this correctly, something around the following should work:

    BYTE constexpr voltageSequence = 0x1B; // or 0x39 or ..., see page 17 in your linked document.
    BYTE cmd[] = { 0xFF, 0x70, 0x07, 0x6B, 
                   0x0B, 0xA2, 0x09, 0xA1,
                   0x07, 0xA3, 0x05, 0xA0,
                   0x03, 0x82, 0x01, voltageSequence, 0x00};
    

    I assume, that all required code for communicating with the device should be available more or less in the linked C# example code.