Android NFC communication with Mifare DESFire EV1

2019-01-18 00:52发布

问题:

Using a Nexus 4 and the latest Android API level 18 to communicate with a Mifare DESFire EV1 AES tag is giving me a headache. Following the NXP native protocol in order to write and read this type of tag, these steps must be followed:

  1. Select application
  2. Authenticate
  3. Write or Read

To do it so, I use Android's IsoDep class which provides access to ISO 14443-4 properties and I/O operations. The very weird thing about it is that once I send the select application native command I get an unexpected response. Imagine I have the AID F4013D so I send:

-> 5AF4013D
<- 6E00

All possible responses must be one byte length (success 0x00 or error_code) and never two or more. Thus, the 0x6E before the success response is absolutely unexpected. It does not happen always, and when it does not and works fine, the select application and authentication processes work fine. However once authenticated the write command does not have a correct behavior, all write commands finishes with a 0xAF from the PICC instead of a success 0x00. It seems like the PICC expect some extra data when it should not (I send the correct length payload). If I send any other command I get a 0xCA (Command Aborted) error code.

-> 5AF4013D
<- 00 /*Success*/
-> AA01
<- AFA8394ED57A5E83106B4EE72FD2BB0CC4
-> AF148F525E1DDE0AD6AB60B4B615552475C91F2E8D89B8523E4465113DD5BD19C6 
<- 0066D255C93F2F492AFE3715C88964F1BD /*Authentication success*/
-> 3D02000000030000222222 /*Write 3 bytes to file nº2*/
<- AF /*Unexpected, 0x00 was expected*/

As it is normal, if I send these type of commands with a personal reader (non Android NFC) it always works fine. It seems that something in the Android NFC API is going strange, when it should just be a raw data transporter which never interprets or modifies data.

I have also tried with ISO 7816-4 APDU structure with the same result. As a curiosity, with a Galaxy Nexus does not happen the select application strange response, but yes the write command one always.

回答1:

(1) For the first part concerning the status code 6E00:

6E 00 is not a "strange byte 0x6E + success status code 0x00". Instead it is a response APDU status word 6E 00 ("Class not supported"). This indicates that there was previous communication with the card using APDU-based access (e.g. Android itself tried to read the card as Type 4 tag and did not reset the connection afterwards). Thus, the card will expect all further communication to be in ISO 7816-4 APDUs. In that case (i.e. if you receive an ISO 7816-4 status code like 6E 00), you could continue using DESFire APDU wrapped commands by simply wrapping your native commands.

EDIT: In fact, this is somewhat expected behavior on an NFC device. The idea is that an NFC device will automatically scan detected tags for NDEF messages. In the case of a DESFire card, the NFC device will detect the card as potential Type 4 tag. Thus the NFC device will send ISO 7816-4 APDUs as it would send to any other Type 4 tag. Hence, if the NFC device doesn't reset the communication with the tag before handing the detected tag to the app, the app can only communicate using ISO 7816-4 APDUs. Note, however, that I would consider it a bug that this happens only for some activations on the same device. In my opinion, the behavior on one specific device model should be consistent.

EDIT: While I would not consider this behavior a bug, it is actually caused by a known bug (#58773) in Android's NFC stack for devices with Broadcom NFC controller. On affected devices, the automatic presence check sends ISO 7816-4 APDUs at timed intervals that cause DESFire cards to switch into ISO 7816-4 APDU mode.


(2) For the second part concerning the (unexpected) response code 0xAF:

Could it be that your file's communication settings are setup for either "plain communication secured by MACing" or "fully enciphered communication"? In that case, simply sending the three data bytes would not be enough. Instead you would need to send either the plain data plus MAC or the padded, CRCed and encyrypted data. Hence the 0xAF indicating that the card expects further data.

EDIT: So to summarize the comments below. After sending further bytes (one byte at a time for each received 0xAF status code: AF FF) it turned out that exactly 8 more bytes were expected by the card. 8 bytes is exactly the size of the CMAC for AES authentication. Thus, the communication settings were set to "plain communication secured by MACing".



回答2:

You can find a good library with some examples here: https://github.com/grundid/nfctools

There is also another one with some examples here: https://code.google.com/p/ismb-npp-java/

I hope this help for your purpose!