Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NFC Tag becomes "corrupted" after writeNdefMessage interrupted I/O

Tags:

We have an Android application that communicates with an NFC tag on a custom hardware device. The hardware device can also communicate and perform operations on the tag mounted to it.

The Android application communicates with the NFC tag in two ways:

  1. IsoDep#transceive(byte[]) for triggering a power cycle of the hardware device.
  2. Ndef#writeNdefMessage(NdefMessage) for writing an NdefMessage/NdefRecord with some user data.

Functionally, these operations look something akin to:

private static final byte[] NDEF_SELECT_APP_FRAME = new byte[] {
    (byte) 0x00, (byte) 0xA4, (byte) 0x04,                  
    (byte) 0x00, (byte) 0x07, (byte) 0xD2,                  
    (byte) 0x76, (byte) 0x00, (byte) 0x00,                  
    (byte) 0x85, (byte) 0x01, (byte) 0x01                   
}; 

private static final byte[] SYSTEM_FILE_SELECT = new byte[] {   
    (byte) 0x00, (byte) 0xA4, (byte) 0x00,                  
    (byte) 0x0C, (byte) 0x02, (byte) 0xE1,                  
    (byte) 0x01                                             
};                                                              

private static final byte[] TOGGLE_GPO = new byte[] {           
    (byte) 0xA2, (byte) 0xD6, (byte) 0x00,                  
    (byte) 0x1F, (byte) 0x01, (byte) 0x00                   
}; 

boolean recordSuccess = writeRecord(tag, intent, context);
if (recordSuccess) {
    boolean success = transceive(NDEF_SELECT_APP_FRAME, tag, context)
            && transceive(SYSTEM_FILE_SELECT, tag, context)
            && transceive(TOGGLE_GPO, tag, context);
    if (success) {
        // Success!
    } else {
        // Error!
    }
}

We've found that, very occasionally, it seems possible that I/O can be interrupted while the Ndef data is being written (we're not sure why, but we presume pulling the phone away from the tag at just the right time is the reason). This seems to result in the tag being in a "corrupted"-like state, where the previous Ndef data can no longer be found on the tag. In fact, tag.getTechList() won't even list Ndef as an available technology on the tag, though it was originally available.

All further attempts to write Ndef data to the tag will then fail because Ndef.get(tag) will return null.

As far as I'm aware, the normal procedure from this point would be to reformat the tag using NdefFormatable. However, NdefFormatable is not listed as a technology type in tag.getTechList(), and so NdefFormatable.get(tag) also returns null.

Questions:

  1. Why is the tag seemingly becoming corrupted/erased?
  2. Why is Ndef not listed as a tag technology after corruption, even though the tag originally supported it?
  3. How can we recover from this state, given that NdefFormatable.get(tag) seems to return null?

EDIT: The NFC chip appears to be a M24SR04-Y. The specification sheet can be found here: https://www.st.com/resource/en/datasheet/m24sr04-g.pdf.

Capability Container contents shown by TagInfo app:

# Capability Container (CC) file content:
Mapping version 2.0
CC length: 15 bytes
Maximum Le value: 246 bytes
Maximum Lc value: 246 bytes
NDEF File Control TLV:
* Length: 6 bytes
* NDEF file ID: 0x0001
* Maximum NDEF data size: 512 bytes
* NDEF access: Read & Write
[0] 00 0F 20 00 F6 00 F6 04 06 00 01 02 00 00 00    |.. ............ |
like image 395
Orbit Avatar asked May 28 '20 03:05

Orbit


2 Answers

After having a glance at the datasheet shared by you, following are my observations:

  • 0xE103 : CC File
  • 0x0001 : NDEF File
  • CC File is Read-Only from both RF and I2C
  • Max NDEF File Size: 512 bytes
  • Read and Write : Free Access
  • Max No of bytes can be read or write in one operation : 246 bytes
  • Assuming that CC content has never changed: 00 0F 20 00 F6 00 F6 04 06 00 01 02 00 00 00 : 15bytes

