ritch
ritch

Reputation: 1808

Unable to retrieve the ATR of second card when using Smart Card IO

For some background, I have used the In_List_Passive_Target command specified in the PN532 user manual to retrieve the UID's of all the cards in the terminals field. I'm also using the pseudo command FF 00 00 00 04 for the ACR122U to send these commands to the PN532.

>>  FF 00 00 00 04 D4 4A 01 00           # In_List_Passive_Target (1)
<<  D5 4B 01 01 00 04 08 04 3E 58 A7 D1  # Response including UID (1)
>>  FF 00 00 00 04 D4 4A 01 00           # In_List_Passive_Target (2)
<<  D5 4B 01 01 00 04 08 04 9E 69 A7 D1  # Response including UID (2)
>>  FF 00 00 00 04 D4 4A 01 00           # In_List_Passive_Target (3)
<<  D5 4B 00                             # No more cards in field (3)

Now that I have done this, I want to select these one by one. I can do this by halting a card (In_Deselect) when I have finished with it and then selecting the next one by using In_List_Passive_Target command with it's UID.

However, every time I select a card, I want to know the ATR it returns. This is proving to be difficult with the Java Smart Card IO API, as the card object created by the terminal is always the same card (and consequently returns the same ATR), even if I disconnect the card and then create a new one. This is strange considering if I communicate with the card through the PN532 terminal command In_Data_Exchange, it is the correct different card (not the old one accessible through the Card object). I need the ATR to be able to detect which type of card it is (Mifare Classic, Desfire, Ultralight, etc.)

Here is the function I have created for collecting the cards:

public static void getCardsInField()
    {
        cardList = new ArrayList<AbstractCard>();
        Boolean loop = true;

        // Card already connected to the terminal
        byte[] firstCardUID = transmitADPUCommand(GET_ADDRESS);
        MifareClassic firstCard = new MifareClassic(cardChannel, firstCardUID);
        cardList.add(firstCard);

        System.out.println(firstCard);
        System.out.println(readable(card.getATR().getBytes()));

        while(loop)
        {
            byte[] inDeselectResponse = transmitADPUCommand(IN_DESELECT); // Deselect current card
            byte[] inListPassiveTargetsResponse = transmitADPUCommand(IN_LIST_PASSIVE_TARGETS); // Select a new card

            System.out.println(">>  " + readable(IN_LIST_PASSIVE_TARGETS));
            System.out.println("<<  " + readable(inListPassiveTargetsResponse));

            // Trying to create a new card object for new card
            try
            {
                card.disconnect(true);
                card = cardTerminal.connect("*");
                cardChannel = card.getBasicChannel();
            }
            catch (CardException e)
            {
                e.printStackTrace();
            }

            if (Arrays.equals(inListPassiveTargetsResponse, IN_LIST_PASSIVE_TARGET_RESPONSE_NO_TARGETS)) // no more targets
            {
                loop = false;
            }
            else
            {
                byte[] loopCardUID = extractUID(inListPassiveTargetsResponse);
                MifareClassic loopCard = new MifareClassic(cardChannel, loopCardUID);
                cardList.add(loopCard);

                System.out.println(loopCard);
                System.out.println(readable(card.getATR().getBytes())); // this should be different ATR but it is the old cards atr
            }
        }
    }

Upvotes: 0

Views: 1516

Answers (1)

Michael Roland
Michael Roland

Reputation: 40821

Contactless cards do not have an ATR (answer-to-reset). An ATR is only generated by contact cards (ISO/IEC 7816-3 in response to deasserting the reset pin). Moreover, PC/SC emulates an ATR for contactless cards (based on certain parameters of the card) as PC/SC was primarily designed for contact cards and, hence, the PC/SC API expects an ATR to be available.

Contactless cards have other values instead. For instance, a card based on ISO/IEC 14443 Type A has an ATQA (SENS_RES), SAK (SEL_RES), UID (NFCID1), and possibly an ATS (which comes close to what an ATR is). Contactless cards based on ISO/IEC 14443 Type B have similar values.

You get all the information that is necessary to identify the type of a card in response to the InListPassiveTarget command:

Card 1: D5 4B 01 01 00 04 08 04 3E 58 A7 D1
Card 2: D5 4B 01 01 00 04 08 04 9E 69 A7 D1

For card 1, this data decodes to:

  • ATQA (SENS_RES) = 00 04
  • SAK (SEL_RES) = 08
  • UID (NFCID1) = 3E 58 A7 D1
  • ATS = none

For card 2, this data decodes to:

  • ATQA (SENS_RES) = 00 04
  • SAK (SEL_RES) = 08
  • UID (NFCID1) = 9E 69 A7 D1
  • ATS = none

Hence, both cards have ATQA = 00 04 and SAK = 08, which means that they are most likely MIFARE Classic 1K or MIFARE Plus.

See MIFARE Type Identification Procedure for a comprehensive list of values to identify ISO/IEC 14443 Type A cards from NXP.

Upvotes: 1

Related Questions