Android : NFC APDU command response '6700' Wrong length' - android

I am sending below APDU command to ISODep tag and I am getting '6700 wrong length'
byte[] command = new byte[]{ (byte)0x80, (byte)0xD0, (byte)0x01, (byte)0x00, (byte)0x07,(byte)0x22 , (byte)0x22,(byte)0x12 , (byte)0x34 , (byte)0x56 , (byte)0x78 , (byte)0x90 };
Please suggest if something is wrong in above command.

You are sending a case 4 APDU there, right? Your Lc indicates 0x07 bytes of data, and there's a Le of 0x90 trailing.
Check with your specification whether this command is actually expecting a case 4 structure, or whether you just got the data length in the Lc field wrong (0x08 instead of 0x07).

Related

I would like to understand the manipulation of NfcV ISO-15639

I'm new in NFC Technology!
I have difficulty understanding how to manipulate blocks.
byte[] cmd = new byte[] {
(byte)0x20, //FLAG
(byte)0x21, //WRITE SINGLE BLOCK COMMAND
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, //UID
(byte)0x00, //OFFSET
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 //DATA
};
My questions about code above:
What is a FLAG and what is its function?
What is a UID and what is its function? in code the UID line has 8 "index", is it possible to increase or decrease the size? instead of 8 as in code, decrease to 6 or increase to 10?
What is a OFFSET and what is its function?
In line 6 of the commented code as DATA, is this where I define the byte size of my block? In code, it has 4 indexes, does it mean that my data stored in the block will have 4 bytes? can i increase or decrease?
Lets go suppose, i have a 4 bytes data myData = "ABCD", and i want to write this data to block 04 of my tag, how would I do it according to the code mentioned above?
I'm not an NfcV expert but below is what I have learnt about Tags and low level access
What is the Flag byte mean? - Unknown BUT http://www.ti.com/lit/an/sloa141/sloa141.pdf Section 4.1 has details of ISO 15693 Flag meanings
But one of the Flag means using addressed or un-addressed mode, this leads on to the UID
What is UID bytes - Most tags have a serial number or Unique IDentifier number
In addressed mode you have to provide the correct UID of the card you are reading or writing from for it to succeed. This means you won't write or reading from the wrong card. There is a command to read the UID from the card first.
In un-addressed mode the UID is provided as zeros
You have worked out the the second byte is 0x21 for an write command.
0x20 for read command
http://www.ti.com/lit/an/sloa141/sloa141.pdf Section 4.2 has details of ISO 15693 Command values and as you can see must of them are Optional or Custom and support and what they do depends on the chip.
The OFFSET as you put it is the memory block offset from the first block or better described as the memory address (think of this like the page number in a book). Most chips split the memory in to blocks of a set size. There are some chips that use a single byte as the memory address and there are some that use 2 bytes.
Each block is a set number of bytes, it's common for it to be 4 bytes, but I've seen chip specs where it is 128 bytes.
The data structure you gave in your question is usually used as a template of a well formed command for chip you are trying to communicate to.
The DATA 4 bytes in your example are just place holders for the actual data your want to write, you should copy in to the template the actual 4 bytes you want to write before the send the command.
So when you are using it for write you have to adjust the OFFSET/Memory Address to be the "right page of the book" and copy in the right number of "letters" that can be written on the page in to the DATA part of the template
Some examples of NfcV code for Android from a chip manufacturer can be seen at the end of https://www.st.com/content/ccc/resource/technical/document/application_note/group0/76/0e/00/a0/1b/04/4c/f2/DM00103491/files/DM00103491.pdf/jcr:content/translations/en.DM00103491.pdf
So the last question Lets go suppose, i have a 4 bytes data myData = "ABCD", and i want to write this data to block 04 of my tag
example of constructing the command
// Command Template
byte[] cmd = new byte[] {
(byte)0x20, //FLAG
(byte)0x21, //WRITE SINGLE BLOCK COMMAND
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, //UID
(byte)0x00, //OFFSET
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 //DATA
};
// The data to be written
String myData = "ABCD";
// Get the data as bytes
byte[] data = myData.getBytes();
// Change the "OFFSET" / "Block number" to the the fourth Block
// If that what was meant by "block 04"
// The addresses start at Zero and the byte array starts at zero
// So the "Block Number" is the 11th byte in the command
cmd[10] = (byte)((3) & 0x0ff);
// Copy in 4 bytes of data in to bytes 11 to 15
// Starting at byte 0 in the data array
System.arraycopy(data, 0, cmd, 11, 4);
For Reference what the arraycopy Parameters https://docs.oracle.com/javase/7/docs/api/java/lang/System.html#arraycopy(java.lang.Object,%20int,%20java.lang.Object,%20int,%20int)

