1

I wrote a program using java card that allows me to read some data from a smartcard. The file system of the card is structured as follows:

Smart Card File System

The smart card is a card of the Italian public administration.

I can correctly connect to the card, send the data reading command to the path MF/DF1/EF_Dati_Personali path by running this code.

When I try to enter the DF2/Dati_personali_aggiuntivi I can not find any data despite they are present.

According to the reference guide, to access the DF1 and DF2 areas, the sectors are as follows:

Data sectors

Below is the code I wrote. Code is commented at line to get data in order to identify problem.

Can someone kindly tell me where I'm wrong? Every suggestion is appreciated. thanks a lot

package smartcard;

import java.io.IOException;
import static java.lang.System.out;
import java.util.List;
import javax.smartcardio.ATR;
import javax.smartcardio.Card;
import javax.smartcardio.CardChannel;
import javax.smartcardio.CardException;
import javax.smartcardio.CardTerminal;
import javax.smartcardio.CommandAPDU;
import javax.smartcardio.ResponseAPDU;
import javax.smartcardio.TerminalFactory;
import javax.swing.JOptionPane;

public class SmartCard {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws CardException, IOException {
        try {
             TerminalFactory factory = TerminalFactory.getDefault();
            List<CardTerminal> terminals = factory.terminals().list();
            System.out.println("Terminals: " + terminals);

            // Use the first terminal
            CardTerminal terminal = terminals.get(0);

            // Connect wit hthe card
            Card card = terminal.connect("*");
            System.out.println("card: " + card);
            CardChannel channel = card.getBasicChannel();

            //GET ATR
            ATR atr = card.getATR();

            byte[] ATR = atr.getBytes();
            System.out.println("Card ATR: " + bytesToHex(ATR));
           //   // originale

            //GET SELECT_FILE_APDU
            byte[] READ_BINARY_APDU = {(byte) 0x00, (byte) 0xB0, (byte) 0x00, (byte) 0x00, (byte) 0xff}; 

            byte[] dati_personali = {(byte) 0x00, (byte) 0xA4, (byte) 0x08, (byte) 0x00, (byte) 0x04, (byte) 0x11, (byte) 0x00, (byte) 0x11, (byte) 0x02, (byte) 0x00};
            // Whit this String I can correctly read DF1 Data of CNS (Carta Nazionale servizi)

            // This should be the string for get DF2 data but I cannot find anything.
            byte[] dati_personali_aggiuntivi = {(byte) 0x00, (byte) 0xA4, (byte) 0x08, (byte) 0x00, (byte) 0x04, (byte) 0x12, (byte) 0x00, (byte) 0x12, (byte) 0x01, (byte) 0x00};

            String dati_personali_string = richiedi(channel, READ_BINARY_APDU, dati_personali, "<b>Dati personali:</b><br>");
            String dati_personali_aggiuntivi_string = richiedi(channel, READ_BINARY_APDU, dati_personali_aggiuntivi, "<b>Dati personali aggiuntivi:</b><br>");
            JOptionPane.showMessageDialog(null,"dati personali: "+ dati_personali_string, "Dati personali",JOptionPane.INFORMATION_MESSAGE);
            JOptionPane.showMessageDialog(null,"dati personali agiguntivi: "+ dati_personali_aggiuntivi_string, "Dati personali aggiuntivi",JOptionPane.INFORMATION_MESSAGE);


            // Disconnect the card
            card.disconnect(false);
            System.out.println("DISCONEESSO ");

        } catch (Exception e) {
            System.out.println("Ouch: " + e.toString());
        }

    }

    public static String richiedi(CardChannel channel, byte[] read, byte[] select, String titolo) throws CardException {
        out.println(titolo);
        // Send Select Applet command
        ResponseAPDU answer = channel.transmit(new CommandAPDU(select));
        // Send test command
        answer = channel.transmit(new CommandAPDU(read));
        byte r[] = answer.getData();
        String test = "";
        for (int i = 0; i < r.length; i++) {
            test += (char) r[i];
        }
        System.out.print(test);
        out.println(test);
        out.println("<br><br>");
        return test;
    }

    public static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder(bytes.length * 2);
        for (int i = 0; i < bytes.length; i++) {
            sb.append(String.format("%02x", bytes[i]));
        }
        return sb.toString();
    }
}

UPDATE APDU tracing

REQUEST: Dati personali:
read command: >>> 00b00000ff
select command: >>> 00a40800041100110200

RESPONSE: Dati personali:
<<< answer from CNS: 303030303733303436303330303830373039323031303038303730393230313630384954414c49414e4f3130414e544f4e494f20435249535449414e3038323230343139383230314d30303130544c4e4e4e43383244323246323035493030303446323035303030303034463230353030303000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009000

_____________________
REQUEST: Dati personali aggiuntivi:
read command: >>> 00b00000ff
select command: >>> 00a40800041200120100

RESPONSE: Dati personali aggiuntivi:
<<< answer from CNS: 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009000
  • *.. I can not find any data ...* is a bit vague. Which error code(s) do you get? – guidot Oct 18 '18 at 06:46
  • Please add APDU tracing around each transmit in the `richiedi()` method, e.g. `System.out.println(">>> " + bytesToHex(select));`...transmit(select)...`System.out.println("<<< " + bytesToHex(answer.getBytes()));`...`System.out.println(">>> " + bytesToHex(read));`...transmit(read)...`System.out.println("<<< " + bytesToHex(answer.getBytes()));` and update your question with this trace. – vlp Oct 18 '18 at 07:44
  • Hello, thank you for your answer. I added the APDU tracing around each transmit in the richiedi() method. First call is related to DF1 (dati personali), second one for DF2 (dati_personali_aggiuntivi). I've updated the question with these data. Thank you. – Gammone Gammone Oct 18 '18 at 09:37
  • @GammoneGammone Your trace shows that read was successful (card responds with status word '9000') and file contains 100 zero bytes... – vlp Oct 18 '18 at 09:47

1 Answers1

1

According to given trace your code works correctly and data from the card is successfully read -- elementary file 'DF2/Dati_personali_aggiuntivi' is filled with zeroes.

Which is in line with the documentation (section 4.3):

EF.Dati_personali_aggiuntivi – l’intero contenuto è posto a ‘00’hex

Translated using Google translate:

EF.Additional_personal_dates - the entire content is set to '00'hex

Some additional notes:

  • 'EF.Dati_personali' file contains 400 bytes -- you might need to use several 'READ BINARY' commands to get them all

  • Always check APDU response status ('90 00') -- ResponseAPDU.getSW() is useful for this

Good luck with your project!

EDIT> OpenSC supports CNS card (see here and here) you might want to give it a try

vlp
  • 7,811
  • 2
  • 23
  • 51
  • First of all, thanks for your answer. You're right, "the entire content is set to '00'hex" was my doubt. I tried to read the other bytes in "EF.Dati_personali" but I get a zero-string, as if there were no more data than what I read. I try to change question: with another software (I think written in delphi, but I do not think this is the problem) I get on my screen the information I need (that is Additional_personal_data). According to your experience and given the file system above, where could this data be? Any indication or intuition is welcome! Thank you – Gammone Gammone Oct 19 '18 at 13:58
  • @GammoneGammone I looked into the documentation briefly and did not find any clue (but I don't speak italian and have never worked with CNS card before). You can have a look what the other application does with the card using tools like [APDUPlay](http://fi.muni.cz/~xsvenda/apduinspect.html) or [WinSCard APDU View Utility](http://fernandes.org/apduview/index.html) (please check the legality of your actions). Maybe the other application communicates with some server to get additional information...good luck! – vlp Oct 19 '18 at 17:25