Page 1 of 1

How to get object working over Shareable Interface

Posted: Mon Apr 29, 2019 4:51 am
by tay00000
We have the classical setup of two applets and a Shareable Interface used by both of them.

Shareable Inteface:

Code: Select all

package API;

import javacard.framework.Shareable;

public interface API extends Shareable {

    public void getArray(byte[] output, short off, short len);

}
Server Applet:

Code: Select all

package ShareableSampleApplet;

import javacard.framework.*;
import API.API;

public class ShareableSampleApplet extends Applet {

    public AID apiAID = new AID(
            new byte[]{
                (byte) 0x4B, (byte) 0x4D, (byte) 0x31, (byte) 0x30, (byte) 0x31, (byte) 0x00
            },
            (short) 0,
            (byte) 6);
    public API api = null;
    public byte[] b0 = JCSystem.makeTransientByteArray((short) 258, JCSystem.CLEAR_ON_RESET);
    public short[] sb = JCSystem.makeTransientShortArray((short) 1, JCSystem.CLEAR_ON_RESET);

    public static void install(byte[] bArray, short bOffset, byte bLength) {
        new ShareableSampleApplet();
    }

    protected ShareableSampleApplet() {
        register();
    }

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

        byte[] buffer = apdu.getBuffer();

        if ((buffer[ISO7816.OFFSET_CLA] == (byte) 0xB0) && (buffer[ISO7816.OFFSET_INS] == (byte) 0x00)) {
            if (api == null) {
                api = (API) JCSystem.getAppletShareableInterfaceObject(apiAID, (byte) 0);
            }
        } else if ((buffer[ISO7816.OFFSET_CLA] == (byte) 0xB0) && (buffer[ISO7816.OFFSET_INS] == (byte) 0x10)) {
            if (api != null) {
                try {
                    api.getArray(b0, (short) 0, (short) 5);
                    apdu.setOutgoing();
                    apdu.setOutgoingLength((short) 5);
                    apdu.sendBytesLong(b0, (short) 0, (short) 5);
                } catch (Exception e) {
                    if (e instanceof NullPointerException) {
                        ISOException.throwIt(Util.makeShort((byte) 0x6f, (byte) 0x21));
                    } else if (e instanceof SecurityException) {
                        ISOException.throwIt(Util.makeShort((byte) 0x6f, (byte) 0x22));
                    } else if (e instanceof ArrayIndexOutOfBoundsException) {
                        ISOException.throwIt(Util.makeShort((byte) 0x6f, (byte) 0x23));
                    } else if (e instanceof UserException) {
                        ISOException.throwIt(Util.makeShort((byte) 0x6f, (byte) 0x24));
                    } else if (e instanceof SystemException) {
                        ISOException.throwIt(Util.makeShort((byte) 0x6f, (byte) 0x25));
                    } else if (e instanceof CardRuntimeException) {
                        ISOException.throwIt(Util.makeShort((byte) 0x6f, (byte) 0x26));
                    } else if (e instanceof ClassCastException) {
                        ISOException.throwIt(Util.makeShort((byte) 0x6f, (byte) 0x27));
                    } else {
                        ISOException.throwIt(Util.makeShort((byte) 0x6f, (byte) 0x2F));
                    }
                }
            } else {
                ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
            }
        } else {
            ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
        }
    }
}
Client Code:

Code: Select all

package ShareableSampleClient;

import javacard.framework.*;
import API.API;

public class ShareableSampleClient extends Applet {

    public AID apiAID = new AID(
            new byte[]{
                (byte) 0x4B, (byte) 0x4D, (byte) 0x31, (byte) 0x30, (byte) 0x31, (byte) 0x00
            },
            (short) 0,
            (byte) 6);
    public API api = null;
    public byte[] b0 = JCSystem.makeTransientByteArray((short) 258, JCSystem.CLEAR_ON_RESET);
    public short[] sb = JCSystem.makeTransientShortArray((short) 1, JCSystem.CLEAR_ON_RESET);

    public static void install(byte[] bArray, short bOffset, byte bLength) {
        new ShareableSampleClient();
    }

    protected ShareableSampleClient() {
        register();
    }

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

        byte[] buffer = apdu.getBuffer();

        if ((buffer[ISO7816.OFFSET_CLA] == (byte) 0xB0) && (buffer[ISO7816.OFFSET_INS] == (byte) 0x00)) {
            if (api == null) {
                api = (API) JCSystem.getAppletShareableInterfaceObject(apiAID, (byte) 0);
            }
        } else if ((buffer[ISO7816.OFFSET_CLA] == (byte) 0xB0) && (buffer[ISO7816.OFFSET_INS] == (byte) 0x10)) {
            if (api != null) {
                try {
                    api.getArray(b0, (short) 0, (short) 5);
                    apdu.setOutgoing();
                    apdu.setOutgoingLength((short) 5);
                    apdu.sendBytesLong(b0, (short) 0, (short) 5);
                } catch (Exception e) {
                    if (e instanceof NullPointerException) {
                        ISOException.throwIt(Util.makeShort((byte) 0x6f, (byte) 0x21));
                    } else if (e instanceof SecurityException) {
                        ISOException.throwIt(Util.makeShort((byte) 0x6f, (byte) 0x22));
                    } else if (e instanceof ArrayIndexOutOfBoundsException) {
                        ISOException.throwIt(Util.makeShort((byte) 0x6f, (byte) 0x23));
                    } else if (e instanceof UserException) {
                        ISOException.throwIt(Util.makeShort((byte) 0x6f, (byte) 0x24));
                    } else if (e instanceof SystemException) {
                        ISOException.throwIt(Util.makeShort((byte) 0x6f, (byte) 0x25));
                    } else if (e instanceof CardRuntimeException) {
                        ISOException.throwIt(Util.makeShort((byte) 0x6f, (byte) 0x26));
                    } else if (e instanceof ClassCastException) {
                        ISOException.throwIt(Util.makeShort((byte) 0x6f, (byte) 0x27));
                    } else {
                        ISOException.throwIt(Util.makeShort((byte) 0x6f, (byte) 0x2F));
                    }
                }
            } else {
                ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
            }
        } else {
            ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
        }
    }
}
I tried the above demo codes on A40CR and the APDU results:

Code: Select all

>>> 00 A4 04 00 05 73 68 61 72 31
<<< 90 00
>>> B0 00 00 00 00
<<< 90 00
>>> B0 10 00 00 00
<<< 6F 22 (SecurityException)
Any ideas how to resolve the SecurityException ?

Re: How to get object working over Shareable Interface

Posted: Tue Apr 30, 2019 2:54 am
by tay00000
Solved by passing the output byte array using the APDU buffer.

Why does the APDU buffer work ? Because it is the default global byte array buffer that is allowed to cross between the applet firewall by the JCRE and thus is a natural candidate. APDU buffer also has the advantage of the JCRE automatically clearing it's memory to prevent "data leakages" during applet selects and APDU command handling since the APDU buffer might contain sensitive PIN or key material while being used to transport data between the applet firewall. The automated memory clearing feature done by the JCRE on the APDU buffer makes it a primary choice not just security wise to lessen data leakages but also as a simple way of communicating via Shareable and between firewalled applets.