'How to read/write a MIFARE tag with Arduino at NFC?

I am developing an application for reading and writing data from MIFARE tags. I bought a device that can read and write MIFARE tag operations with NFC tech.

NFC Shield

I have been using a MIFARE ultralight tag but I encounter a problem when trying to authenticate a specific memory address. For this reason I can't start reading. Here is my Arduino code:

//This example reads a MIFARE memory block. It is tested with new MIFARE 1K cards.
//Uses default keys.
//Contributed by Seeed Technology Inc (www.seeedstudio.com)

#include <PN532.h>

#define SCK 52
#define MOSI 51
#define SS 10
#define MISO 50

PN532 nfc(SCK, MISO, MOSI, SS);

void setup(void) {
  Serial.begin(9600);
  Serial.println("Hello!");

  nfc.begin();

  uint32_t versiondata = nfc.getFirmwareVersion();
  if (! versiondata) {
    Serial.print("Didn't find PN53x board");
    while (1); // halt
  }
  // Got ok data, print it out!
  Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX); 
  Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); 
  Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC);
  Serial.print("Supports "); Serial.println(versiondata & 0xFF, HEX);
  
  // configure board to read RFID tags and cards
  nfc.SAMConfig();
}

void loop(void) {
  uint32_t id;
  // look for MiFare type cards
  id = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A);
  
  if (id != 0) {
    Serial.print("Read card #"); Serial.println(id);
    
    uint8_t keys[]= {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
    if(nfc.authenticateBlock(1, id ,0x08,KEY_A,keys)) { //authenticate block 0x08
      Serial.print("giris tmm #");
      //if authentication successful
      uint8_t block[16];
      //read memory block 0x08
      if(nfc.readMemoryBlock(1,0x08,block)) {
        Serial.print("Read tmm #");
        //if read operation is successful
        for(uint8_t i=0;i<16;i++) {
          //print memory block
          Serial.print(block[i],HEX);
          Serial.print(" ");
        }
        Serial.println();
      }
    }
  }
  
  delay(500);
}

This reading code was made for Arduino Mega 2560 and Seeedstudio NFC Shield v1.0 and MIFARE ultralight tags. Same problem encountered during the writing op too.

How can I solve this problem ?



Solution 1:[1]

I had the same issue and edited the Mifare Classic example to read out Mifare Ultralight cards instead. Here's my code: https://gist.github.com/SamDecrock/bd1ec55f083a71ecee95

Output should be something like this:

Looking for PN532...
Found chip PN532
Firmware ver. 1.6
Waiting for an ISO14443A Card ...
Found an ISO14443A card
  UID Length: 7 bytes
  UID Value: 4 13 74 72 83 1E 81 
Page 0   04 13 74 EB    ..t.
Page 1   72 83 1E 81    r...
Page 2   6E 48 00 00    nH..
Page 3   E1 11 06 00    ....
Page 4   00 00 00 00    ....
Page 5   00 00 00 00    ....
Page 6   00 00 00 00    ....
Page 7   00 00 00 00    ....
Page 8   00 00 00 00    ....
Page 9   00 00 00 00    ....
Page 10  00 00 00 00    ....
Page 11  00 00 00 00    ....
Page 12  00 00 00 00    ....
Page 13  00 00 00 00    ....
Page 14  00 00 00 00    ....
Page 15  00 00 00 00    ....


Send a character to run the mem dumper again!

As you can see, page 0 and page 1 contain the UID ;-)

Solution 2:[2]

MIFARE Ultralight is not the same as MIFARE Classic 1K. MIFARE Ultralight does not support (or need) authentication. You can just start reading without using authentication.

Solution 3:[3]

With PN532 library and NDEF library, you can read/write mifare classic tags and read mifare ultralight tags.

Solution 4:[4]

In wikipedia you can read

"The MIFARE Ultralight has only 512 bits of memory (i.e. 64 bytes), without cryptographic security. The memory is provided in 16 pages of 4 bytes."

So I think at least you must change the code removing the authenticateBlock and start reading blocks of 4 bytes long.

There is a document at adafruit.com where they explain how Mifare Classic and Mifare Ultralight work. There are some tips about the meaning of the bytes you read from Mifare Ultralight.

In the document they say about Mifare Ultralight:

Accessing Data Blocks

In order to access the cards, you must following two steps: 'Connect' to a Mifare Ultralight card and retrieve the 7 byte UID of the card. Memory can be read and written directly once a passive mode connection has been made. No authentication is required for Mifare Ultralight cards.

Read/Write Lengths

For compatability reasons, "Read" requests to a Mifare Ultralight card will retrieve 16 bytes (4 pages) at a time (which corresponds to block size of a Mifare Classic card). For example, if you specify that you want to read page 3, in reality pages 3, 4, 5 and 6 will be read and returned, and you can simply discard the last 12 bytes if they aren't needed. If you select a higher page, the 16 byte read will wrap over to page 0. For example, reading page 14 will actually return page 14, 15, 0 and 1.

"Write" requests occur in pages (4 bytes), so there is no problem with overwriting data on subsequent pages.

UPDATE!!

I have found adafruit have two NFC libraries for adruino (one using I2C and the other SPI) and both implement one method named:

// Mifare Ultralight functions
  uint8_t mifareultralight_ReadPage (uint8_t page, uint8_t * buffer);

Libraries are here: learn.adafruit.com/adafruit-pn532-rfid-nfc/arduino-library

I hope they are compatible with your shield.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 naugler
Solution 3 Yihui Xiong
Solution 4 M2sh