Think about NFC, probably, you imagine payment systems, door lock access controls, tags, IoT or many other devices. Interestingly, the NFC readers play the most important role in this technological environment.

Some readers have different capabilities depending in its configuration, or how they were programmed. The main function of a NFC reader, is exactly that, to read. But until now, I did not find an example about how those devices can detect and read more than one NFC card simultaneously.

The Myth

There is a NFC myth about reading two cards at the same time: could be inappropriate, difficult or impossible because this process depends on many different factors: induction, detuning, power draining or insufficient power and many other things.

I have been researching NFC for around one year, and until now, I could not see an example which challenges this myth. As usual, to be capable to do something like this, we should consider to learn as much as we can about the NFC reader that we will implement, and how it processes the cards, data and power under the hood.


I will use the PN532 board from Elechouse and its datasheet from NXP. I will implement the SPI configuration to read data connected with an Arduino. Adding that I will use this datasheet as reference throughout this post.



I implemented the core of Adafruit library. I created new methods implementing the original code as reference, and I added them in my Github repository. I will explain some of these methods through this post. To use my new methods, they have to be added to the original Adafruit files.

The process

Initially, I had to make sure that the PN532 was capable to initialize more than one card simultaneously:

Screen Shot 2018-07-18 at 12.50.40 PM

Analyzing the datasheet I noticed that in the section of InListPassiveTarget states that this device has support to initialize 2 targets as maximum at once. Cool! It is enough for a PoC. I did not start from scratch. I used the iso14443a_uid example from the Adafruit library.

The iso14443a_uid example applies the readPassiveTargetID as main function to read a target:

success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &uid[0], &uidLength);

Screen Shot 2018-07-18 at 2.43.15 PM

This library does not have support to initialize a second card at the same time:

pn532_packetbuffer[1] = 1; // max 1 cards at once (we can set this to 2 later)

So, it is essential to change the code to allow a second card but also to control the output/input as well. The reference in the output part is critical:

Screen Shot 2018-07-18 at 5.19.35 PM

Running the code without changes, this is the output data in the serial monitor:

Screen Shot 2018-07-18 at 5.25.30 PM

Reading: 0x0 0x0 0xFF 0xC 0xF4 0xD5 0x4B 0x1 0x1 0x0 0x4 0x8 0x4 0x28 0xC 0x34 0x25 0x41 0x0 0xAA

Byte    –    Description
[0..6]   –    Frame header and preamble: 0x0 0x0 0xFF 0xC 0xF4 0xD5 0x4B
[7]       –    Tags Found: 0x1
[8]       –    Tag Number: 0x1
[9..10] –    SENS_RES: 0x0 0x4
[11]     –    SEL_RES: 0x8
[12] .   –    NFCID Length: 0x4
[13..]   –    NFCID: 0x28 0xC 0x34 0x25

I adapted a second method to handle the output of two cards simultaneously:

Screen Shot 2018-07-18 at 6.32.58 PM

bool Adafruit_PN532::readPassiveTargetID2(uint8_t cardbaudrate, uint8_t * uid, uint8_t * uidLength, uint8_t * uid2, uint8_t * uidLength2, uint16_t timeout) {

pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET;
pn532_packetbuffer[1] = 2; // Let’s have fun
pn532_packetbuffer[2] = cardbaudrate;

This is the log when two cards are present in the coil range:


Reading: 0x0 0x0 0xFF 0x15 0xEB 0xD5 0x4B 0x2 0x1 0x0 0x4 0x8 0x4 0x28 0xC 0x34 0x25 0x2 0x0 0x4 0x8 0x4 0x21 0xC6 0x96 0x2E 0x83 0x0 0xAA

Byte      –    Description – First Card
[0..6]     –    Frame header and preamble: 0x0 0x0 0xFF 0xC 0xF4 0xD5 0x4B
[7]         –    Tags Found: 0x2
[8]         –    Tag Number: 0x1
[9..10]   –    SENS_RES: 0x0 0x4
[11]       –    SEL_RES: 0x8
[12]       –    NFCID Length: 0x4
[13..16] –    NFCID: 0x28 0xC 0x34 0x25

Byte      –    Description – Second Card
[17]       –    Tag Number: 0x2
[18..19] –    SENS_RES: 0x0 0x4
[20]       –    SEL_RES: 0x8
[21]       –    NFCID Length: 0x4
[22..25] –    NFCID: 0x21 0xC6 0x96 0x2E

With this idea, I modify all the required methods to read the two Mifare Classic cards in the same process; specifically,

  •  mifareclassic_AuthenticateBlock
  • mifareclassic_ReadDataBlock

Reading the block 0 from two different cards:

Screen Shot 2018-07-18 at 9.11.14 PM.png

or basically read all the blocks independently from each card that is already initialized:

Why this is important? Lately, many people is adapting 2FA(Two Factor Authentication) in the software side. But… What about if we start using 2FA in the hardware side as well. Two keys for physical authorization: one could be a physical card and a second could be a phone; just to mention an example. To access a building, start a car, or share an access privilege between two individuals.

Knowing that NFC is an exploitable technology, like any other. We should create and design new methods and methodologies to improve it. Some of them could be readers with constant internet access to validate authorized users, share keys securely or update a card every time someone used it.

What about if we implement developed protocols to give them a second use. For example the NFC payment systems, we could implement them as well to authorized users using the tokenization protocol.

I want to say thank you to Tpx company for its support and sponsorship! 🙂

Well, there are many ways to work with NFC, and I will continue researching about it! Stay tuned!