XSIID - "Tag is not NDEF-compliant"

Pages 0, 1, 2, 3 are for configuration. They contain things like the UID and the Capability Container, some of which you cannot change, and some of which you should be very fucking careful changing.

I think Devilclarke left a bunch of empty pages at the beginning before writing the URI NDEF record because the forum URL is not very long, and he wanted to make sure that all the messed up bytes left over from whatever was previously written was completely overwritten. Wouldn’t want any vestigial data left over. Here’s an example of what a very similar NDEF record looks like on my tag using TagInfo, without the empty pages at the beginning:

[04] +r 03 26 D1 01 |␃&.␁|
[05] +r 22 55 00 68 |"U␀h|
[06] +r 74 74 70 73 |ttps|
[07] +r 3A 2F 2F 66 |://f|
[08] +r 6F 72 75 6D |orum|
[09] +r 2E 64 61 6E |.dan|
[0A] +r 67 65 72 6F |gero|
[0B] +r 75 73 74 68 |usth|
[0C] +r 69 6E 67 73 |ings|
[0D] +r 2E 63 6F 6D |.com|

Thanks a lot, you’ve been a lot of help!


I think he was mimicking what TagWriter does by mistake… the null bytes are where the TLV values are supposed to live, but instead of writing those TLVs, TagWriter writes nulls… it’s a bug… but the way Android handles NDEF messages, it keeps reading data until it hits the NDEF message envelope header… then it starts reading the NDEF message, record(s), and payload(s).


Sorry, I keep thinking of new questions… Is it pretty much always the first four pages for configuration, or does it depend on the chip? I don’t want to accidentally overwrite some config data because I thought it was free space…
Also, do the pages always start at 0, or do some start at 1?

For the NTAG chip variants the first four pages are usually the configuration bytes.
NTAG 216: xNT, NExT

The other chip variants are different. MIFARE has its own janky memory structure. DESFire chips have more of a file system. JavaCard is this whole other thing. The LF chips are all over the place.

In most technology the beginning is index position 0. That makes index position 1 the “second” position. It’s something you have to constantly keep in mind, especially when you’re working so close to the silicon like in this case.


That makes sense, thank you for taking the time to answer my questions!

All really good comments, my only aim was to get it back to a situation where the tlv data and following ndef was correct ish to allow tagwriter and other apps to work normally.

1 Like

actually… hah… the config bytes (8.5.7 Configuration pages in the spec doc) are typically at the end of NTAG’s memory or in the case of the NTAG I2C in xSIID, the end of sector 0.

