iyosch
Posts: 19
Joined: Tue Jun 09, 2015 6:40 am
Location: Jakarta, Indonesia

NFC ndef read write mifare classic tag PN532

Fri Jul 03, 2015 7:55 am

Hello, currently I am working on a project that uses PN532 nfc module from itead. I managed to use the module using I2C and libnfc following this tutorial : http://blog.iteadstudio.com/raspberry-p ... th-libnfc/

I can read the UID, ATQA, and SAK from my NFC tag. But I don't really know what ATQA and SAK means and how can I change the value of those things?

I also want to know how to read and write the ndef message on my nfc tag. How can I do that? Do libnfc capable of doing that?
I have done some research on this website http://www.libnfc.org/api/examples_page.html but I don't really understand all of them. I've tried every example program provided by the lib-nfc, the only one working is nfc-poll and quick_start_example1 and 2 which is actually doing the same thing as the nfc-poll.

Can anyone help?

Edit 2015-08-07 :
i have done searching all over the web so far this is what i have found useful
http://matt.bionicmessage.net/blog/2010 ... h%20course
it looks like this guy successfully authenticate the key to read the data block for NFC card but this guy is using different files/library not from libnfc
so i modified the quick_start_example1.c from libnfc (libnfc-1.7.1/examples/doc/quick_start_example1.c) and i make this new code

Code: Select all

/**
 * @file quick_start_example1.c
 * @brief Quick start example that presents how to use libnfc
 */
 
/**
 * this code is edited from quick_start_example1
 * this code doesnt work.
 */

// To compile this simple example:
// $ gcc -o quick_start_example1 quick_start_example1.c -lnfc

#include <stdlib.h>
#include <nfc/nfc.h> //located on libnfc-1.7.1/include/nfc/nfc.h
#include <string.h>
//#include <nfc/nfc-types.h> //located on libnfc-1.7.1/include/nfc/nfc-types.h
#include </home/pi/libnfc-1.7.1/utils/mifare.h>

static mifare_param mp; //addition
nfc_target_info nti; //declare nfc_target_info as nti for ease of use
nfc_device *pnd;



//declaring keys 6x8 = 48 bit
static uint8_t keys[] = {
        0xff,0xff,0xff,0xff,0xff,0xff,
        0xd3,0xf7,0xd3,0xf7,0xd3,0xf7,
        0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,
        0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,
        0x4d,0x3a,0x99,0xc3,0x51,0xdd,
        0x1a,0x98,0x2c,0x7e,0x45,0x9a,
        0xaa,0xbb,0xcc,0xdd,0xee,0xff,
        0x00,0x00,0x00,0x00,0x00,0x00
};


//function to authenticate
static bool
authenticate(int block, int keynum, bool keyB) {
        memcpy(mp.mpa.abtAuthUid,nti.nai.abtUid,4);
        memcpy(mp.mpa.abtKey, &keys[keynum], 6);
        
        bool res = nfc_initiator_mifare_cmd(pnd, (keyB ? MC_AUTH_B : MC_AUTH_A), block, &mp);
        if (res) {
                printf("Authentication succcessful on block %d\n",block);
        } else {
                printf("Authentication failed on block %d\n",block);
        }
        return res;
}


//function to readblock
void readblocks(int start, int end) {
        int block;
        for (block=start; block<(end+1); block++) {
                bool res = nfc_initiator_mifare_cmd(pnd, MC_READ, block, &mp);
                if (res) {
                        printf("Block %d data: ",block);
                        //print_hex(mp.mpd.abtData,16);
                } else {
                        printf("Reading block %d failed\n",block);
                }
        }
}


//function print_hex to show data on terminal
static void print_hex(const uint8_t *pbtData, const size_t szBytes)
{
  size_t  szPos;

  for (szPos = 0; szPos < szBytes; szPos++) {
    printf("%02x  ", pbtData[szPos]);
  }
  printf("\n");
}

