Interfacing with a PayPass card under Linux using LibNFC
After spending some time searching the Web, I realised that not many people have successfully attempted to do so using LibNFC (or if they have, they’ve decided to remain quiet about it, for reasons unknown); and resorted to trying to use CardPeek‘s EMV script – which worked successfully with the ISO/IEC 7816 contact interfaces of all of the cards that I’ve tried (until I accidentally broke one of the contact interface pins), but doesn’t work with my reader’s RFID transceiver…
nfc-list -v command, I was able to obtain the following information regarding the contactless interface:
1 ISO14443A passive target(s) found: ATQA (SENS_RES): 00 04 * UID size: single * bit frame anticollision supported UID (NFCID1): 29 8b cf 51 SAK (SEL_RES): 28 * Compliant with ISO/IEC 14443-4 * Not compliant with ISO/IEC 18092 ATS: 78 80 82 02 80 31 80 66 b0 84 12 01 6e 01 83 00 90 00 * Max Frame Size accepted by PICC: 256 bytes * Bit Rate Capability: * Same bitrate in both directions mandatory * Frame Waiting Time: 77.33 ms * Start-up Frame Guard Time: 1.208 ms * Node ADdress not supported * Card IDentifier supported * Historical bytes Tk: 80 31 80 66 b0 84 12 01 6e 01 83 00 90 00 * Tk after 0x80 consist of optional consecutive COMPACT-TLV data objects; the last data object may carry a status indicator of one, two or three bytes. See ISO/IEC 7816-4 126.96.36.199 for more info Fingerprinting based on ATQA & SAK values: * JCOP31 v2.3.1 * SmartMX with Mifare 1K emulation
I’ve modified the formatting of that command’s output slightly, so that it fits within this blog’s template boundaries – but the data is identical to what I see when running it.
Since I couldn’t find any useful example code in C or C++ for exchanging ISO/IEC 7816 APDUs with contactless cards, I decided to investigate the possibility of modifying one of the TAMA scripts (UltraLightRead.cmd) in the LibNFC repository, and discovered that by prefixing the EMV commands mentioned in Saush’s blog post with
40 01, I was able to make the card respond to a request for the Payment System Environment.
The resulting script looks like this:
02; // Get firmware version 4A 01 00; // 1 target requested // Select the payment system environment 40 01 00 A4 04 00 0E 31 50 41 59 2E 53 59 53 2E 44 44 46 30 31;
If I get chance, I’ll probably see if I can modify CardPeek’s EMV script somehow to generate APDUs with
InDataExchange (0x40) framing, and hopefully get contactless mode working with my reader (so that I don’t have to implement EMV by myself, in order to test other commands) – but I have my doubts, somehow.
In the meantime, I hope that this discovery is vaguely helpful for others…