FIDO2 - Get Authenticator Info issue

I am developing Android authenticator.I am getting {-125,0,1,4} byte array from webauthn client after pairing. When I decoding this array
-125 (0x83) - MSG
1 (0x01) - length of the data
4 (0x04) - AuthenticatorGetInfo
I am not sure about 0 in this array. Please let me know is there any meaning for this 0.
For this request, I am sending response as CBOR data.
00a60182684649444f5f325f30665532465f563202816b686d61632d73656372657403506435323965353235383533343133663304a462726bf5627570f564706c6174f469636c69656e7450696ef505190400069f01ff
I am notifying above data by using Fido Status as follows.
for (byte[] frame : response.toFrames(mMTU)) {
getFidoStatus().setValue(frame);
mGattServer.notifyCharacteristicChanged(device, getFidoStatus(), true);
}
After that I am not getting any request/response from webauthn client. I am sending KEEPALIVE(0x82) command with value PROCESSING(0x01) for every kKeepAliveMillis(500ms). Is there any issue with my implementation?
Please help me to proceed this. Thanks in advance.
This speciciation fully explains for you
https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-client-to-authenticator-protocol-v2.0-id-20180227.html#ble-framing-fragmentation
CMD is 0x83 (MSG)
Length of DATA is 2 bytes: HLEN byte and LLEN byte.
In your case, length of DATA is 0x0001 (= 1). The DATA is 0x04

Android NfcV get information command returns only one byte