//function main
int
main(int argc, const char *argv[])
{
  //nfc_device *pnd; //this initialization is moved to the top of the file
  nfc_target nt;
  
  // Allocate only a pointer to nfc_context
  nfc_context *context;

  // Initialize libnfc and set the nfc_context
  nfc_init(&context);
  if (context == NULL) {
    printf("Unable to init libnfc (malloc)\n");
    exit(EXIT_FAILURE);
  }

  // Display libnfc version
  const char *acLibnfcVersion = nfc_version();
  (void)argc;
  printf("%s uses libnfc %s\n", argv[0], acLibnfcVersion);

  // Open, using the first available NFC device which can be in order of selection:
  //   - default device specified using environment variable or
  //   - first specified device in libnfc.conf (/etc/nfc) or
  //   - first specified device in device-configuration directory (/etc/nfc/devices.d) or
  //   - first auto-detected (if feature is not disabled in libnfc.conf) device
  pnd = nfc_open(context, NULL);

  if (pnd == NULL) {
    printf("ERROR: %s\n", "Unable to open NFC device.");
    exit(EXIT_FAILURE);
  }
  // Set opened NFC device to initiator mode
  if (nfc_initiator_init(pnd) < 0) {
    nfc_perror(pnd, "nfc_initiator_init");
    exit(EXIT_FAILURE);
  }

  printf("NFC reader: %s opened\n", nfc_device_get_name(pnd));

  // Poll for a ISO14443A (MIFARE) tag
  const nfc_modulation nmMifare = {
    .nmt = NMT_ISO14443A,
    .nbr = NBR_106,
  };
  if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) > 0) {
    printf("The following (NFC) ISO14443A tag was found:\n");
    printf("    ATQA (SENS_RES): ");
    print_hex(nt.nti.nai.abtAtqa, 2);
    printf("       UID (NFCID%c): ", (nt.nti.nai.abtUid[0] == 0x08 ? '3' : '1'));
    print_hex(nt.nti.nai.abtUid, nt.nti.nai.szUidLen);
    printf("      SAK (SEL_RES): ");
    print_hex(&nt.nti.nai.btSak, 1);
    if (nt.nti.nai.szAtsLen) {
      printf("          ATS (ATR): ");
      print_hex(nt.nti.nai.abtAts, nt.nti.nai.szAtsLen);
    }
    
    //try to read blocks
        } else {
                goto DISCONNECT;
        }
        // Try to login to sector 0. Use the default key FFFF, for key A
        bool authenticated = authenticate(3,0,false);
        
        if (!authenticated) {
                goto DISCONNECT;
        }
        
        readblocks(0,3); //read block 0 untill 3 (4 blocks)
        
        DISCONNECT: 
        // Disconnect from NFC device
        nfc_disconnect(pnd);
        return EXIT_SUCCESS;
        
    
    //compare the UID from nt.nti.nai.abtUid with stored UID
    const uint8_t winner[] = { 0x9e, 0x74, 0x03, 0x0a};
        if (memcmp(nt.nti.nai.abtUid, winner, 4) == 0) {
            printf("UID matched\n");
        }
    //nt.nti.nai.abtUid
    //nt = nfc_target
    //nti = nfc_target info
    //nai =  nfc_iso14443a_info nai <- all this is set on nfc-types.h
    //abtUid = UID of the nfc tag
        
    //template of memcmp 
    //int memcmp(const void *str1, const void *str2, size_t n)
    
    //try to read the data block
    //template to read data block
    //uint8_t mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t * data);
    
    //print the ats
    printf("         Test ATS : ");
    print_hex(nt.nti.nai.abtAts, 254);
    
    //print dep info
    printf("         DEP abtNFCID3 : ");
    print_hex(nt.nti.ndi.abtNFCID3 , 11);    

    
  // Close NFC device
  nfc_close(pnd);
  // Release the context
  nfc_exit(context);
  exit(EXIT_SUCCESS);
}

this code can't be compiled, i don't know why. i use the command :

Code: Select all

gcc -o quick_start_example4 quick_start_example4.c -lnfc
but then i got into error

Code: Select all

/usr/bin/ld:cannot find -lnfc
collect2: ld returned 1 exit status
can anyone help?

Edit 2015-07-09
Turns out there is something wrong with the script i use to compile the code. I changed it with my script that has been successful to compile quick_start_example3.c and now the quick_start_example4.c doesn't show

Code: Select all

/usr/bin/ld:cannot find -lnfc
that error anymore. But changed into this

Code: Select all

