in SmartCard, Work&Life

JavaCard free memory detect (how much memory left)

Problem / Requirement: You have a JavaCard and have full access to it, you want to know how much user space, or how much memory left for you to use?

Here is what I do,
Write a basic JavaCard applet in JCOP. The code snippet as below,
1, Declare the public variable to store the loop counter,
public static short counter = 0x0000;
in process function process(APDU apdu),
switch(buf[ISO7816.OFFSET_INS]){
case (byte) 0xb3:
counter=0; //put counter as 0
ReturnAvailableMem(); //call function to allocate the NVM memory in while loop
return;

2, ReturnAvailableMem() function as below:
public void ReturnAvailableMem() {
try {
while (true) {
byte[] dump = new byte[1000];
counter += 1;
}
} catch (Exception e) {
temparray[0] = (byte)((counter) & 0xff);
temparray[1] = (byte)((counter >> 8) & 0xff); //or you can use //Util.setShort(temparray, (short)0, counter);
ISOException.throwIt((short) (counter)); //4 bytes header?
}
}

3, JCSystem.getAvailableMemory, to get the available NFV memory if less than 0x7FFF.
case (byte) 0xb0:
counter = JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_PERSISTENT);
apdu.setOutgoing();
apdu.setOutgoingLength( (short)2 );
Util.setShort(buf,(short)(0),counter);
apdu.sendBytes((short)0 , (short)2);
break;

4, JCSystem.requestObjectDeletion(), to clear created array.
case (byte) 0xb1:
JCSystem.requestObjectDeletion();
break;

5, get the value of the first two bytes of array temparray stored the size information in 0xb3 command
case (byte)0xb2:
apdu.setOutgoing();
apdu.setOutgoingLength( (short)2 );
Util.arrayCopy(temparray,(short)(0),buf,(short)(0),(short)2);
apdu.sendBytes((short)0 , (short)2);
break;

The concept is to allocate NVM memory by create new array, size as 1,000 bytes, in the infinite loop, until the NVM memory was depleted, the program will through an Exception, to store the counter into the temparray[], and returned by Status Word. The testing on the real JavaCard as below,

> send 00A4040006617070616964
=> 00 A4 04 00 06 11 22 33 44 55 66 //select applet
(130 msec)
<= 90 00 Status: No Error

<<00 B0 00 00 02 //getAvailableMemory to get the available NVM memeory
>>7F FF 90 00

> send b0b2000000
=> B0 B2 00 00 00 //before allocate NVM memory read out the temparray[], first two bytes.
(184 msec)
<= 00 00 Status: No Error > //first two bytes as 00 00

=> B0 B3 00 00 00 // send b0b3000000 to deplete the NVM memory, took around 10 seconds to return error, here the SW didn’t return, so the only way to get the memory size is to read out the temparray[], first two bytes.
Error code: 45d (0x045D)
Error message: SCardTransmit(): 0x45d, The request could not be performed because of an I/O device error.
Command failed.

=> B0 B2 00 00 00 //send b0b2000000 here return 0050, means 0x50, available size calculation = 0x50 * (1000+4)/1024 + 3K = 81K
(95 msec)
<= 00 50

<<00 B0 00 00 02 //getAvailableMemory still got 0x020C bytes, less than 1000 bytes. >>02 0C 90 00

<<00 B1 00 00 00 //requestObjectDeletion, delete the unreferenced persistent object, can re-do the test again. >>90 00

<<00 B0 00 00 02 //getAvailableMemory to get the available NVM memeory
>>7F FF 90 00
——————————————————————————————————
A few points,
1, for available memory size calculation = 0x50 * (1000+4)/1024 + 3K = 81K, the available user memory is 0x50 * (1000+4) = 80320, here added 4 bytes to 1000 bytes, as array object has header, I put as 4 bytes for each array, plus the applet itself size around 3K, then the total memory size is 80320/1024 + 3 = 81K, this is estimated size, not accurate, but can give you an idea about how much memory available to user.

2, how many bytes for the header of the simple byte array?
http://www.ruimtools.com/doc.php?doc=jc_best this link says 8 bytes.
https://www.cardis.org/proceedings/cardis_2014/pdf/CARDIS2014_1.pdf, this link says 4 bytes.

3, JCSystem.requestObjectDeletion() can delete the unreferenced persistent object owned by the current applet, use this methods then there is no need to uninstall the applet to re-do the test.

4, JCSystem.getAvailableMemory(byte memoryType) can get the available memory, Javacard must be 2.2 or above, and getAvailableMemory’s return type is short and the max value of a positive short variables is 0x7FFF, any free space larger than this (32K), it still returns 0x7FFF.

5, GP GET DATA, tag ‘FF 21’ (ETSI 102.226) to get the Extended Card resource information, 82 tag may contain the free non volatile memory, but cards may not support this feature. <

Reference links:
http://javacardos.com/javacardforum/viewtopic.php?t=19
http://stackoverflow.com/questions/20090783/java-card-applet-size

Write a Comment

Comment

  1. This is a good reference. I sped it up by asking for 32K at a time and for each failure, I cut the request size in half until my request size is less than 100. This goes a lot faster.

    int index2 = 0;
    index = (short) 32000;
    while (index >= 100) {
    try {
    byte[] dump = new byte[index];
    index2 += index;
    }
    catch (Exception e) {
    index = (short) (index >> 2);
    }

    Of course, with the addition of Javacard 3 we get a direct request:
    JCSystem.getAvailableMemory(array, (short) 0, JCSystem.MEMORY_TYPE_PERSISTENT)