java smartcard problem // card provider configuration

552 Views Asked by At

I have a seemingly easy task, which is to read unencrypted data from a chip card with Java. I have no experience at all with smart cards and I'm hoping that someone can point me in the right direction.

I set up a project with the javax.smartcardio library and while that works like a charm with my credit card (card reader recognized, cart insert recognized, card connection established), it doesn't work with the card I'm trying to read.

The problem is that the card doesn't conform to smartcard standards (I believe), because I get an SCARD_E_NO_SMARTCARD error when I insert the card into the reader.

I do not have any documentation on how the data is actually stored on the card, but I would like to (if possible) just poke around a bit and figure it out. I also don't need to write to the card, just read the data stored on it.

I would like to create a CardTerminal implementation that allows me to just send arbitrary commands to the card instead of initiating a protocol.

This is what I have:

import java.util.List;
import javax.smartcardio.*;

public class SReader {

    public static int listCounted() {

        TerminalFactory factory = TerminalFactory.getDefault();

        try {
            List terminals = factory.terminals().list();
            CardTerminal ter = (CardTerminal)terminals.get(0);

            ter.waitForCardPresent(3000000);

            if(ter.isCardPresent())
            {
                System.out.println("Card present");

                // this causes the issue
                Card ca = ter.connect("*");
                System.out.println(ca);
            }

            System.out.println( ((CardTerminal)terminals.get(0)).isCardPresent());

            return terminals.size();

        } catch (CardException e) {
            e.printStackTrace();
        }
        return 0;
    }

    public static void main(String[] args) {
        listCounted();
    }
}

and this is the error message I get when I insert the card:

Card present
javax.smartcardio.CardNotPresentException: No card present
    at java.smartcardio/sun.security.smartcardio.TerminalImpl.connect(TerminalImpl.java:83)
    at Smaca/com.Smaca.SReader.listCounted(SReader.java:35)
    at Smaca/com.Smaca.SReader.main(SReader.java:58)
Caused by: sun.security.smartcardio.PCSCException: SCARD_E_NO_SMARTCARD
    at java.smartcardio/sun.security.smartcardio.PCSC.SCardConnect(Native Method)
    at java.smartcardio/sun.security.smartcardio.CardImpl.<init>(CardImpl.java:97)
    at java.smartcardio/sun.security.smartcardio.TerminalImpl.connect(TerminalImpl.java:79)
    ... 2 more

I guess I need to write a custom TerminalFactory implementation to be able to read the card? I have searched for days to find an example on how to do this but couldn't find anything useful. I'm also not sure if this approach is right for what I'm trying to achieve.

Any cross-platform solution that would allow me to do this (node.js, python, Java) would work.

Any help is greatly appreciated!

Thanks, Tom

1

There are 1 best solutions below

5
On

Your card is a synchronous I2C memory card (AT24C16). Unlike asynchronous cards your reader has to explicitly support it.

Have a look to your reader documentation and check if (and which) I2C memory cards are supported.

If your reader supports I2C cards then there should be described how to communicate with this particular card. Possible options usually are:

  • using special APDU commands -- this way is directly doable from java with javax.smartcardio

  • using extra reader API -- you would probably need to leave javax.smartcardio and use some vendor provided library (that is almost always native) and call it from java (e.g. with JNA)

If your reader does not support this card you will have to get another reader. For java prefer readers with APDU interface (see above).

EDIT>

For pseudo-APDUs, you need to use "direct" mode to connect to the reader (which means you want to communicate directly with the reader):

Card ca = ter.connect("direct");

Then pseudo-APDUs should work. Typical communication sequence for AT24C16 looks like this (see section 8.2 in "ACR39 Series – Reference Manual" for details):

  • SELECT_CARD_TYPE -- FF A4 00 00 01 02 (type 0x02 for 32, 64, 128, 256, 512, and 1024 kilobit I2C Card)

  • SELECT_PAGE_SIZE -- FF 01 00 00 01 (0x04 for 16 byte page)

  • then READ_MEMORY_CARD / WRITE_MEMORY_CARD as needed

Good luck with your project!