/tmp/cc3wcb4X.o: In function `authenticate':
quick_start_example3.c:(.text+0xa0): undefined reference to `nfc_initiator_mifare_cmd'
/tmp/cc3wcb4X.o: In function `readblocks':
quick_start_example3.c:(.text+0x144): undefined reference to `nfc_initiator_mifare_cmd'
/tmp/cc3wcb4X.o: In function `main':
quick_start_example3.c:(.text+0x498): undefined reference to `nfc_disconnect'
collect2: ld returned 1 exit status
Edit 2015-08-05:
Turns out we can read mifare classic tag PN532 using libnfc-1.7.1
after setting up from http://blog.iteadstudio.com/raspberry-p ... th-libnfc/
we can create hex dump file using this :

Code: Select all

nfc-mfclassic r b dump.mfd
nfc-mfclassic r b dump.mfd
r means read, b means using key b, dump.mfd is a file created containing sectors, blocks, keys, and data stored on the card
we read the .mfd filetypes using command

Code: Select all

xxd dump.mfd
if the linux don't have xxd, install it using

Code: Select all

sudo apt-get install xxd
Now, how can we read ndef from nfc mifare classic just like we do on android smartphone easily?
Last edited by iyosch on Wed Aug 05, 2015 3:44 am, edited 1 time in total.

GartZen
Posts: 1
Joined: Fri Jul 31, 2015 11:20 am

Re: NFC ndef read write mifare classic tag PN532

Fri Jul 31, 2015 11:23 am

Hi,

First nfc_disconnect has been replaced by nfc_close.
About nfc_initiator_mifare_cmd, this function is available in the mifare.c, just compile wih mifare.c (see in utils folder of libnfc-1.7.1) should be enough.

iyosch
Posts: 19
Joined: Tue Jun 09, 2015 6:40 am
Location: Jakarta, Indonesia

Re: NFC ndef read write mifare classic tag PN532

Wed Aug 05, 2015 3:36 am

thank you for your reply. turns out we can use nfc-mfclassic provided by libnfc-1.7.1 to read the NFC mifare classic. I didn't see it untill now. We can type

Code: Select all

nfc-mfclassic r b dump.mfd
r means read, b means using key b, dump.mfd is a file created containing sectors, blocks, keys, and data stored on the card
read the .mfd filetypes using command

Code: Select all

xxd dump.mfd
I will update my post.

Is there any easier method to read and write ndef message NFC mifare classic 4k ?

engrkhawaja
Posts: 3
Joined: Mon Aug 24, 2015 10:03 pm

Re: NFC ndef read write mifare classic tag PN532

Mon Aug 24, 2015 10:08 pm

Hi,

I am working of similar sort of thing. The code following this tuotorial http://matt.bionicmessage.net/blog/2010 ... h%20course
is being compiled and build. It can read the tag ID as in nfc-poll and display the tag info. But it cannot authenticate the block sector.

I would appreciate if you could help me to solve this.

Also if you found solution to ndef read data then please also inform me about it.

Looking Forward

User avatar
topguy
Posts: 6491
Joined: Tue Oct 09, 2012 11:46 am
Location: Trondheim, Norway

Re: NFC ndef read write mifare classic tag PN532

Mon Aug 24, 2015 10:55 pm

engrkhawaja wrote: It can read the tag ID as in nfc-poll and display the tag info. But it cannot authenticate the block sector.

I would appreciate if you could help me to solve this.
Do you know the key(s) for the sector you are trying to read or are you guessing ? Is the card blank or has some other application written to it.

iyosch
Posts: 19
Joined: Tue Jun 09, 2015 6:40 am
Location: Jakarta, Indonesia

Re: NFC ndef read write mifare classic tag PN532

Mon Sep 07, 2015 9:47 am

i am guessing that you are not using a clean or new nfc card/tag. in that case you might try using mfoc
follow this : https://www.youtube.com/watch?v=BDO84uO ... ck%20keys"

source :
https://github.com/nfc-tools/mfoc
install using :
(on download directory)
git clone https://github.com/nfc-tools/mfoc
cd mfoc
autoreconf -vis
./configure
make
sudo make install
sudo ldconfig

then you can run
mfoc -h or place an nfc card then mfoc -P 500 -O keyFileDump.mfd

you will get a keydumpfile.mfd which contains the same key as the card. now you can use it along with
the program "nfc-mfclassic" from libnfc along with the keydumpfile.mfd that you get from mfoc. at the moment i am still searching on how to modify the keys and the value of each block data. hope that helps.

Return to “General discussion”