No response from MIFARE CLASSIC - android

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.

Related

I can't read the same bytes from NFC cards

I am testing with Mifare-Ultralight nfc card. It is new and not have private key.
NFC Tools app and NXP TagInfo app, show me a difference in bytes read respect to my read data. result 1 and result 2. That why I suppose my code is wrong
my code:
byte[] key = new byte[]{(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF};
StringBuilder result = new StringBuilder();
for(int i=0;i<64;i+=4){
if(util.authenticate(i, 0, key)){
for(int j=i;j<i+4;j++){
byte[] readData = util.read_block(i);
if(readData != null){
result.append(NfcUtil.toHexString(readData));
}
}
}
}
All authenticate in blocks return false, even I tried all key in extended-std.keys
I tried commenting authenticate method, but then the result of data is different. I think the problem is here.
047BB94E8B700000FBA30000E1103E00277E047BB94E8B700000FBA30000E1103E00277E047BB94E8B700000FBA30000E1103E00277E047BB94E8B700000FBA30000E1103E00277E0312D1010E5402656E68656C6C6F20773EE40312D1010E5402656E68656C6C6F20773EE40312D1010E5402656E68656C6C6F20773EE40312D1010E5402656E68656C6C6F20773EE46F726C64FE0000000000000000000000CE626F726C64FE0000000000000000000000CE626F726C64FE0000000000000000000000CE626F726C64FE0000000000000000000000CE62000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749000000000000000000000000000000003749
If I decode that data the info is there, but no in standard Type2 Ndef format. Or at least not equal to NFC tools output.
Is necessary authentication for get right data all time?
I would have to authenticate in all the blocks even if I only have a record on the card?
Your looping over the blocks is wrong
if you simplify the loop to just print out the blocks index you read
for(int i=0;i<64;i+=4){
for(int j=i;j<i+4;j++){
System.out.print(i);
}
}
gives a result of
00004444888812121212161616162020202024242424282828283232323236363636404040404444444448484848525252525656565660606060
So you are reading block 0 four times then block 4 four times, etc
Which matches the repeating patterns in your data
047BB94E8B700000FBA30000E1103E00277E047B
As a read of a mifare ultralight will give you 4 blocks of 4 bytes from the start address of the read command your loop should look like
for(int i=0;i<64;i+=4){
if(util.authenticate(i, 0, key)){
byte[] readData = util.read_block(i);
if(readData != null){
result.append(NfcUtil.toHexString(readData));
}
}
}
which means the start of the 4 block read is:-
0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60
(a read of block 0, returns data of blocks, 0,1,2,3 )
I also note that a mifare Ultralight don't have multiple keys/passwords for different memory areas and once you authenticated once you can access the Tag until it is Halted. I know you are using a proprietary API to access these Tags but you should not need call util.authenticate more than once. But calling it multiple times won't have a bad affect.

NFC - Help to exchange data between RC522 & Android HCE

I will explain my project :
I have my RC522 and a door connected on my Arduino UNO.
I can currently open the door with a MIFARE classic.
But now I want to open it with my Android smartphone, this is why I develop a HCE applet to accept the good APDU with the selected AID, then my phone will transfer the data in order to open the door.
But the problem is :
I don't know how to send an APDU command with my Arduino using the RC522.
Currently, for my MIFARE Cards, I use the https://github.com/miguelbalboa/rfid library.
My test code :
byte selectApdu[] = {
0x00, /* CLA */
0xA4, /* INS */
0x04, /* P1 */
0x00, /* P2 */
0x05, /* Length of AID */
0xF2, 0x22, 0x22, 0x22, 0x22,
};
byte * backData = (byte *)malloc(16*sizeof(byte));
byte * dataLen = (byte *)16;
status = mfrc522.PCD_TransceiveData(selectApdu,10,backData,dataLen,NULL,0,false);
if ( status != MFRC522::STATUS_OK) {
Serial.print(F("PCD_TransceiveData() failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
else
{
Serial.println(F("PICC_TransceiveData() success "));
}
Neverless, it doesn't work ( "Timeout in communication"), and I slowly need to think that the RC522 is not compatible...
It's an (well commented) open-source project. Just have a look to source code, for instance If you use MIFARE_Read function of MFRC522.cpp
MFRC522::StatusCode MFRC522::MIFARE_Read( byte blockAddr, ///< MIFARE Classic: The block (0-0xff) number. MIFARE Ultralight: The first page to return data from.
byte *buffer, ///< The buffer to store the data in
byte *bufferSize ///< Buffer size, at least 18 bytes. Also number of bytes returned if STATUS_OK.
) {
MFRC522::StatusCode result;
// Sanity check
if (buffer == NULL || *bufferSize < 18) {
return STATUS_NO_ROOM;
}
// Build command buffer
buffer[0] = PICC_CMD_MF_READ;
buffer[1] = blockAddr;
// Calculate CRC_A
result = PCD_CalculateCRC(buffer, 2, &buffer[2]);
if (result != STATUS_OK) {
return result;
}
// Transmit the buffer and receive the response, validate CRC_A.
return PCD_TransceiveData(buffer, 4, buffer, bufferSize, NULL, 0, true);
} // End MIFARE_Read()
You could see function PCD_TransceiveData is called and check source of this function:
/**
* Executes the Transceive command.
* CRC validation can only be done if backData and backLen are specified.
*
* #return STATUS_OK on success, STATUS_??? otherwise.
*/
MFRC522::StatusCode MFRC522::PCD_TransceiveData( byte *sendData, ///< Pointer to the data to transfer to the FIFO.
byte sendLen, ///< Number of bytes to transfer to the FIFO.
byte *backData, ///< NULL or pointer to buffer if data should be read back after executing the command.
byte *backLen, ///< In: Max number of bytes to write to *backData. Out: The number of bytes returned.
byte *validBits, ///< In/Out: The number of valid bits in the last byte. 0 for 8 valid bits. Default NULL.
byte rxAlign, ///< In: Defines the bit position in backData[0] for the first bit received. Default 0.
bool checkCRC ///< In: True => The last two bytes of the response is assumed to be a CRC_A that must be validated.
) {
byte waitIRq = 0x30; // RxIRq and IdleIRq
return PCD_CommunicateWithPICC(PCD_Transceive, waitIRq, sendData, sendLen, backData, backLen, validBits, rxAlign, checkCRC);
} // End PCD_TransceiveData()
You could called PCD_TransceiveData or PCD_CommunicateWithPICC functions.
UPDATE
You put 0 values for parameters: "backData", "backLen", and "validBits".
validBits could be null.
backData and backLen must be defined as byte.
UPDATE2
If you have a look at library support protocols It supports ISO/IEC 14443-3 (type A) and not supports ISO/IEC 14443-4 (type B).
If you have a look at Android HCE documentation :
Specifically, Android 4.4 supports emulating cards that are based on
the NFC-Forum ISO-DEP specification (based on ISO/IEC 14443-4) and
process Application Protocol Data Units (APDUs) as defined in the
ISO/IEC 7816-4 specification. Android mandates emulating ISO-DEP only
on top of the Nfc-A (ISO/IEC 14443-3 Type A) technology. Support for
Nfc-B (ISO/IEC 14443-4 Type B) technology is optional. The layering of
all these specifications is shown in the figure 3
In this post: HCE support for ISO/IEC 14443-3 Type B?
Looking at devices in the field, some devices use Type A for HCE and
some seem to use Type B. So it's basically the device manufacturer who
decides if Type A or Type B is used. The Android API provides no means
for the app developer to influence this.
So you have to check with another Android NFC device if your device emulate ISO/IEC 14443-3 (Type A) or ISO/IEC 14443-4 (Type B). You could use NfcTagInfo application on other android device to check this.

Android Mifare Classic authentication Key A not working

I'm having a problem in my application with the MifareClassic.autenticateSectorWithKeyA(int sector, byte[] keyA) method. I have tried many ways but it dose not authenticate.
My key A is:
byte[] key = new byte[] { (byte) 0x3c, (byte) 0x55, (byte) 0x28,
(byte) 0x12, (byte) 0x5c, (byte) 0x61, (byte) 0x00,
(byte) 0x5C, (byte) 0x71, (byte) 0x00 };
What does each byte in this key represent?
If I have a key like 3c5528125c61 as above, how should I write the byte array to authenticate, read block 2 and get the bytes?
What is an AID (Application code)? When should I use it?
Your key byte array does not make much sense as a MIFARE Classic key. A key for MIFARE Classic consists of only 6 bytes. Hence, this would be a possible value for key:
byte[] key = new byte[] { (byte)0x3c, (byte)0x55, (byte)0x28,
(byte)0x12, (byte)0x5c, (byte)0x61 };
How do I authenticate to a sector and read a data block?
In order to read block 2 (and assuming that it is readable after authenticationg with the above key), you would do something like the following:
Authenticate to the sector that contains the block to read (block 2 is located in sector 0, you can use the helber method MifareClassic.blockToSector() to obtain the sector number for a given block number.
If authentication was successful, you can read the block.
final MifareClassic mfc = MifareClassic.get(tag);
mfc.connect();
final int blockNumber = 2;
if (mfc.authenticateSectorWithKeyA(mfc.blockToSector(blockNumber), key)) {
final byte[] data = mfc.readBlock(blockNumber)
// TODO: do something with data
}
mfc.close();
What is AID (Application Identifier)? and when should I use it?
MIFARE Classic itself has a linear memory layout. I.e. one that is addressed based on block numbers, where each block contains 16 bytes. These blocks are grouped into sectors with individual access conditions and keys.
In order to logically assign this data (the sectors/groups of blocks) to specific applications (e.g. some data for a physical access control system, some data for an electronic purse, etc.) and, hence, to use one card for more that one application at the same time, the MIFARE Application Directory (MAD) was introduced. The MAD is basically a lookup table (located in sector 0 for MIFARE Classic 1K and in sectors 0 and 16 for MIFARE Classic 4K). This lookup table maps each sector of the card to one application. Applications are identified though a two byte value, the MIFARE application identifier (AID). Thus, if a card uses the MAD, an application can lookup its data sectors by browsing the MAD for its AID.

Android NFC Card emulation with fixed UID

I've downloaded NFC parts from AOSP and I'm looking for the method used by Android to generate the random UID used by card emulation. My goal is to fix the UID instead of having a different one each time there is a communication with the target. I found inside "libnfc-nci" module the file "nfa_ce_act.c" containing this:
void nfa_ce_t3t_generate_rand_nfcid (UINT8 nfcid2[NCI_RF_F_UID_LEN])
{
UINT32 rand_seed = GKI_get_tick_count ();
/* For Type-3 tag, nfcid2 starts witn 02:fe */
nfcid2[0] = 0x02;
nfcid2[1] = 0xFE;
/* The remaining 6 bytes are random */
nfcid2[2] = (UINT8) (rand_seed & 0xFF);
nfcid2[3] = (UINT8) (rand_seed>>8 & 0xFF);
rand_seed>>=(rand_seed&3);
nfcid2[4] = (UINT8) (rand_seed & 0xFF);
nfcid2[5] = (UINT8) (rand_seed>>8 & 0xFF);
rand_seed>>=(rand_seed&3);
nfcid2[6] = (UINT8) (rand_seed & 0xFF);
nfcid2[7] = (UINT8) (rand_seed>>8 & 0xFF);
}
This method generate an UID for FeliCa tags. I'm not able to find the one for ISO14443 cards (MIFARE) which generate an UID beginning with 0x08 by default. According to Martijn Coenen, as explained in his G+ Post, it's something possible.
Sorry, I realize many people wanted this, but it's not possible in the official version. (You could of course do it with some AOSP hacking). The reason is that HCE is designed around background operation. If we allow apps to set the UID, every app possibly wants to set their own UID, and there's no way to resolve the conflict. We hope that with HCE, NFC infrastructure will move to higher levels of the protocol stack to do authentication instead of relying on the UID (which is easily cloned anyway).
https://plus.google.com/+MartijnCoenen/posts/iX6LLoQmZLZ
Is anyone know how to achieve it?
Thanks
One important thing to know is that the UID transfered at a very low level of the nfc protocol. This means that it is done independently by the nfc firmware and not within the android operating system.
We had the same problem in our NFCGate project and found a solution for Broadcom BCM20793 chips like the ones in the Nexus4/5 and others by writing the UID with NFC_SetConfig directly into the chip firmware.
You can see a working version in our repository on github. Here is a non-tested version to show the principle:
uint8_t cfg[] = {
CFG_TYPE_UID, // config type
3, // uid length
0x0A, // uid byte 1
0x0B, // uid byte 2
0x0C // uid byte 3
};
NFC_SetConfig(sizeof(cfg), cfg);
Our tests revealed that android sometimes sets the UID back to random (length=0 if I recall correctly), so you need to find a good place to set it when you need it or do something similar as we did and intercept NFC_SetConfig calls from android to re-set our own UID.

Android NfcV (ISO 15693) tag

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.

Categories

Resources