Page 1 of 1

ERROR INFO: Transaction failed? Why?

Posted: Tue Aug 15, 2017 1:50 am
by Liguwu
I have a problem with my applet. When I sent the command 0x10 40 00 00 01 01 02, it's expected to get 9000. But in fact,I got " Transaction failed. " . And I tried to find the where caused this problem, but got nothing. Could anyone give me a pointeror a clue? Thanks a lot.

The whole code of my applet

Code: Select all

package monpackage;

import javacard.framework.APDU;
import javacard.framework.Applet;
import javacard.framework.ISO7816;
import javacard.framework.ISOException;
import javacard.framework.JCSystem;
import javacard.framework.Util;
import javacardx.apdu.ExtendedLength;

public class MonApplet extends Applet{

     private MonApplet() {
     }

     public final static byte CLA = (byte) 0x10;
     public final static byte INS_GET_ARRAY_SIZE = (byte) 0x80;
     public final static byte INS_GET_ARRAY_CONTENT = (byte) 0x20;
     public final static byte INS_CHECK_ARRAY_INTEGRITY = (byte) 0x40;
     
     public static byte[] array = null;
     
     
     public static void install(byte bArray[], short bOffset, byte bLength)
               throws ISOException {
          new MonApplet().register();
          short arraySize = 2048;
          boolean foundMaxSize = false;
          while (!foundMaxSize) {
               try {
                    array = JCSystem.makeTransientByteArray(arraySize, JCSystem.CLEAR_ON_RESET);
                    foundMaxSize = true;
               }
               catch(Exception e){
                    arraySize--;
               }
          }
     }

     public void process(APDU apdu) throws ISOException {
          byte[] buf = apdu.getBuffer();
          byte cla = buf[ISO7816.OFFSET_CLA];
          byte ins = buf[ISO7816.OFFSET_INS];
          short bytesLeft = (short) (buf[ISO7816.OFFSET_LC] & 0x00FF);
          short readCount = apdu.setIncomingAndReceive();
          while (bytesLeft > 0) {
               bytesLeft -= readCount;
               readCount = apdu.receiveBytes(ISO7816.OFFSET_CDATA);
          }
         
          if (selectingApplet()) return;
         
          if (cla != CLA) ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);

          short le = apdu.setOutgoing();
         
          switch (ins) {
          case INS_GET_ARRAY_SIZE:
               apdu.setOutgoingLength((short)2);
               Util.setShort(buf, ISO7816.OFFSET_CDATA, (short)array.length);
               apdu.sendBytes(ISO7816.OFFSET_CDATA, (short)2);
               break;
          case INS_GET_ARRAY_CONTENT:
               short dumpOffset = (short)((short)(buf[ISO7816.OFFSET_P1] & 0x00FF) * 256 + (short)(buf[ISO7816.OFFSET_P2] & 0x00FF));
               if (dumpOffset > array.length) {
                    ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
               }
               if ((short) (dumpOffset+le) >= array.length) {
                    le = (short) (array.length - dumpOffset);
               }
               apdu.setOutgoingLength(le);
               Util.arrayCopy(array, dumpOffset, buf, (short)0, le);
               apdu.sendBytes((short)0, le);
               break;
          case INS_CHECK_ARRAY_INTEGRITY:
               // array[(short)(array.length-1)] = (byte)1;
               for (short i=0; i<array.length; i++) {
                    if (array[i] != (byte)0) {
                         apdu.setOutgoingLength((short)2);
                         Util.setShort(buf, (short)0, i);
                         apdu.sendBytes((short)0, (short)2);
                    }
               }
               break;
          default:
               ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
          }     
     }
}

Re: ERROR INFO: Transaction failed? Why?

Posted: Tue Aug 15, 2017 4:53 am
by chico0609
Tips:
1. You shouldn't call apdu.setIncomingAndReceive() systematically, as it will process P3 as an incoming data length (Lc).
2. You are calling setOutgingLength() inside a loop, it will result in an APDUException with ILLEGAL_USE reason .

Re: ERROR INFO: Transaction failed? Why?

Posted: Tue Aug 15, 2017 5:22 am
by Liguwu
If I add the "else case", it works without any problem.

Code: Select all

if (array[i] != (byte)0) {
     apdu.setOutgoingLength((short)2);
     Util.setShort(buf, (short)0, i);
     apdu.sendBytes((short)0, (short)2);
}
else {
     apdu.setOutgoingLength((short)1);
     apdu.sendBytes((short)0, (short)1);
}

Re: ERROR INFO: Transaction failed? Why?

Posted: Tue Aug 15, 2017 5:22 am
by Liguwu
chico0609 wrote:Tips:
1. You shouldn't call apdu.setIncomingAndReceive() systematically, as it will process P3 an an incoming data length (Lc).
2. You are calling setOutgingLength() inside a loop, it will result in an APDUException with ILLEGAL_USE reason .


Thank you so much for your useful suggestion.