But… let’s start at the top…

  • Page 00 contains UID bits, read only, can’t mess this up

  • Page 01 more UID bits, read only, can’t mess this up

  • Page 02 some reserved crap and lock bytes. OTP (program once). You can definitely mess this up if they aren’t disabled (set to lock themselves)

  • Page 03 is the CC (capability container) which has a specific format for use as an NFC compliant device. Also OTP. You can definitely mess this up if it isn’t locked (we lock it first with lock bytes from page 02 before using lock bits in page 02 to lock page 02 so no further memory pages can be locked by the lock bits in page 02… get it?

  • Pages 04-E1 are user memory

  • Pages E2-E5 (on an NTAG216) are configuration bytes. These bytes reside at different memory addresses on smaller capacity NTAGs like the NTAG213, NTAG215, etc.

  • Page E2 contains dynamic lock bytes. OTP. Can mess up if not disabled.

  • Page E3 contains config bits you don’t want to mess with in byte 0, data mirroring settings in byte 1 and 2 (you might want to mess with these if you want, but do it carefully), and AUTH0 resides in byte 3.

AUTH0 is important because it controls from which memory page and all following pages are protected with the password feature. We set this to E2 to leave user memory unaffected, but protect the configuration bytes (even though we set E2 to lock itself, it kinda makes sense). So, for example, if you set the AUTH0 byte in page E3 to say… FF… then nothing will be affected by the password feature. If you set it to 00 then everything will… or if you set it to E5 then just the password block and PACK (password acknowledgement) will be protected. This is an important thing to understand, because if you set AUTH0 to E6 or greater, then the password stored in E5 will not be protected by the password. That means even though you can’t read block E5 (it does not allow reading at all), you can write to it without any restriction (so long as the dynamic lock bytes haven’t locked this block)… so even though you don’t know the password, you could write whatever password you wanted to this block and then you’d know the password… get it? So, AUTH0 is a powerful setting that should be fully understood before you mess with it.

  • Page E4 contains basically one single manageable byte… byte 0… it’s called the ACCESS byte, which is broken down in to various bit value flags. In general, you really don’t want to mess with this byte… except maybe to change bit 7… but right next to it is CFGLCK (lock config) which you definitely don’t want to flip to a 1… and then we have AUTHLIM at the end (bits 0-2) which basically sets a maximum number of password attempts…

… but let’s get back to the PROT bit… it’s short for protection… and it determines what kind of effect the password feature has on memory pages specified by AUTH0 or greater. If PROT is 0 then you can read any memory pages from AUTH0 or greater but need to authenticate before you can write to any of those pages protected by AUTH0… or you can set PROT to 1 and then you will need to authenticate before you can read or write to any of the memory pages specified by AUTH0 or greater.


All of the above is identical for xSIID in the first sector… basically the first memory sector in the NTAG I2C chip in the xSIID is identical to the NTAG216… the only difference is, the xSIID’s chip has another sector… sector 1… and this sector only contains user memory and no configuration bytes at all. The challenge has been for apps and OS libraries alike to properly deal with this sector as an extension of user memory. That’s what the TLVs are supposed to be for… to help guide the NFC parser to skip the config bytes in sector 0 and move on to sector 1 and keep writing… but nobody seems to be parsing all of the configuration bytes properly, or the TLVs… it’s a wreck.


So, for instance, if I was to set auth0 to 04, then all the user data and end config would all be protected by the password, but anything before 04 wouldn’t be? And, would there be any reason not to lock all the way back to 00?

Correct… though there may be other protections in place (locks for example) for prior pages. The password feature is it’s own thing, separate from lock byte operations… so it may be redundant or have no appreciable effect… depending.

No not really… but maybe… it depends… so like, you can’t change pages 00 or 01 anyway so it’s pointless. Possible, but pointless. But, let’s say your static lock bytes were still set to 00 00 (default), which means you can still permanently lock basically the first half of your tag… and page 03 with the CC is also wide open for changes. If you wanted to retain your options you might protect all that with the password feature… but honestly… for an implant… we didn’t ever see that as having a point so we locked page 03 and then locked the static lock bytes themselves.

1 Like

And, I’m guessing that you would set the password with a command similar to A2E5FFFFFF? Does the XSIID come with a password by default?

One thing to mention… the password feature is not secure… not at all. It’s kinda like locking your car door. There are tons of ways around it from a shim to breaking the window… I don’t consider it “protection”.

That makes sense I suppose, does a more secure option exist on these chips? I’m not too worried about the security aspect, more interested in the ability to dissuade it against accidental or unwelcomed writes, if that makes sense

Specifically the user data, the actual useable portion of the storage

yep. the password is just stored in a special memory page that doesn’t allow reads… but yes if AUTH0 is set to E6-FF you can just issue that command to set the password. If AUTH0 includes E5 then you will need to issue an auth command first, then you can write to page E5

The current batch of NExT does have a password set, but we decided to leave the xSIID password set to factory default FF FF FF FF. We did set AUTH0 to enable protections, just to ensure there was an extra step at least to alter those bytes… but it was a gamble… so many badly written NFC apps will gladly issue the PWDAUTH command with factory default just as a check mechanism, and in doing so, may possibly impact the AUTHLIM counter (if it’s enabled) which is a terrible disservice as an app to take a potentially destructive action without even informing the user… but then once PWDAUTH is issued, it can freely overwrite config bytes by accident… if it’s badly written… so you see it’s a bit of a risk for our users to not set a password on the xSIID…

I think though that once we have our own app (@hoker), we will program the next batch to have a non-factory but defacto default password… maybe we will make all DT product passwords DNGR from the factory… dunno yet.


not on these chips… DESFire chips have way more security options… but if all you’re looking to do is protect unwelcome writes from casual attackers, then the password feature is enough for that.

Interesting. It would be really nice if the Dangerous NFC 2.0 app had some preconfigured commands for fixing the XSIID setup and helping to set a password to prevent the PWDAUTH issue with other apps, though I don’t know how hard that would be to accomplish… Just an idea!
For now, are there any blocks in particular that should be protected by autho0 to prevent config bytes being overwritten by other apps, or is just changing the password from default enough?

That sounds exactly like what I was looking for! Thanks for answering all my questions!

Well this is a little more complex. We can fix the TLVs but I’ve already tested and all the apps out there don’t respect them … can’t fix that… so we must make our own app that not only properly addresses the TLV issue but also lets customers utilize the full 2kB of storage. In short, we have to reinvent the wheel because everyone else’s wheels are square shaped.

That also has nothing to do with us… each app transforms the ASCII input you type into their password boxes into their own bullshit. In the Dangerous NFC app used to protect the xNT and set a password, what you type is what is written to page E5… but that’s not true for TagWriter or NFC Tools or any others I’ve found… they modify the data somehow… dunno how and dunno why. This makes it so the password feature is basically locking you into using only that app for all password protected operations. I’ve seen this with people who set a password with TagWriter and then later want to use NFC Tools to do some password stuff and it doesn’t work… so they have to set the password back to factory default, then switch apps and set the password again with that app…


So once again, we must reinvent the wheel.

I think in general you’re ok… I hope… but I would maybe set the password to something other than factory default… that will help… and leave AUTH0 set to E2

1 Like

That makes sense, thanks again for taking the time to help!

1 Like

Is it possible to make sure this is disabled? An if it isn’t, to disable it?
Also, how do I go about altering data that is protected by AUTHO0, in other words, what command would be used to authenticate with the password? And, is it necessary to send another command after the fact to “lock” it again?
Thanks in advance!

You can’t disable authlim really… you could lock config bytes but then you disable all configuration changes so the options available are not practical.

To alter data protected under AUTH0 you will be to authenticate first. At this point you really should be taking the datasheets to heart, so I’m not going to keep picking bits out for you… read it. Absorb it. Know it.

Any authentication is only valid during the iso14443a session. Once power is lost, so too is the authenticated state.