What is an APDU, and when does your code need one?
An APDU is the command and response unit of ISO/IEC 7816-4. A command carries four header bytes, CLA, INS, P1 and P2, then optional data and an expected length; the response carries data and two status bytes. Code needs one for Type 4 tags and for cards, through IsoDep on Android or NFCISO7816Tag on iOS.
Command and response
A command APDU starts with four bytes. CLA gives the class of the instruction, INS the instruction itself, P1 and P2 its parameters. Data follows when the command sends any, preceded by its length, Lc, and the command can end with Le, the length of the response it expects. Apple's NFCISO7816APDU initializer builds one from exactly these fields.
Lengths come in two sizes. A standard APDU carries at most 255 bytes of data, 261 bytes in all, and an extended one up to 65535, according to the IsoDep reference, and some Android controllers refuse the extended form, as the controller limits page explains. Apple's initializer encodes Le from a number: 256 sends 00 in the short form, 65536 sends 0000 in the extended form, and -1 declares that no response data is expected.
The response is data followed by two status bytes, SW1 and SW2. The data can be empty, and Apple notes that it can be empty even when the command succeeded.
When code needs one
Whenever the tag speaks ISO/IEC 7816-4: Type 4 tags, which store NDEF in files reached by APDUs, and cards built on ISO/IEC 14443-4, which Android exposes through IsoDep. A Type 2 tag does not; it answers the NFC-A commands described on the Type 2 memory page.
On Android, IsoDep.transceive() sends the APDU and returns the response with its two status bytes at the end. On iOS, a tag session delivers NFCISO7816Tag and its sendCommand(apdu:); for MIFARE Plus and DESFire tags delivered as NFCMiFareTag, Apple provides sendMiFareISO7816Command for the same purpose.
Reading or writing NDEF on a Type 4 tag takes no hand built APDU: Android's Ndef class and the Core NFC NDEF calls do it. Code builds APDUs for what NDEF does not cover, such as a file other than the NDEF file, an access condition, or an application of its own. The Type 4 NDEF file page follows the sequence the platforms run.
Selection comes first
An ISO/IEC 7816-4 card holds applications and files, and a command acts on what is currently selected. SELECT, instruction 0xA4, chooses by name when P1 is 0x04, the name being an application identifier, and by file identifier when P1 is 0x00. These are the values Android's open source NFC stack uses to reach NDEF on a Type 4 tag.
iOS restricts the first kind. A SELECT with P1 set to 0x04 must name an application listed in the app's Info.plist, otherwise the call fails with readerErrorSecurityViolation, according to the sendCommand reference. The session also selects one of the listed applications when it discovers the tag, and reports which in initialSelectedAID; the declarations page covers the list.
A selection lasts no longer than the tag's power. A tag that leaves the field loses both, so code that reconnects selects the application again before its next command.
Reading the status bytes
90 00 means the command completed. The other values come from ISO/IEC 7816-4 or from the card's application, and the Android stack names those a Type 4 reader meets most often:
| SW1 SW2 | Meaning |
|---|---|
90 00 | Command completed |
6A 82 | File or application not found |
67 00 | Wrong length |
69 86 | Command not allowed |
6B 00 | Wrong parameters |
6D 00 | Instruction not supported |
6E 00 | Class not supported |
Each platform hides them in its own way. On Android they are the last two bytes of the array transceive() returns, and code that treats the whole array as data mistakes them for content. On iOS the error covers communication only, and an app that checks the error and not sw1 and sw2 takes a refusal for a success.
Frequently asked questions
Does a Type 2 tag use APDUs?
No. It answers NFC-A commands such as READ and WRITE; APDUs belong to Type 4 tags and to cards built on ISO/IEC 14443-4.
Why does iOS refuse my SELECT command?
A SELECT by application identifier must name an identifier listed in Info.plist. Otherwise Core NFC fails the call with readerErrorSecurityViolation.
What does 6A 82 mean?
That the file or application named in the command was not found. After a SELECT of the NDEF application, it means the tag has none.
Is an APDU encrypted?
Not by its format. Protection, where a card has any, is defined by the card's application and described in the chip's datasheet.