Is it possible to write data to specific blocks in memory on the NfcV (ISO 15693) tag? E.g. write data to block# 5 or any specific block#.
I am new to NFC technologies. I am creating an application to read/write NfcV (ISO 15693) tags. I have successfully create the reading portion but the problem is on writing portion. When I want to write some text data into the tag it start from block# 2 to onward and every time doing the same procedure. I have searched lot but I can't find any solution to write data to specific blocks.
The exact details depend on which ISO 15693 compatible chip is inside the tag. The ISO 15693-3 standard lists different write commands. Support for these are all optional, so your tag may support one or more of these or even use a proprietary command for writing data. I would recommend to look up the datasheet of the chip and/or acquire the ISO standard to find out what the right command is.
Once you know what the right command is, you can simply pass the bytes of the command in a byte array to the NfcV.transceive() method. (Usually the command bytes consist of a flag byte, followed by a write command byte, one or more block bytes and the data bytes to be written.)
Tried the following: Getting the "Tag was lost" Exception:
nfc.connect();
byte[] arrByt = new byte[7];
arrByt[0] = 0x40;
arrByt[1] = 0x21;
arrByt[2] = 0x06;
arrByt[3] = 0x00;
arrByt[4] = 0x00;
arrByt[5] = 0x00;
arrByt[6] = 0x00;
byte[] response = nfc.transceive(arrByt);
I guess the android framework does not handle the response from the ISO15693 tags very well. I have been playing with HF-I tags. Few commands work flawlessly and for few other commands the NFC stack throws TAG Lost exception.
Related
I'm trying to build a C++ wrapper around libnfc to make a communication between my Android and the PN532 RFID module.
This helped me a lot: http://nfc-tools.org/index.php/Libnfc:APDU_example
This code is meant to send an APDU command where the body is contained in message (I'm not sending any header bytes etc.) and read the response into response.
Problem: If message exceeds 262 characters then I get a buffer overflow detected error. Otherwise it works perfectly well. I don't even think the error is thrown by the NFC library.
bool send(const std::string &message, std::string &response){
std::vector<uint8_t> apduCmd(message.begin(), message.end());
uint8_t *capdu = &apduCmd[0];
size_t capdulen = apduCmd.size();
uint8_t rapdu[10];
size_t rapdulen = 10;
// BUFFER OVERFLOW HERE
int res = nfc_initiator_transceive_bytes(m_nfcDevice, capdu, capdulen, rapdu, rapdulen, 500);
if (res<0) {
return false;
}
if(res<2 || rapdu[res-2] != 0x90 || rapdu[res-1] != 0x00){
return false;
}
// byteArrayToString omitting the last two bytes
response = byteArrayToString(rapdu, 0, res-2);
return true;
}
The limit of 262 bytes is a hard limit imposed the PN532 NFC chip. This is the maximum size of the raw data that can be sent (and received) in one InDataExchange command. libnfc explicitly enforces this limit for the method nfc_initiator_transceive_bytes() (see the definition of abtCmd in pn53x_initiator_transceive_bytes() and the definition of PN53x_EXTENDED_FRAME__DATA_MAX_LEN).
What you could do to overcome this limit, is to compose your own ISO/IEC 14443-4 blocks (using InCommunicateThru, i.e. nfc_initiator_transceive_bytes() with m_nfcDevice->bEasyFraming turned off. While each frame would still be limited to 263 bytes (the PN532 actually allows 264 bytes for InCommunicateThru but libnfc seems to limit this to 263 bytes), you can then pack your extended length APDUs into multiple ISO/IEC 14443-4 I-blocks. However, you would need to handle the whole ISO/IEC 14443-4 framing on your own (which means that you also have to take care of receive acknowledgements, etc.)
Finally, since the other communication endpoint is an Android device: Many Android devices do not support extended length APDUs. Consequently, even if you send longer APDUs, you might not be able to receive and process them on the Android side. Also, be aware that you should send proper APDUs conforming to the structures defined in ISO/IEC 7816-4 (i.e. APDUs with valid header and lengths fields), otherwise you might run into issues when talking to some devices.
I have a a number of newbie NfcA questions. There seems to be little guidance on this in the docs and elsewhere on the web, so I hope no-one minds me stringing a few basic questions together here...
I am using nfcA.transceive() to write data to my NTAG213 tag like this:
byte[] result = nfcA.transceive(new byte[] {
(byte)0xA2, // WRITE
(byte)(pageNum & 0x0ff),
myData[0], myData[1], myData[2], myData[3]
});
1. The result array is a single byte of value 10. What does this mean and what other values should I look out for?
I am also using the same method to read data from my NTAG213 tags:
byte[] result = nfcA.transceive(new byte[] {
(byte)0x30, // READ
(byte)(pageNum & 0x0ff)
});
2. I expected this to return 4 bytes of user data (i.e., the 4 bytes that correspond to my pageNum), but it returned 16 bytes. Why is that the case?
3. Is it good practise to check nfcA.isConnected() before calling nfcA.connect() and, if so, is there likely to be any sigificant performance penalty in doing so? (I ask as I have seen code examples from reputable sources of both.)
4. Is it better to call nfcA.setTimeout() before or after nfcA.connect()?
5. For my NTAG213 tags nfcA.getMaxTransceiveLength() returns 253. Does that really mean I can write up to 251 bytes of user data (plus the 2 other bytes) in one go and, if so, is that advisable or is it better to write each page (4 bytes) with separate nfcA.transceive() calls?
1. The result array for a WRITE command is a single byte of value 10. What does this mean and what other values should I look out for?
The value 10 (Ah in hexadecimal or 1010b in binary representation) is an explicit ACK, an acknowledgement returned when a command that returns no data succeeds.
The possible values are actual data, ACK, passive ACK, or NACK. These are defined by the NFC Forum Digital Protocol specification and by the NFC Forum Type 2 Tag Operation specification.
If the command is expected to return actual data on success, the data is returned instead of an explicit ACK value.
ACK is defined as a 4-bit short frame (see NFC Forum Digital Protocol specification and ISO/IEC 14443-3 for further details) with the value 1010b (Ah).
A passive ACK is defined as the tag not sending a response at all within a certain timeout.
NACK is defined as a 4-bit short frame with the value 0x0xb (where x is either 0 or 1).
The NTAG213/215/216 product data sheet is a bit more specific on possible NACK values:
0000b (0h) indicates an invalid command argument.
0001b (1h) indicates a parity or CRC error.
0100b (4h) indicates an invalid authentication counter overflow.
0101b (5h) indicates an EEPROM write error.
In addition to the above, the NFC stack implementations on some devices do not properly propagate NACK responses to the app. Instead they either throw a TagLostException or return null. Similarly, you might(?) get a TagLostException indicating a passive ACK.
Thus, you would typically check the result of the transceive method for the following (unless you send a command that is expected to result in a passive ACK):
try {
response = nfca.transceive(command);
if (response == null) {
// either communication to the tag was lost or a NACK was received
} else if ((response.length == 1) && ((response[0] & 0x00A) != 0x00A)) {
// NACK response according to Digital Protocol/T2TOP
} else {
// success: response contains ACK or actual data
}
} catch (TagLostException e) {
// either communication to the tag was lost or a NACK was received
}
2. I expected the READ method to to return 4 bytes of user data (i.e. the 4 bytes that correspond to my pageNum), but it returned 16 bytes. Why is that the case?
The READ command is defined to return 4 blocks of data starting with the specified block number (in the NFC Forum Type 2 Tag Operation specification). Thus, if you send a READ command for block 4, you get the data of blocks 4, 5, 6, and 7.
3. Is it good practise to check nfcA.isConnected() before calling nfcA.connect() and, if so, is there likely to be any sigificant performance penalty in doing so?
If you receive the Tag handle directly from the NFC system service (through an NFC intent) the tag won't be connected. So unless you use the Tag handle before calling nfca.connect(), I don't see why you would want to call nfca.isConnected() before. However, calling that method before connecting has barely any performance overhead since calling isConnected() on a closed tag technology object will be handled by the famework API without calling into the NFC system service. Hence, it's not much more overhead than a simple if over a boolean member variable of the NfcA object.
4. Is it better to call nfcA.setTimeout() before or after nfcA.connect()?
I'm not sure about that one. However, the transceive timeout is typically reset on disconnecting the tag technology.
5. For my NTAG213 tags nfcA.getMaxTransceiveLength() returns 253. Does that really mean I can write up to 251 bytes of user data (plus the 2 other bytes) in one go and, if so, is that advisable or is it better to write each page (4 bytes) with separate nfcA.transceive() calls?
No, you can only write one block at a time. This is limited by the WRITE command of the NTAG213, which only supports one block as data input.
However, a transceive buffer size of 253 allows you to use the FAST_READ command to read multiple blocks (up to 62, so up to 45 for the NTAG213) at a time:
int firstBlockNum = 0;
int lastBlockNum = 42;
byte[] result = nfcA.transceive(new byte[] {
(byte)0x3A, // FAST_READ
(byte)(firstBlockNum & 0x0ff),
(byte)(lastBlockNum & 0x0ff),
});
I'm trying to authenticate any sector of a MIFARE classic card. I'm using a twinlinx mymax sticker (which makes almost any bluetooth device NFC enabled). It sends commands to a connected NFC tag. I've already made a connection and sent and recieved data with a Ultralight C tag, but so far I had no success on accessing a Mifare Classic. Here is my authentication code:
private boolean authenticate(int sector, byte[] key, boolean keyA) {
byte[] cmd = new byte[12];
// First byte is the command
if (keyA) {
cmd[0] = 0x60; // phHal_eMifareAuthentA
} else {
cmd[0] = 0x61; // phHal_eMifareAuthentB
}
// Second byte is block address
cmd[1] = (byte) 0x03;
// Next 6 bytes are the key
System.arraycopy(key, 0, cmd, 2, 6);
// Next 4 bytes is the UID
System.arraycopy(Answer, 3, cmd, 8,4);
byte[] test = null;
//this makes a connection to the NFC tag (and this works)
TR.ConnectToExternalCard(AUTH, (byte)0x00);
//checking if the tag is still connected
if (TR.isCardPresent() == true){
//sending command to authenticate
test = TR.SendCommandPropAndWaitResponse(cmd, (byte) 0x00);
}
try {
if (test != null) {
return true;
}
}
I'm using standard MIFARE Classic keys, the tags are fresh from the factory. The complete command (in bytes) which is sent to the tag is:
[0x60, 0x3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xf4, 0xa9, 0xfb]
Any Ideas? The tag seems to be non-responsive... tried accessing other Classic tags but also had no success. Thanks!
It is hard to say what you are doing wrong using an SDK that is not publicly available. However, the API looks familiar enough, so I will give it a try anyway. I can think of a number of things you may try (in decreasing order of likeliness):
The UID bytes may be in the wrong order, so try reversing them.
Perhaps Answer does not only contain the UID, but other bytes, too (e.g. SAK), and you are copying the wrong bytes from it.
The MIFARE Classic tags you have may have a 7-byte UID and you are not using the correct 4 bytes from that.
May be TR.SendCommandPropAndWaitResponse() is the wrong method to use. Perhaps there is a dedicated method for MIFARE Classic.
The MyMax sticker may not support MIFARE Classic. I don't see explicit confirmation on their website that they do. However, indications are that their solution is based on NXP hardware, which always supports MIFARE Classic.
i write some data (NDEF) into Mifare Ultralight Tag. Then the tag is set to read only with Ndef.MakeReadOnly(). The Tag seems to be read only afterwards.
But reading the Tag content shows, that only pages (4-15, Lx bytes are set to 1) are locked, the three BLx Bytes are left 0. When i got it right, this means that Pages Locks could be altered again. Page 2, Bytes 2 = 11111000, Page 2 Byte 3 = 11111111 - (see http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf , page 12).
Is there a way to make the tag permanently write protected?
Thanks for your time.
To make the whole tag read only, you could get the tag again as a MifareUltralight instead of as a Ndef. Then you do
MifareUltralightTag.writePage(2,new byte[] {0x00, 0x00, 0xFF, 0xFF});
followed by
MifareUltralightTag.transceive(new byte[] {0x26});
to "activate the new locking configuration."
Could somebody provide an NFC-V tag reading example code?
Android Development Guide provides only the NFCDemo code that is for NDEF tag only. There are no resources for all the other kinds of tags. Thanks!
Reading block 0 demo working for an 15693 i-code sli
ByteArrayOutputStream out = new ByteArrayOutputStream();
out.write(new byte[] { (byte)0x20, (byte)0x20 }); //addressed mode, read single blocks,
out.write(nfcV_tag.getTag().getId()); //address
out.write(new byte[] { (byte)blockIndex }); //block 0
byte errorcode_and_block0[] = nfcV_tag.transceive(out.toByteArray());
//1st byte should be 0 if everything is ok. next 4 bytes are block 0
Well - With Android 2.3.4 you can use the ordinary NDEF format and use the usual android API to write to the tag just like any other ndef complient tag. NFC-V has been the major feature for Android 2.3.4 after all.
If you otherwise want to communicate with the NFC-V tag: It's nothing more then the ISO 15693 standard. You should be able to find the PDUs that this tag understands with a google-search and then you can roll your own implementation if you really want.