In contrast to previous posts, I'm going for some real results here.
The goal is to use the smart card session I created in the previous posts, to have a discussion with the application running on the card:
- Open a session with the smart card,
- retrieve ID and card version.
A summary of terms used:
- APDU: it's a protocol to interact with the software that's running on some smart cards.
- ISO14443_4: a protocol for smart cards that can represent their internal functionality as APDU interactions
The Infineon card that's on the reader in this post is specialised to provide key / encryption related functionality.
The card holds a number of keys (going fast here, there's a lot more to it) that can be used in secure transactions.
A few of the APDU functions are:
- store and communicate public keys
- generate keys
- hash data based on its private key
I'm not using any of these here. I'm going to show public key exchange in a next blog.
In this post, I open an APDU application session, and return the card's APDU ID.
An APDU session is really like running an application on a server. The card has to be on the reader, to keep a session alive, and to keep giving energy to the card.
Once you remove the card, the session is broken and void.
APDU Command Code
All the values from line 2 to line 7 are exactly the same APDU command bytes as in Infineon's application developer instructions.
I've pasted the relevant part in the table below the code.
void CardISO14443::selectApp() { uint8_t cls = 0x00; uint8_t ins = 0xA4; uint8_t p0 = 0x04; uint8_t p1 = 0x00; uint8_t data_out[13] = {0xD2, 0x76, 0x00, 0x00, 0x04, 0x15, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01}; uint8_t data_out_len = 0x0D; uint8_t data_in[20]; uint32_t max_data_in_len = 20;; uint32_t response_len; uint8_t send_le = 1; uint8_t apdu_status[2]; UfrFactory::Status status = UfrFactory::retvalConvert(uFR_APDU_Transceive( cls, ins, p0, p1, data_out, data_out_len, data_in, max_data_in_len, &response_len, send_le, apdu_status) ); if (status != UfrFactory::UFR_OK) { throw CardException(status); } }
There's only one line of code that calls the APDU app on the card: line 15.
Line 2 to 12 is declaring variables and preparing the message to the card.
Line 21-23 is exception handling.
Here's than analysis of line 6, the APDU command.
Because I'm running the first, mandatory command to start the app session, I can just reuse my analysis of the Android example app for the card:
Command analysis from my first post: |
---|
Send the SELECT APP command
This is the first command you have to send to the card before it can be used in a scenario. The APDU command: 00A404000DD276000004150200010000000100.
image source: User Manual Blockchain Security 2Go Starter Kit
APDU Send / Receive Communication Script
|
APDU Answer from the Card:
After sending the above APDU command the card, here's the reply received in the buffer data_in.
And my analysis of the Android phone app response is again valid, because I tapped the same smart card:
Response analysis from my first post: |
---|
Analyse the Reply
This is what what the card sends back: 0002090C2900020040001576312E309000.
|
Full scenario in the c++ main code (the Eclipse project with current version of the source is attached:
isocrd->setISO14443_4(); isocrd->selectApp(); isocrd->unsetISO14443_4();
I added the unsetISO14443_4() call while testing. During my tests, the second time I ran the program, with the card still on the reader, would fail.
I read in my reader's manual that it's mandatory to close the data stream to the app after the last APDU call.
That turns operation back to normal RF card mode, and fixes my test failure.
Related Blog |
---|
Blockchain - Talk Directly to the Infineon 2Go Smart Cards API |
NFC Card Reader Protocol of Digital Logic µFR - part 0: intent |
µFR NFC Card Reader - part 1: first C program for Linux (RPi, BB, ...) |
µFR NFC Card Reader - part 2: first C++ program |
µFR NFC Card Reader - part 3: C++ Class to handle ISO14443 / APDU cards |
µFR NFC Card Reader - part 4: first meaningful ISO14443 / APDU conversation |
µFR NFC Card Reader - part 5: refactor, look back at initial design |