2

Below, you see a program that is written to return the EEPROM available memory on reception of any APDU command :

public class HelloWorld extends Applet {
    public static void install(byte[] bArray, short bOffset, byte bLength) {
        new helloWorld.HelloWorld().register(bArray, (short) (bOffset + 1),
                bArray[bOffset]);
    }

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

        getAvailableMem(apdu);

    }

    public void getAvailableMem(APDU apdu){
        byte[] buffer = apdu.getBuffer();
        short[] AvailableMem = {};

        UtilX.getAvailableMemoryInfo(AvailableMem, (short) 0,
                UtilX.MEMORY_TYPE_PERSISTENT);

        for(short i=0;i<(short)AvailableMem.length;i++){
            buffer[i]=(byte)AvailableMem[i];
        }

        apdu.setOutgoingAndSend((short)0, (short)(2*AvailableMem.length));
    }
}

But when I send an APDU command to the applet, it returns 0x6F00:

OSC: opensc-tool -s 00a4040006010203040506 -s 00000000
Using reader with a card: ACS CCID USB Reader 0

Sending: 00 A4 04 00 06 01 02 03 04 05 06
Received (SW1=0x90, SW2=0x00)

Sending: 00 00 00 00
Received (SW1=0x6F, SW2=0x00)

Note that I tried the above program with the below loop also :

for(byte i=0;i<(byte)AvailableMem.length;i++){
                buffer[i]=(byte)AvailableMem[i];
            }

It compiled successfully also! Shouldn't the compiler restrict the type of array indexes to byte only or short only? Why it accepts both types for indexes?

-This second program has the same output in OpenSCTool. What's wrong?

Jean
  • 687
  • 1
  • 9
  • 25

2 Answers2

2

You have to store the result into an existing array of non-zero length:

class MyApplet extends Applet {

short[] shorts = JCSystem.makeTransientShortArray((short)2, JCSystem.CLEAR_ON_RESET);

public void process(APDU apdu) {
    //...
    UtilX.getAvailableMemoryInfo(shorts, (short)0, UtilX.MEMORY_TYPE_PERSISTENT);
    //...
}

Your status code 6F00 is an uncaught instance of ArrayIndexOutOfBoundsException.

You can use both integer types as an index: byte or short, there is no real difference (for arrays not longer than 0x7F, of course).

vojta
  • 5,591
  • 2
  • 24
  • 64
  • Thanks. And what about the type of indexes variables? – Jean Mar 18 '15 at 11:21
  • @Jean I do not understand... Please, try to be more specific. – vojta Mar 18 '15 at 11:23
  • Is there any difference between creating a transient short class array (the `shorts` that you used in your answer) and initializing my short local array (that I named it `avalableMem`). In the other words what's the difference between your solution and my first program if I replace `short[] AvailableMem = {};` with `short[] AvailableMem = {(short)0x0000,(short)0x0000};`? Is there any difference in the way that JCRE allocate memory allocations for them - BTW, both returns **`01 00 ..`** and I don't understand what is the meaning of this value! – Jean Mar 18 '15 at 11:48
  • I found that I must replace the line `apdu.setOutgoingAndSend((short)0, (short)AvailableMem.length);` with `apdu.setOutgoingAndSend((short)0, (short)(2*AvailableMem.length));` (Beacause each short array members occupy two byte array member). And now the outout is `01 00 00 00`. What this mean!? The available memory is **`0x01000000`** bytes?! Surely no! what is wrong? – Jean Mar 18 '15 at 12:17
  • please don't mix shorts and bytes. Look at my post for a full example – Paul Bastian Mar 18 '15 at 17:26
  • Usually you would use `CLEAR_ON_DESELECT` for this kind of thing. – Maarten Bodewes Mar 18 '15 at 23:29
  • @PaulBastian Sorry for my late response. Thanks for your answer. I'll try it tomorrow. But what is wrong with my program(in the question)? – Jean Mar 28 '15 at 15:10
  • Transient memory only supports byte arrays on the cards i know of – Paul Bastian Mar 28 '15 at 16:09
0

Example code taken out of one of my applets:

Declarations in the beginning of my class

    short[] mem = new short[2];

From inside the process tree:

case Cmd.GET_FREE_MEM:
                UtilX.getAvailableMemoryInfo(mem, (short) 0, UtilX.MEMORY_TYPE_PERSISTENT);
                Util.setShort(apdu.getBuffer(), (short) 0, mem[0]);
                Util.setShort(apdu.getBuffer(), (short) 2, mem[1]);
                UtilX.getAvailableMemoryInfo(mem, (short) 0, UtilX.MEMORY_TYPE_TRANSIENT_RESET);
                Util.setShort(apdu.getBuffer(), (short) 4, mem[0]);
                Util.setShort(apdu.getBuffer(), (short) 6, mem[1]);
                apdu.setOutgoingAndSend((short) 0, (short) 8);
                break;
Paul Bastian
  • 2,597
  • 11
  • 26