Question

I am making a NFC application that use ISO-DEP (ISO 14443-4) as TagTechnology. I try to execute a authentication with a DESFire EV1.

The authentication work well if the chaining of the command is without pause.

But if for exemple, I make something that take time (like the Thread.Sleep after NATIVE_AUTHENTICATION_COMMAND_P1) I got an error 0x911C ("Command code not supported") during the authentication command part 2 from the card. Normaly the error come when the authentication has been canceled. Like if the card got another command during the authentication procedure that have nothing about it.

The problem is that my application do nothing else that sending the selectApplication, Authentication Part 1, Sleep and the Part 2. I have try the same code in C++ with a PCSC Reader and the Sleep is not the probleme, even with 5 second sleep the authentication have work on my computer. So I would like to know if Android is "playing" with the card even after giving the Intent to the application or if the Frame Waiting Time (ISO 14443-4) is not working or NDEF "pull" broke the authentication or...

(The value of NATIVE_AUTHENTICATION_COMMAND_P2 is a exemple)

 final byte[] NATIVE_AUTHENTICATION_COMMAND_P1 = new byte[]{(byte)0x90, (byte)0x0A, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x00};
 final byte[] NATIVE_AUTHENTICATION_COMMAND_P2 = new byte[]{(byte)0x90, (byte)0xAF, (byte)0x00, (byte)0x00, (byte)0x10, (byte)0xAB, (byte)0xB4, (byte)0x66, (byte)0xA4, (byte)0xE9, (byte)0x99, (byte)0xFF, (byte)0x5C, (byte)0xD7, (byte)0xF3, (byte)0xA7, (byte)0x81, (byte)0x62, (byte)0x2F, (byte)0xFA, (byte)0x16, (byte)0x00};
 final byte[] NATIVE_SELECT_COMMAND = new byte[]{(byte)0x90,(byte)0x5A,(byte)0x00,(byte)0x00,(byte)0x03,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00};

IsoDep tag = IsoDep.get(tagFromIntent);

tag.connect();

byte[] result;
result = tag.transceive(NATIVE_SELECT_COMMAND); //SUCCESS
result = tag.transceive(NATIVE_AUTHENTICATION_COMMAND_P1); //SUCCESS

// Thread.sleep(1000);

result = tag.transceive(NATIVE_AUTHENTICATION_COMMAND_P2); //result = 0x90AE without Sleep and with Sleep 0x911C ("Command code not supported")

tag.close();

If someone have an idea because I am totally lost :)

UPDATE: After the help of michael-roland and his tips; I have use the reader-mode API with NDEF check disable and delay presence check to 10 second to get my chaining command working perfectly !

@Override
protected void onResume() {
    super.onResume();
    Bundle options = new Bundle();
    options.putInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, 10000);
    mAdapter.enableReaderMode(this, this, NfcAdapter.FLAG_READER_NFC_A | NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK, options);
}

@Override
public void onPause() {
    super.onPause();
    mAdapter.disableReaderMode(this);
}
Was it helpful?

Solution

You ran into a known problem with the NFC stack for Broadcom's NFC chipset. The issue is known for quite a while (see this Android bug report, something similar applies to non APDU-based tags too).

In your case, the problem is that while the connection between the phone and the tag is idle, Android automatically performs a presence check. While this presence check is correctly implemented for NXP's NFC stack, the Broadcom version uses a READ BINARY command (for IsoDep cards) or an equivalent READ command (for other tag technologies).

So, if your command sequence is slow, Android might send a READ BINARY APDU somewhere in between your commands.

Unfortunately, this bug still exists in Android 4.4.2 and to me it seems unclear if Google will eventually do something about it. UPDATE: There is a new presence check mechanism starting with Android 5.

If you use Android 4.4, there is, however, something you can do to avoid the bug: Use the new reader-mode API to tweak the presence-check timeout. If you do not use NDEF, you could even completely disable the presence-check.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top