I'm writing an app for reading binary infos of NFC tags. Here's the code of the NFC intent handler function:
protected void onNewIntent(#NonNull Intent intent)
{
try
{
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
NfcV nfcV = NfcV.get(tag);
byte[] cmdInfo = new byte[]{(byte) 0x02, (byte) 0x2b}; // 'Get info' command
byte[] answer = nfcV.transceive(cmdInfo); // Read info from tag.
...
}
catch(IOException e)
{
...
}
}
If I run this function reading an NFC tag on a Samsung S3 Neo everything works fine, the answer variable is filled with the expected data:
00 04 4B A0 14 01 00 A0 07 E0 F3 07
Howewer if I run the same function reading the same NFC tag on a Huawei P8lite the answer variable is filled with only one byte:
03
In case of an error, the ISO 15693-3 standard says that I should receive something like
01 03
I.e. at least two bytes, where the second byte is the error code. So the answer I'm actually getting is theoretically not possible.
What am I doing wrong? Does it depend on the mobile hardware? And how can I fix it?
Since you are not using an addressed command (Address_flag not set, no UID field in request). You should not receive any resonse at all if an optional command is not supported by the tag (not even an error code). Hence you should neither receive 03 nor 01 03 according to the standard.
Note that NFC chipsets in Android devices often have limitations when it comes to ISO/IEC 15693 and do not support the complete standard. For instance, some chipsets are known to have issues with non-addressed commands. You could work around that by using the addressed version of the command:
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
NfcV nfcV = NfcV.get(tag);
byte[] cmdInfo = new byte[]{
(byte)0x20,
(byte)0x2B,
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 };
System.arraycopy(tag.getId(), 0, cmdInfo, 2, 8);
byte[] answer = nfcV.transceive(cmdInfo);
You might also want to test with different settings for the Data_rate_flag since the NFC chipset on your device might have problems with VICCs responding with at high data rate.

Mifare Ultralight C Lock

I'm attempting to lock a Mifare Ultralight C tag. I want to set NDEF pages 0x04 to 0x27 to read-only. I think this can be achieved via Ndef.makeReadonly().
Additionally, I would like to set pages 0x29 to 0x2F to be password protected (for read and write) so they can only be accessed after authentication was successful. I'm struggling to understand which bytes need to set in lock bytes (page 0x28, bytes 0, 1) and if sectors 0x2A and 0x2B need to be set as well.
I'm attempting to set NDEF pages 0x04 to 0x27 to readonly. I think this can be achieved via Ndef.makeReadonly().
Not necessarily, Ndef.makeReadonly() might only set the read-only flag in the capability container (according to the NFC Forum Type 2 Tag Operation specification).
If you want to make sure to set the actual lock bits, you would connect the tag as NfcA or MifareUltralight tag technology and issue a write command for the lock bits instead.
NfcA nfcA = NfcA.get(tag);
nfcA.connect();
byte[] result1 = nfcA.transceive(new byte[] {
(byte)0xA2, /* CMD = WRITE */
(byte)0x02, /* PAGE = 2 */
(byte)0x00, (byte)0x00, (byte)0xFF, (byte)0xFF /* DATA = lock pages 3..15 */
});
byte[] result2 = nfcA.transceive(new byte[] {
(byte)0xA2, /* CMD = WRITE */
(byte)0x28, /* PAGE = 40 */
(byte)0x0F, (byte)0x00, (byte)0x00, (byte)0x00 /* DATA = lock pages 16..27 */
});
Also see Mifare Ultralight: lock specific pages for the coding of the lockbits.
I would like to set pages 0x29 to 0x2F to be password protected (for read and write) so they can only be accessed after authentication was successful.
Using the write command that I showed above, you would first write your authentication key into pages 44..47. You would then write AUTH1 (page 43) as all-zeros. Finally, you would write AUTH0 (page 42) as 0x29 0x00 0x00 0x00 to require authentication for pages 41 and up. Actually I would suggest to lock pages 40 and up so that nobody could set the lock bits for those pages. Alternatively, you could set the block locking bits (i.e. write 0x1F 0x0F 0x00 0x00 to page 40) so that the lock bits for the unlocked pages cannot be changed.

NFC Update Binary command sequence not clear

I write data to a 14443A Tag with a HTC One SV (PN544, Android 4.1.2), using the "binary update" APDU command, but I see between the message size (byte#5) and the beginning of the NDEF record two additional zero-bytes (#6,7). I checked the ISO7816 standard and can't see the purpose of these two additional bytes, is this conforming to the standard ?
I'm parsing the APDU/NDEF message in a C-program, how can I find the beginning of the NDEF message, can I assume that these two zero bytes are always there or do I have to search for the "D1" byte ?
The ISO7816, UPDATE BINARY:
CLA As defined in 5.4.1
INS 'D6'
P1-P2 See text below
Lc field Length of the subsequent data field
Data field String of data units to be updated
Le field Empty
If b8=1 in P1, then b6-5 are set to 0 (RFU bits). bit5-1 of P1 are a short EF identifier and P2 is the offset of the first byte to be updated in data units from the beginning of the file.
If b7=1 in P1, then P1||P2 is the offset of the first byte to be written in data units from the beginning of the file.
cmdMessage = "\u0002"+"en"+"erase";
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
NdefRecord txtRecord = new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], cmdMessage.getBytes());
NdefMessage newMessage = new NdefMessage(new NdefRecord[] { txtRecord});
writeNdefMessageToTag(newMessage, tag);
0x00: 0x02
0x01: 0x00 CLA
0x02: 0xD6 INS, bin update
0x03: 0x00 P1, Address MSB
0x04: 0x00 P2, Address LSB
0x05: 0x0E Lc, msg size
0x06: 0x00 ??
0x07: 0x00 ??
0x08: 0xD1 NDEF header, TNF
0x09: 0x01 type-len
0x0A: 0x08 payload-len
0x0B: 0x54 "T"
0x0C: 0x02 0x02
0x0D: 0x65 e "en"
0x0E: 0x6E n
0x0F: 0x65 e "erase"
0x10: 0x72 r
0x11: 0x61 a
0x12: 0x73 s
0x13: 0x65 e
after sending the 0x9000 acknowledge the smartphone is sending another write message:
what's the purpose of this additional write access ?
I guess that 0x0C is the size of the NDEF message which was written in previous sequence,
but why sending this information in a separate write access ?
0x00: 0x03<\n>
0x01: 0x00<\n>
0x02: 0xD6<\n>
0x03: 0x00<\n>
0x04: 0x00<\n>
0x05: 0x02<\n>
0x06: 0x00<\n>
0x07: 0x0C<\n>
The first two bytes of the NDEF message file contain the data size (i.e. the number of valid bytes in the file). In the first write command (i.e. while writing the NDEF message, these two bytes are set to zero. Thus, if the write operation is interrupted before the whole message was written, reading the the NDEF file will show an empty file instead of a corrupted NDEF message. Then, when the whole NDEF message was successfully written to the file, another write command is issued to update the data size to the size of the NDEF message. Now, if the file is read, the reader will receive the correct NDEF message size and will thus be able to read the full NDEF message.

Categories

Resources