2

I am using NFCA.transceive to write to NTAG213 and can successfully write to location 28h that holds the dynamic locks without any problems when the tag is empty. But when I try to write it back to its default state I get a TAG_LOST exception. All other fields reset fine such as the password, AUTH0, etc.

In the specification is says NTAG213 features "tearing" protected write operations to specific memory content and mentions 28h. Is that something to do with it? I did not understand the term "tearing".

I should mention that before I update I used the authentication and this must be working OK as everything apart from this page/location changes back. I have played around with order of writes to no effect.

Relevant code:

public String resetBDtag(Tag tag) {
    NfcA nfca = NfcA.get(tag);

    String resultString = "";

    byte[] result;
    try {

        nfca.connect();
        try {
        result = nfca.transceive(new byte[]{
                (byte)0x1B,  // Command: password Auth
                (byte)0x93, (byte)0xD0, (byte)0x55, (byte)0xB7
        });} catch (IOException e) {
            Log.e(TAG, "IOException while authenticating :" + resultString, e );
            resultString = "Error authenticating"+ e.toString();
        }



        try {
            result = nfca.transceive(new byte[]{
                    (byte) 0xA2,  // Command: WRITE
                    (byte) 0x29,  // Address: page 0x29 (2)

                    (byte) 0x04, (byte) 0x00, (byte) 0x00, (byte) 0xFF  // CF

            });
        } catch (IOException e) {
            Log.e(TAG, "IOException while resting Auth0 requirement :" + resultString, e );
            resultString = "Error removing Authentication requirement"+ e.toString();;
        }

        try {
            result = nfca.transceive(new byte[]{
                    (byte) 0xA2,  // Command: WRITE
                    (byte) 0x2B,  // Address: page 0x2B (2)

                    (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF  // Password
            });

        } catch (IOException e) {
            Log.e(TAG, "IOException while clearing password :" + resultString, e );
            resultString = "Error clearing password"+ e.toString();;
        }
        try {
            result = nfca.transceive(new byte[]{
                    (byte) 0xA2,  // Command: WRITE
                    (byte) 0x10,  // Address: page 0x10 (2)

                    (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00  // Status / Count
            });
        } catch (IOException e) {
            Log.e(TAG, "IOException while clearing the status data :" + resultString, e );
            resultString = "Error clearing status data"+ e.toString();;
        }
        try {
            // This does not work!
            result = nfca.transceive(new byte[]{
                    (byte) 0xA2,  // Command: WRITE
                    (byte) 0x28,  // CFG1

                    (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xBD  // reset CFG1

            });
        } catch (IOException e) {
            Log.e(TAG, "IOException while removing locked pages 18-19 :" + resultString, e );
            resultString = "Error removing locks"+ e.toString();;
        }


    } catch (IOException e) {
        Log.e(TAG, "IOException while writing MifareUltralight :" + resultString, e );
        resultString = "Can not speak to the tag!";
    } finally {
        if (nfca != null) {
            try {
                nfca.close();
                Log.d("finally","isoDep closed");
            }
            catch (IOException e) {
                Log.e(TAG, "Error closing tag...", e);
                resultString = "Can not close the connection to the  tag!";
            }
        }
    }
    return resultString;
}
Michael Roland
  • 39,663
  • 10
  • 99
  • 206
ZipNFC
  • 489
  • 1
  • 6
  • 16

1 Answers1

2

Regarding your write command for the dynamic lock bits

You try to write to byte 3 (i.e. byte 3 has a value other than 0x00 in your write command). You should not do that. The datasheet clearly states that you should set all RFUI bits to 0 (which applies to byte 3, as well as to some bits in bytes 1 and 2).

How the write command works for one-time programmable memory areas like the dynamic lock bits

The write command will do a logical OR between the current value of the page and the new value sent in the write command parameter. For instance, if the page is currently set to FF 0F 00 BD and you try to write 00 00 3F 00, the new value for the page will be FF 0F 3F BD. Hence, you can only set bits (= set to 1) in the dynamic lock bits but you can never reset them to zero.

Why your write command fails

You set the RFUI byte (byte 3) to 0xBD in your write command. This is not allowed.

What is "tearing" protection?

Tearing is when you remove (accidental or intentional) the tag from the reader during a write operation. This removal during a write could result in a partial write of a page, which would leave the memory in an undefined state. Tearing protection means that the tag will either fully complete the write or will not perform the write at all. Hence, the memory won't get into any unexpected state.

Michael Roland
  • 39,663
  • 10
  • 99
  • 206
  • Thank you so much for editing my question and thank you for you answer @Michael. I will try to fix this based on your information. One further question I have based on the answer is if you have dynamically locked some pages with a write is it possible to remove the locks with another write? I was trying to get them back to 0 and that is the state of a untouched tag? – ZipNFC Jul 31 '15 at 19:30
  • No, once you set any of the lockbits, you can't set them back to zero. Hence, you can't remove a lock. If you want simple password protection use AUTH0 instead to block writes/read+write for the last n pages. – Michael Roland Aug 01 '15 at 08:34
  • Ah - that has saved me a lot of time! I knew that you can't reverse a tag that is locked, so makes sense that a dynamic lock can not be reversed. I inherited this approach from another developer so will explore if this needs to be done as he is using Auth0 and password already. – ZipNFC Aug 02 '15 at 09:33