1

I'm trying to write some data into a NFC using the acr 122u card reader. So far, I'm able to do it. My problem is that I need to also make the NFC password protected. I can add the password using a phone app like nfctools, but I need this process to be automated in the future.

For this I am using python smartcard.System to connect and write to the NFC tag. My problem is that I can't find anywhere how to save a password into the tag.

from smartcard.System import readers
from smartcard.CardConnection import CardConnection
from smartcard.scard import SCARD_SHARE_DIRECT

reader = readers()[0]
print(reader)
connection = reader.createConnection()
connection.connect()
command = [0xFF, 0xD6, 0x00, 0x05, 0x04, 0x34, 0x03, 0x3d,0x91]
r, sw1, sw2 = connection.transmit(command)

This works for writing. I've tried this for authentication:

auth= [0xFF, 0x00, 0x00, 0x00, 0x07, 0xd4, 0x42, 0x1b, 0x01, 0x01, 0x01, 0x01]
r, sw1, sw2 = connection.transmit(auth)
print(r)
print(sw1)
print(sw2)

auth2= [0xFF, 0x86, 0x00, 0x00, 0x05, 0x01, 0x00, 0x04, 0x60, 0x00]
r, sw1, sw2 = connection.transmit(auth2)
print(r)
print(sw1)
print(sw2)

And this does not work. As far as I know, this would only authenticate me into the NFC and will not write the password into the NFC itself.

Any tips? Thanks

Edit: I'm using the API file in the acs website http://www.acs.com.hk/download-manual/419/API-ACR122U-2.04.pdf

  • 1
    Please specify the exact model of the Mifare Ultralight Tag as there are currently 3 different versions (https://www.nxp.com/products/rfid-nfc/mifare-hf/mifare-ultralight:MC_53452) each with different password/authentication models. The exact method for setting the password on each is defined in the datasheets shown in the URL I listed. – Andrew Oct 12 '22 at 09:04
  • @Andrew it turns out i was placing my phone on my wallet that had a mifare ultralight ev1 inside. The nfc i want to read/write is an Ntag213. I'll be cheking the datasheet for that too. – Paulo Barbosa Oct 12 '22 at 09:42
  • Ntag 21x series and the Ultralight EV1 use very similar methods of a PASSWORD and PAK stored at the correct block address and then changes to the correct configuration page block address to enable. An detailed example in Java at https://stackoverflow.com/a/22723250/2373819 which show the commands as the correct byte arrays but as you a using an acr122u you need to wrap them in the Pseudo ADPU to get the reader to transmit the correct command byte array – Andrew Oct 12 '22 at 09:48
  • @Andrew I'm using the direct transmit that the acs provides. But i cant get it write. I'm sending a simple command to read block 0x05 but i get "Card returned no valid response". The command I'm sending is [0xff, 0x00, 0x00, 0x00, 0x02, 0x30, 0x05]. I'm missong something. – Paulo Barbosa Oct 12 '22 at 11:21
  • Well, using the direct trasnmit was correct, but the command is not a command for the nfc but for the PN532 as stated in https://stackoverflow.com/a/25084763/15078755 – Paulo Barbosa Oct 12 '22 at 11:35
  • To make my commands work i need to add 0xd4 and 0x42 like this (updating the number of bytes to send). [0xff, 0x00, 0x00, 0x00, 0x04,0x4d,0x42, 0x30, 0x05]. – Paulo Barbosa Oct 12 '22 at 11:36

1 Answers1

1

With the help of @Andrew and some research I was able to find the solution.

I was using python smartcard to communicate from python to the acr122u like this:

from smartcard.System import readers
from smartcard.CardConnection import CardConnection
from smartcard.scard import SCARD_SHARE_DIRECT

reader = readers()[0]
connection = reader.createConnection()
connection.connect()

In order to write normal data to the tag, I was using the Update Binary Blocks from http://www.acs.com.hk/download-manual/419/API-ACR122U-2.04.pdf, like this:

command = [0xFF, 0xD6, 0x00, 0x05, 0x04, 0x34, 0x03, 0x3d,0x91]
r, sw1, sw2 = connection.transmit(command)
if (sw1,sw2) == (0x90,0x00):
    print("Correct command")
else:
    print("Error")

When it comes to setting a password for the tag, we need to use the Direct Transmit command from the ACS PDF. This command will send our payload to the PN532 chip inside the NFC reader. So, inside our payload we need to have a special command to tell the PN532 to send our command to the NFC tag, that special code is 0x4d,0x42.

Now we can use any command supported by the Ntag 213 present here https://www.nxp.com/docs/en/data-sheet/NTAG213_215_216.pdf we just need to follow this layout:

[0xff, 0x00, 0x00, 0x00, Number of bytes to send, Payload]

where payload is:

[0xd4,0x42, ntag command] for example a read is [0xd4,0x42,0x30, 0x29]

In total, our command to use in the direct transmit will look like this: [0xff, 0x00, 0x00, 0x00, 0x4, 0xd4,0x42,0x30, 0x29]

enter image description here

In order to complete the password process, we need to follow the steps described in NTAG212 Mifare Ultralight with Authentication like this:

def createPseudoAPDU(payload, nBytes):
    #nBytes+0x2 to add the 0xd4 and 0x42 two bytes
    return np.concatenate(([0xff, 0x00, 0x00, 0x00, nBytes+0x2,0xd4,0x42], payload), axis=0).tolist() 


setPwd = createPseudoAPDU([0xa2, 0x2b,0x32,0x30,0x32,0x32],0x06)
setPack = createPseudoAPDU([0xa2, 0x2c,0x00,0x00,0x00,0x00],0x06)

setAuthLimAndProt = createPseudoAPDU([0xa2, 0x2a,0x00,0x05,0x00,0x00],0x06)

setauth0 = createPseudoAPDU([0xa2, 0x29,0x04,0x00,0x00,0x00],0x06)

r, sw1, sw2 = connection.transmit(setPwd)
print(r)
print(sw1)
print(sw2)

r, sw1, sw2 = connection.transmit(setPack)
print(r)
print(sw1)
print(sw2)

r, sw1, sw2 = connection.transmit(setAuthLimAndProt)
print(r)
print(sw1)
print(sw2)

r, sw1, sw2 = connection.transmit(setauth0)
print(r)
print(sw1)
print(sw2)
  • 1
    Glad you were able to put it together, all the bits info where available on datasheets, stackoverflow. – Andrew Oct 12 '22 at 15:23