DF is lost after JCOP restart?

181 Views Asked by At

I am working on a small ticketing prototype. What I want to do is - if the top-level ADF is selected I want to return the AID of all the containing DFs and on first sight it works quite well.

I create the ADF, and 1 or 2 DFs. When the ADF is selected, the AIDs of those DFs are returned fine and I can add EFs (or DFs), ...

Now when I restart the whole thing (I am using JCOP btw.) I can still select the ADF but the AIDs from the DFs are not returned anymore, in fact I get a 6F00 "no precise diagnosis".

For my data structure - first you see the minimal constructor for the ADF, which has no parents

public DirectoryFile(byte[] aid) {
  super(aid);
  this.aid = aid;
  numApp = 1;
  created = true;
}

the second structure is the same but for a "usual" DirectoryFile with a parentDirectoryFile and an array (arrayFiles) of Elementary Files:

public DirectoryFile(byte[] aid, DirectoryFile parent) {
    super(aid, parent);
    for (byte i = 0; i < numberFiles; i++) {
      arrayFiles[i].setActive(false);
    }   
}

both inherit from the same File.class

public File (byte aid[]) {
    Util.arrayCopy(aid, (short) 0, this.aid, (short) 0, (short) 6); 
}

public File (byte[] aid, DirectoryFile parentFile) {
    this.parentFile = parentFile;
    Util.arrayCopy(aid, (short) 0, this.aid, (short) 0, (short) 6); 
}

This should be a very basic Filesystem and it does work as long as the card is connected to the terminal, but the information seems to be lost after restart of the program although I am not using transient arrays at all for this.

The return code is always "6F00 - no precise diagnosis" which leads to an unreferred byte[] or something like that, which I cannot find any except of the DF objects, that get instanciated when the new Object is created.

EDIT: just figured out it might be a more "general" problem and that is what I am doing wrong.

Now, if I take a "Hello World" like http://umer555.wordpress.com/2012/05/17/java-card-hello-world-applet/ and add some INS like I did here:

  public class HalloWeltApplet extends Applet {
    private static byte[] helloWorld = new byte[11];
    private static final byte HW_CLA = (byte)0x80;
    private static final byte HW_INS = (byte)0x00;
    private static final byte HW_INS1 = (byte)0x01;
    private static final byte HW_INS2 = (byte)0x02;


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

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

     byte[] buffer = apdu.getBuffer();
     byte CLA = (byte) (buffer[ISO7816.OFFSET_CLA] & 0xFF);
     byte INS = (byte) (buffer[ISO7816.OFFSET_INS] & 0xFF);

     if(CLA != HW_CLA) {
       ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
     }

     switch(INS) {
       case HW_INS:
         getHelloWorld(apdu);
         break;
       case HW_INS1:
         getHelloWorld1(apdu);
         break;
       case HW_INS2:
         getHelloWorld2(apdu);
         break;
       default:
         ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
      }

   }

   private void getHelloWorld( APDU apdu) {
     byte[] buffer = apdu.getBuffer();
     short length = (short) helloWorld.length;
     byte[] test =  {(byte)'H',(byte)'e',(byte)'l',(byte)'l',(byte)'o',(byte)' ',(byte)'W',(byte)'o',(byte)'r',(byte)'l',(byte)'d',};

     Util.arrayCopy(test, (short) 0, helloWorld, (short) 0, (short) test.length);

   }  
   private void getHelloWorld1( APDU apdu) {
     byte[] buffer = apdu.getBuffer();
     short length = (short) helloWorld.length;
     byte[] test =  {(byte)'H',(byte)'i',(byte)' ',(byte)'W',(byte)'o',(byte)'r',(byte)'l',(byte)'d'};

     Util.arrayCopy(test, (short) 0, helloWorld, (short) 0, (short) test.length);

   }
   private void getHelloWorld2( APDU apdu) {
     byte[] buffer = apdu.getBuffer();
     apdu.setOutgoing();
     apdu.setOutgoingLength((short) helloWorld.length);
     apdu.sendBytesLong(helloWorld, (short) 0, (short) helloWorld.length);
   }
 }

So this should in my eyes save 'Hello World' or 'Hi World' into helloWorld and with INS2 I can show which one is saved. But whenever I restart the program, helloWorld will be empty due to initiation, right? Could that be my problem after all, and if so, how can it be resolved?

1

There are 1 best solutions below

14
On

The problem is probably here:

super(aid);
this.aid = aid;

First you correctly copy the data, then you overwrite the field in File with the one you've used in the DirectoryFile constructor. If that is a transient buffer or worse, the JCRE owned APDU buffer, then your code will fail as JCRE owned objects should not be used through persistent references.

Note that AID's are Application Identifiers. They identify applications such as your Java Card applet. Normally files and non-application DF's (especially child DF's) are not identified or selected with an AID but with a file identifier or a (related) short file identifier. See ISO/IEC 7816-4 (any version I guess) for details.

Note that resets work in the JCOP simulator, but that all information is lost when you restart the process; data is not saved to disk and applets must be reloaded.