2
votes

I am writing a JavaCard 2.2.1 applet which do some heavy mathematical processing on the input data and return the result to computer. My code has many for and while loops. The problem is that when I call the card from the PC, the connection to the card not wait for the card to finish all process, and return with a PC/SC protocol error. I use PCSC library in C# for communicating to the card from PC, and get this error: A communication error with the smart card has been detected.

To reproduce the problem, I have prepared a test applet with some dummy calculations:

package my.testapplet;

import javacard.framework.*;

public class TestApplet extends Applet
{

    public static void install(byte[] bArray, short bOffset, byte bLength) 
    {
        new TestApplet().register(bArray, (short) (bOffset + 1), bArray[bOffset]);
    }

    public void process(APDU apdu)
    {
        if (selectingApplet())
        {
            return;
        }

        byte[] buf = apdu.getBuffer();
        short result = 0;
        if (buf[ISO7816.OFFSET_CLA] == ISO7816.CLA_ISO7816) {
            switch (buf[ISO7816.OFFSET_INS])
            {
            case (byte)0x00:
                {
                    short temp1 = 0;
                    short temp2, temp3 = 0;
                    while(temp1 < 30000) {
                        temp1++;
                        temp2 = 0;
                        while(temp2 < 30000) {
                            temp2++;
                            if(temp2 > 0) {
                                temp3 = (short)(temp1 * 2 + 1);
                            }
                        }
                    }
                    result = 100;
                }
                break;
            default:
                ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
            }

            buf[0] = (byte) (result & 0xff);
            buf[1] = (byte) (result >>> 8);

            apdu.setOutgoingAndSend((short) 0, (short) 2);
        } else {
            ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
        }
    }

}

I have tested this applet on 3 different java card models (from different vendors), all with the same result. Also I have to note that there is no problem when running the code in the java card simulator. The problem occurs on a real physical java card. It seems the virtual machine on the java card false detects some loops in running code as infinite loop, and breaks the connection.

I have no idea on this problem. Have any one similar experiences with java card? Any idea on why this behavior occurs on java card and how to resolve it? Is there any special instruction/configuration on java card to disable this behavior and wait for the java card to prepare and return the result?

1
Are these contactless Java Cards? Most newer Java Cards would correctly implement Waiting Time Extensions (WTX) but maybe your reader doesn't. - Maarten Bodewes
You can also request WTX yourself, see here. Possibly that may help, unless you're stuck in an API call (as it is hard to request additional time if your single thread it stuck out of your control). Sorry I forgot, also for contact... - Maarten Bodewes
@MaartenBodewes The cards support contactless, but I don't use them as contactless in development and tests. One of the cards is from Fudan Microelectronics. - M.Mahdipour
Have you tried another reader? Which operating system are you using and after how many seconds does the error occur? - Paul Bastian
@MaartenBodewes Using WTX resolved the problem. WTX was the answer. I used it inside my loop. But we should be careful using WTX, not use it for too long (I mean minutes!) processing. In my test, the card reader was locked and I cannot insert any card inside it anymore! (and don't know how to fix it! An omnikey reader) I tested it for at least 30 minutes!!! - M.Mahdipour

1 Answers

3
votes

WTX (waiting time extensions) are necessary to inform the reader that it will have to wait as no response is yet forthcoming, otherwise it will indeed time out and disconnect. WTX cannot be seen at APDU layer, as it operates on the lower level T=0, T=1 and T=CL protocol levels. It can be seen to have a similar role to the TLS heartbeat or other message to keep transport layers alive. The standard waiting time can be configured through the ATR, by the way.

Newer cards will generally be able to automatically handle WTX even if that functionality is not required to be implemented. Older cards generally only have WTX extensions enabled for specific API calls that may take longer than complete. Obviously, RSA key pair generation is the main offender here, but other operations such as Garbage Collection at the start up and installing Applets may also use WTX.

If you have a longer running method then you may have to issue WTX yourself at regular intervals. You want to issue WTX for relatively small periods to allow more fine grained control - if you can estimate the time it takes correctly. Preferably your protocol consists of fine grained APDU's as well, so that WTX is used as little as possible. As M. Mahdipour has found out, issuing WTX may lead to the card reader to wait about forever, so it is not entirely without risk (see the comments below the question).

Anyway, the method of making Java Card send the low level WTX message is the static APDU.waitExtension() method.