With reference to the code snippet of operations shared by you:

  1. What is it that you are doing in TOGGLE_GPO? Session Open, WIP or MIP?
  2. I suspect that the card is going in corrupted-like state, when it is interrupted during this phase
  3. Assuming that you are not modifying the CC file content in writeRecord().
  4. If possible, share the low-level details of every steps that you are performing, which will help understand better.

Update:

  • Now that the possibility of Corrupted CC is ruled out, the next step would be to do the same for NDEF TLV, especially the V block where the NDEF File ID, Max. NDEF size and Read/Write Access of NDEF File are stored, by comparing Working and Corrupted state values.
  • Identify the step, where upon occurring error the card goes to corrupted state. This could be achieved by logging every step. If the card gets corrupted on interruption at a specific step consistently, then it will narrow down the hunt.
  • Try to SET the StateControl, when the card is in corrupted state. This is just a random thought, but might help.

Cheers!

like image 114
Adarsh Rotte Avatar answered Sep 30 '22 19:09

Adarsh Rotte


This is very difficult to answer without knowing what type of card it is and what NFC specification it conforms to.

The first step to understanding this is to get the datasheet for the NFC card. It might be worth using an Android app like nxpinfo on it to try and determine the chip type and NFC specification type on the card which could then lead to the datasheet/nfc specification used.

Answers
2) The support of NDEF on a card is determined by a thing called the "Capability Container" in most specs, This can be stored at a specific block address or other method of reading it.

If there is no readable "Capability Container" by the defined method for the NFC specification used then the Card won't be seen as NDEF capable and formatable.

Possible this is a custom card and the "Capability Container" has been corrupted as well.

1) Unknown without more details about the card type, but another cause could be that 2 reader/writers are trying to access the card at the same time (One from the hardware device and one from the App). Normal NDEF writing/reading should not cause a problem but may be the hardware device does some custom card access method.

Hopefully when you use the App to access the Card the Hardware is powered off, so it is not possible for for this type of clash.

If not may be make a simple coil of wire connected to an LED to make a basic NFC field detector to see if the hardware is periodically doing stuff with the card that might cause a clash.

3) Again difficult to answer with knowing more about the card, BUT it might be possible on what is probably a custom card type to re-write the "Capability Container" at a low level to make formatable again if this was the cause of the problem.

Update

As it appears to be a NFC Type 4 chip but also has and I2C interface as well. It also has some extended non standard commands

Question

I guess the hardware is connected via i2C?

Reading the spec there seems to be 2 levels of security on the card that are outside of the NDEF spec (I'm not sure that the nxpinfo app will understand the values but might show them).

So it is possible that the NDEF file is password protected or made read only.

If the NDEF file has a write password the normal NDEF formatting won't be able to format it.
You will need to use a non standard Verify command and password to be authorised before you can format it.

If the NDEF file has been permanently locked (made read only) then only the I2C connection can unlock the NDEF file. A card in this state cannot be formatted via any Android App.

The next step is to update the question with the Hex contents of the Capability Container, so the security level can be determined.

Update 2

Ok, so the card is not password protected or locked because the last 2 bytes of the CC file are 00

And as Adarsh some better logging might help determine the cause hopefully your transceive methods check the response byte array from the IsoDep.tranceive and log any non success codes and any exceptions like TagLostException , IOException, etc are also caught and logged.

While you state that the corruption might be caused by the phone going out of range, the Datasheet also shows that the I2C connection can take priority over the RF connection from the phone by killing the RF connection, this could also cause corruption of the NDEF data.

If the RF connection has been killed by the I2C connection then the phone would probably not be able to do anything with the RF connection until it was removed out of range and brought back again.

At the moment I don't have any other thoughts than checking the binary contents of the NDEF file yourself with a low level binary read on a corrupted and non corrupted card. (The Taginfo App might be able to do this with it's full scan function)

But as this card updates cards (can write at the start of the card or at any offset) I would expect Android to always start at the beginning when writing an NDEF message so should not matter if the TLV byte markers were corrupted by a truncated write for a new writeNdefMessage. The corruption of the TLV could stop Android from reading NDEF messages from the file. (Need to check Android OS source code to confirm what it does)

like image 41
Andrew Avatar answered Sep 30 '22 21:09

Andrew