APDU LE byte

Hi,
it seems i do not understand the APDU. i want to send 4byte data and receive 2byte. So i sent:
80 01 00 00 04 10 20 30 40 02
The first 4byte are the header. LC is 4 for 4byte data (10 20 30 40) and then the LE byte follows with 02.
But on the card this does not work:
byte[] buffer = apdu.getBuffer();
short length = apdu.setIncomingAndReceive(); // length = 4, thats right
short expectedOutput = apdu.setOutgoing(); // expectedOutput = 256, why ???Iam not able to receive the LE byte. But in the ISO7816 this case (LC and LE not null) is one of the four cases which has to work with every card. Whats my fault ? :(

I guess your card is using the T=0 protocol.
Doc for setOutgoing states: "In T=0 (Case 4S) protocol, this method will return 256 with normal semantics."
So everything is working as designed (I'm not saying: at is should have been designed).
There is no problem if you know the expected length of the answer (that is the integer Ne, coded by Le) from the spec of the APDU and its input parameters excluding Le, and 0<Ne<256. In that case just set that Nr=Ne using setOutgoingLength and send Nr data bytes with sendBytes. The card will tell Nr to the reader (as part of a conventional status word), some glue code in the bowels of the Java runtime library or application should issue a Get Response command, and everything will be fine. This might work with Ne=256, coded by Le=00h, but do not bet on that without trying.
There is no problem either if you are happy with the default behavior of truncating the Nr bytes of outgoing data to Ne coded by Le. Just do as above as if you knew Ne was the maximum it could be, and everything will be fine.
If your in-card applet really needs (rather than know or assume) Ne, one option is to instead change the spec of the APDU and move Ne to P1,P2, or some of the ingoing data where you can get it.
Else, well... I'd rather not dive into these messy details if the previous three simple options apply.

Similar Messages

  • Proprietary APDU CLA byte

    Hi,
    If I am creating proprietary APDU for the JavaCard applet. I think the CLA byte should be 0x80, because the 4 top most bits must be 1000 according to ISO/IEC 7816
    and if I will not use the secure messaging and logical channels, the lower 4 bits must be 0000, which is 10000000 = 0x80.
    Am I right?
    Regards,
    STeN

    Hello,
    thanks for the reply - sure I must avoid the possible collision with the Global Platform!
    Other question - I think - but I am not sure about this - if the smart card manufacturer supports some extra proprietary APDUs (e.g. enumerating installed JavaCard applets, getting the free EEPROM space) by the smart card OS (i.e. Sm@rtCafe), I should also check those commands, to avoid possible collision, because I think those commands will be handled with higher priority then applet specific APDUs (by this I mean, that if I will send the APDU and OS detect that this is a command it supports, it will handle it and the APDU will nto be sent to the currently selected JavaCard applet)?
    Thanks a lot for the reply and help
    Regards,
    STeN

  • How can I read Extended APDU input to the same buffer

    The following is the code I am currently using where inBuffer is an intermediate array of 1000 length. However, I do not want to allocate any buffers at all, and just want to send a command apdu of 1000 byte length and modify it in the code and return the modified buf in the response APDU.
    // Read extended APDU input
    byte[] buf = apdu.getBuffer();
    short bytesRead = apdu.setIncomingAndReceive();
    short dataOffset = apdu.getOffsetCdata();
    // store first chunk in our intermediate byte array <-- how do i get rid of the intermediate array
    Util.arrayCopyNonAtomic(buf, dataOffset, inBuffer, (short) 0, bytesRead);
    // what is the overall length?
    short overallLength = apdu.getIncomingLength();
    short messageOffset = bytesRead;
    if (bytesRead != overallLength){ // otherwise we're finished, all bytes received
         short received = 0;
         do{
                   received = apdu.receiveBytes((short)0);
                   Util.arrayCopyNonAtomic(buf, (short)0, inBuffer, messageOffset, received);
                   messageOffset  += received;
              } while(received != 0);
    * REST OF CODE IN PROCESS METHOD
    I have also tried replacing the above code with the following
    short bytesLeft = (short) (buffer[ISO7816.OFFSET_LC] & 0x00FF);
    if (bytesLeft < (short)55) ISOException.throwIt( ISO7816.SW_WRONG_LENGTH );
    short readCount = apdu.setIncomingAndReceive();
    while ( bytesLeft > 0){
      // process bytes in buffer[5] to buffer[readCount+4];
      bytesLeft -= readCount;
      readCount = apdu.receiveBytes ( ISO7816.OFFSET_CDATA );
    as shown in the javadocs API, but it does not compile.
    This is my command APDU:
    /send 800100000003E8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003E8
    As you can see:
    CLA - 80
    INS - 01
    P1 & P2 - 00
    LC - 0003E8
    Data - 1000 0s
    LE - 03E8
    I am using JavaCard 3.0 with JCOP in Eclipse. How can I read the extended length apdu to the same buffer? I have no problem in returning an extended length response APDU. Thanks a lot for the help.

    You should not call the convenience method setIncomingAndReceive() in your first code. Please find out about the different APDU states. Furthermore, your Applet should implement the ExtendedLength tagging interface.

  • Problem in APDU-case 1:No command,no response

    Hello evrybody.I have done a method in my java card applet which does not return any command data neither response data.
    I wrote in my APDU script the following(as defined the case 1 in the Zhiqun Chen's book-page 102,says that "P3(the 5th field in the APDU buffer) has to be 0"):
    //CLA INS P1 P2 P3
    0xB1 0x50 0x00 0x00 0x00;
    Howevr, the executed APDU script returns me the following:
    com.sun.javacard.apdutool.ReaderWriterError: Encountered ";" at line 105, column
    25.
    Was expecting one of: <INTEGER_LITERAL> ...
    <CHARACTER_LITERAL> ...
    <STRING_LITERAL> ...
    I have tried to add another 0x00 byte at the end of the above script line, as follwoing:
    //CLA INS P1 P2 Lc Le
    0xB1 0x50 0x00 0x00 0x00 0x00;
    //WIth the idea that Lc=0(no command data) and Le=0(no response data)
    I noticed that the method is working properly(does the work that has to do;I tested and I am definetely sure) but on the other hand the executed APDU script returns as SW1 SW2 the following:
    CLA: b1, INS: 50, P1: 00, P2: 00, Lc: 00, Le: 00, SW1: 6f, SW2: 00 (!!!!)
    Actually,I was waiting for SW1 SW2 == 90 00.
    I do not know why this is returned.
    Do you know what it is going wrong?
    I will appreciate any help and guidance.
    Thank you for you time.

    I will give the code of my function.I think the problem is in the code of this method(function).I will give you in order to have a look at it:
    private void delete_all_records(APDU apdu)
         ver_pin();
         byte[] buffer=apdu.getBuffer();
         byte get_P1=buffer[ISO7816.OFFSET_P1];
         byte P3=buffer[ISO7816.OFFSET_LC];
         //Check the appropriate syntax
         if (get_P1!=(byte)0) // || (P3!=(byte)0) )
         ISOException.throwIt (SW_SYNTAX_DEL_ERROR);
    // else
         //Delete all the record.This for loop
         //deletes all the records' ids.
         for (short i=0;i<kostas.length;i++)
         kostas[(short)i].record_id=(byte)0;
    I did not use any of the functions such as sendBytes() or apdu.setIncomingAndReceive because I did not want to take data either to return response data.Do you have any idea what's going on?
    I will really apprecitae any help.Thank you for your time.

  • How to store multiple bytes

    Ok, the problem I am currently having that gives me a 6f00 (unknown) error is due to the way I am reading in data and storing it in my loop. My code is as follows:
    byte[] buffer = apdu.getBuffer();
    byte numBytes = buffer[ISO7816.OFFSET_LC];     
    byte byteRead = (byte)(apdu.setIncomingAndReceive());
    if (numBytes != byteRead){
    ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    byte ind = ISO7816.OFFSET_CDATA;
    for (short index=0x0000; index <numBytes; index=+0x0001)
    first[(short)index] = buffer[(short)(ind)];
         ind = ind ++;
    What I am trying to do is to store the bytes of data from the script file into my first array. I have tried many different variations on this. I know that this is where I'm getting errors because it works if I only use one byte. If anyone knows what could be causing my problem, I'd appreciate your help. Thank you.

    Use the Util.arrayCopy(....) instead of looping like that

  • Problem with select APDU

    Hi all
    I have a problem when trying to test an applet created by me like Sebastian Lorquet proposed in this post:
    Re: Ask Global Platform SecureChannel
    I managed to install my applet on the card, and when I check the applets it contains I can see that the AID of mine appears.
    But when I use it and send APDUs through it, the SELECT command fails me.
    The SELECT APDU instruction is:
    Command -> 00A404000B0102030405060708090000
    where 01 02 03 04 05 06 07 08 09 00 00 is the AID of my applet
    The response is as follows:
    Response <- 6D00 (Invalid instruction byte / Command not supported or invalid)
    Do not understand why I get that answer.
    I am using gpshell, and the command used is:
    select -AID 0102030405060708090000
    Thanks in advance
    Edited by: bra_racing on 05-jul-2012 15:28

    ah ok. Just answer me one thing, are you using below code ?
    package test;
    import javacard.framework.APDU;
    import javacard.framework.Applet;
    import javacard.framework.ISO7816;
    import javacard.framework.ISOException;
    import org.globalplatform.GPSystem;
    import org.globalplatform.SecureChannel;
    * @author shane
    public class TestSecureChannel extends Applet {
        private final static byte INS_INIT_UPDATE = 0x50;
        private final static byte INS_EXT_AUTH = (byte) 0x82;
        private TestSecureChannel() {
            // empty
        public static void install(byte bArray[], short bOffset, byte bLength) throws ISOException {
            new TestSecureChannel().register();
        public void process(APDU apdu) throws ISOException {
            if (selectingApplet()) {
                return;
            byte[] buffer = apdu.getBuffer();
            byte cla = buffer[ISO7816.OFFSET_CLA];
            byte ins = buffer[ISO7816.OFFSET_INS];
            SecureChannel sc = GPSystem.getSecureChannel();
            if ((byte) (cla & 0x80) == 0x80) {
                switch (ins) {
                    case INS_INIT_UPDATE:
                    case INS_EXT_AUTH:
                        apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA, sc.processSecurity(apdu));
                        return;
                    default:
                        // fall through
            switch (ins) {
                case (byte) 0x01:
                    buffer[0] = sc.getSecurityLevel();
                    apdu.setOutgoingAndSend((short) 0, (short) 1);
                    break;
                default:
                    ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
    }If not above one then copy past your code here. For time being for what I understand it that to send get data command your currently selected application should be card manager.
    Edited by: Umer on Jul 10, 2012 4:34 PM

  • Detect SELECT APDU

    Hi everyone
    I'm writing an applet (Java Card 2.1.1) and in the process method I'm trying to detect the SELECT APDU command, but it's not working. I send a SELECT APDU to my applet, it throws a SW_CLA_NOT_SUPPORTED exception, and it is selected. Ok, the command ends up doing what it is supposed to do, but my applet throws an exception, and it shouldn't.
    Here's my code:
    public void process(APDU apdu) throws ISOException {
      byte[] buffer = apdu.getBuffer();
      byte cla  = buffer[ISO7816.OFFSET_CLA];
      byte ins = buffer[ISO7816.OFFSET_INS];
      if (cla == CLA_FUNCIONARIO) {
          try {
              switch (ins) {
                  // all my cases
                  default:
                      ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
          catch (UserException e) {
              ISOException.throwIt(e.getReason());
      else if (selectingApplet()) {
          return;
      else {
          byte tamanho_lido = (byte) apdu.setIncomingAndReceive();
          apdu.setOutgoing();
          apdu.setOutgoingLength((short) (tamanho_lido + 4));
          apdu.sendBytes((short) 0, (short) 4);
          apdu.sendBytes(ISO7816.OFFSET_CDATA, tamanho_lido);
          ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
    }First of all, I don't know what exactly does the method selectingApplet - in several source codes I've seen around, the verification for the SELECT APDU is done like this:
    (cla == ISO7816.CLA_ISO7816 && ins == ISO7816.INS_SELECT)But, there are some sample codes (like the JavaPurse on JCDK 2.1.1) that prove these two ways of checking the SELECT APDU is not equivalent. So, what's the difference between using the selectingApplet method and using the constants on the ISO7816 interface? Should I use both ways? Only one of them???
    The big problem is what is actually happening to my card. As it can be seen in the code above, if the applet is about to throw an SW_CLA_NOT_SUPPORTED exception, it writes the whole command that it received, so I can see what got there (sort of a System.out.println debugging). And here's what happens: everytime I send the command 0x00 0xA4 0x04 0x00 0x06 0x01 0x02 0x03 0x04 0x05 0x06 0x00, it returns 0x00 0xC0 0x00 0x00 as the response data and 0x6E00 as the status word!!! I googled and I found that C0 is the INS byte of the GET RESPONSE command. What is this command? It's not documented on the GlobalPlatform 2.0.1' specification. And why the hell my applet says it received this command when I send it a SELECT APDU?
    Any answer would be valuable :)
    Thanks!

    You are in the ISO7816 T=0 protocol. The 00CO000000 command is issued to receive the response to the previous SELECT command. You are not returning any data to the SELECT command, but the terminal side seems to insist on getting one.
    The GetResponse command should not be passed to the Applet by your card operating system, I consider this a bug.
    If you return data when selectingApplet() returns true, then you probably will not have any problem.

  • Clearing byte array field

    Hello all,
    I've encountered a problem in trying to reset fields in my applets which I just can't figure out, I'd appreciate some help with it.
    Basically I have a method in a base class for my applets which sets the fields in my card. This works fine, the problem I have is when I tried to alter this method so that if the command APDU received does not contain the data field(i.e. a Case 2 APDU, 5 bytes long), then the designated byte array is set to null. The code is shown below.
    // Method in applet
    public void setSurname(APDU apdu) {
    surname = setByteArrayVariable(apdu);
    // Method in applets' base class
    public byte[] setByteArrayVariable(APDU apdu) {
    byte[] apduBuffer = apdu.getBuffer();
    short len = apduBuffer[ISO7816.OFFSET_LC];
    byte[] arrayname = null;
    if(len != (short)0){
    arrayname = new byte[len];
    // copy buffer data into byte[]
    short bytesRead = apdu.setIncomingAndReceive();
    short Offset = (short)0;
    while (bytesRead > 0) {
    Util.arrayCopy(apduBuffer, ISO7816.OFFSET_CDATA, arrayname, Offset, bytesRead);
    Offset += bytesRead;
    bytesRead = apdu.receiveBytes(ISO7816.OFFSET_CDATA);
    return arrayname;
    What happens when I send the Case 2 APDU to the applet is that the CLA and INS bytes direct the apdu to the proper method to set the field and the byte array is set to null(success). At this point I expect the JCRE to return the sw 9000, however what actually happens is the applet throws the ISOException defined in the default case of the process method. Also I checked this method in the gemplus simulator and it works as expected, its only when I tried it in a GXP211_PK_IS card that the problem occurred, I've asked the Gemplus support about this but as yet have not heard anything in response. I cannot explain why this is happening, has anybody got any suggestions? Thanks,
    Tony

    The status word which is returned is 6D00(INS not supported), as this is what I throw in the process method when the switch doesn't match the INS byte with any of the cases. This is where my confusion comes from, if the method is called(through matching the CLA and INS bytes) how is it that after the method is completed(successfully, as the field is set to null) that the exception is thrown form the process method as if the method wasn't found? I have a workaround whereby instead of throwing the 6D00 I throw the ISO7816.SW_NO_ERROR in the default case of my process method, this can only be a temporary workaround though!!
    I'm guessing that you check for surname != null later on ? I do check this but only when I'm trying to retrieve the surname from the card, basically, if(surname == null)ISOException.throwIt(ISO7816.SW_FILE_NOT_FOUND);
    Doesn't sound like thats what you're getting at though??
    (Will sort out the memory allocation, cheers.)
    TIA for any help you can provide, leaving now for the day but hoping to hear from you tomorrow :)
    Tony

  • Apdu command length

    Hi
    I want to get the length of the entire command in my applet.
    I want to know "5" for the following example.
    /send 8084000000
    Is there such API?

    a command parser in process method can be something like that:
    byte MY_CLA = (byte)0x80;
    byte MY_INS = (byte)0x84;
    // get the APDU buffer bytes (get header first)
    byte[] apduBuffer = apdu.getBuffer();
    // Checking CLA values
    switch(apduBuffer[ISO7816.OFFSET_CLA]){
      case MY_CLA:
        // For a given CLA value, checking INS values
        switch(apduBuffer[ISO7816.OFFSET_INS]){
          case MY_INS:
            // For a given INS value, checking P1, P2, P3 for example:
            if((apduBuffer[ISO7816.OFFSET_P1] != (byte)0x00) || (apduBuffer[ISO7816.OFFSET_P2] != (byte)0x00))
               ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
            if(apduBuffer[ISO7816.OFFSET_LC] != (byte)0x08)
               ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
            // After the command format checking, i can continue the processing that my command is supposed to do
          break;
          default:
            // Throw iso exception: bad instruction byte value
            ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
          break;
      break;
      default:
        // Throw iso exception: bad class byte value
        ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
      break;
    }This example is for a case 3 apdu command.
    If your command is a case 2, you will need to get Le by invoking setOutgoing() method and checking the expected value of Le.
    Thomas
    http://jaccal.sourceforge.net/

  • APDU Commands - How they work ?

    Hi,
    Iam all new to the JavaCard programming and wanted to understand some basics. The APDU Commands (CLA, INS, P1, P2, ...) are they reserved commands (as in reserved words). If so, how do I get a listing of the same.
    Eg. I am looking into one of the programs which have the following few lines,
    SetLength(DataToSend, 13);
    DataToSend[0] := $88;
    DataToSend[1] := $10;
    DataToSend[2] := $11;
    DataToSend[3] := $00;
    DataToSend[4] := $08;
    DataToSend[5] := $F9;
    DataToSend[6] := $FD;
    DataToSend[7] := $CE;
    DataToSend[8] := $8B;
    DataToSend[9] := $F6;
    DataToSend[10] := $F4;
    DataToSend[11] := $14;
    DataToSend[12] := $E0;
    FSCard.SendCustomAPDU(DataToSend, ReceiveBuffer);
    I believe the above writes info. to the card.
    If Yes, how do I retrive the same from Card?
    If No, then what does the instruction stand for?
    Appreciate your help ....

    hI,
    Iam trying to write a sample code by trying to write data to card using XOR, converting the same back in the applet to the original string and retriving the same. The return value is still in XOR value and not the original i sent. Please let me know what iam doing wrong here?
    WRITING DATA:
    CLIENT PROGRAM:
    SetLength(DataToSend, 9);
    DataToSend[0] := $88;
    DataToSend[1] := $10;
    DataToSend[2] := $9A;
    DataToSend[3] := $00;
    DataToSend[4] := $4;
    DataToSend[5] := $A;
    DataToSend[6] := $B;
    DataToSend[7] := $C;
    DataToSend[8] := $D;
    DataToSend[5] := DataToSend[5] XOR DataToSend[6];
    DataToSend[6] := DataToSend[6] XOR DataToSend[7];
    DataToSend[7] := DataToSend[7] XOR DataToSend[8];
    DataToSend[8] := DataToSend[8] XOR DataToSend[5];
    FSCard.SendCustomAPDU(DataToSend, ReceiveBuffer);
    APPLET CALLS THIS PROCEDURE :
    private void SetStringSec5(APDU apdu) {
              byte buffer[] = apdu.getBuffer();
              byte size = (byte)(apdu.setIncomingAndReceive());
              byte index;
    byte indexsn;
    indexsn=0;
              // Store the length of the string and the string itself
              TheBuffer[80] = size;
              for (index = 80; index < (byte)(81+(int)(size)); index++){
                   TheBuffer[(byte)(index + 1)] = buffer[(byte)(ISO7816.OFFSET_CDATA + indexsn)];
    indexsn++;
              CalcSri();
    apdu.setOutgoing();
              apdu.setOutgoingLength((short)size);
    apdu.sendBytesLong(TheBuffer,(short)0,(short)size);
              return;
    private void CalcSri() {
              TheBuffer[(byte)(8)]=(byte)(((int)(TheBuffer[(byte)(5)])) ^ ((int)(TheBuffer[(byte)(8)])));
    TheBuffer[(byte)(7)]=(byte)(((int)(TheBuffer[(byte)(8)])) ^ ((int)(TheBuffer[(byte)(7)])));
              TheBuffer[(byte)(6)]=(byte)(((int)(TheBuffer[(byte)(7)])) ^ ((int)(TheBuffer[(byte)(6)])));
              TheBuffer[(byte)(5)]=(byte)(((int)(TheBuffer[(byte)(6)])) ^ ((int)(TheBuffer[(byte)(5)])));
              return;
    READING DATA:
    CLIENT PROGRAM :
    //Get string from the card
    SetLength(DataToSend, 5);
    DataToSend[0] := $88;
    DataToSend[1] := $10;
    DataToSend[2] := $BE;
    DataToSend[3] := $00;
    DataToSend[4] := $4;
    FSCard.SendCustomAPDU(DataToSend, ReceiveBuffer);
    APPLET CODE CALLING THE PROCEDURE:
    private void GetStr(APDU apdu) {
              byte buffer[] = apdu.getBuffer();
              byte numBytes = buffer[ISO7816.OFFSET_LC];
              apdu.setOutgoing();
              apdu.setOutgoingLength(numBytes);
              byte index;
    byte indexsn;
    indexsn=0;
              for (index = 80; index <= (byte)(80+(int)(numBytes)); index++){
                   buffer[(byte)(indexsn)] = TheBuffer[(byte)(index + 1)];
    indexsn++;
    apdu.sendBytesLong(buffer,(short)0,(short)numBytes);
              return;
    }

  • Send APDU just one time

    My application (in delphi) send Name(string), Family(string), And children (array of string)...
    then These data will convert into Hex format and will be sent to CAD via APDU...
    My question is how can I send all of these data at once via on APDU command, should I send Name and Family one by one and also send every index in my array one by one ??
    I wrote an applet which has a SetName, Set Family and SetChildren Methods and once call SetName and send Name via one APDU, then call SetFamily and send Family via other APDU, and the big problem is in array that I'm sending each index data of array via one APDU...
    I'm sure it's a foolish way and there's a better way to send these data :)
    would u please help me and guid me what can I do, this is so much urgent
    Kind Regards
    Hana

    Zip_Smart_Girl wrote:
    first a question about your last reply:
    I add this code in my applet process method, so what can i send from JCOP, can I now send Lc in 2 bytes ??The card you have is Java Card 2.2.1 which does not support extended length APDU's. As such your only choice is to implement chaining. This is also the reason why your code does not compile in Eclipse. You are building against the JC2.2.1 libraries.
    Here is some code that may help you get started. This code is not tested (apart from the fact it compiles) as I am not at work at the moment. This code comes with all the standard disclaimers and may not be fit for purpose... so use at your own risk :) There is still more validation that could go in (such as checking that the GET-RESPONSE command has the same CLA byte etc). Hopefully this code works and gets you started with command and response chaining. This may also help anyone else that needs to do something similar. If this can help just one person I will be happy.
    Cheers,
    Shane
    package chaining;
    import javacard.framework.APDU;
    import javacard.framework.Applet;
    import javacard.framework.ISO7816;
    import javacard.framework.ISOException;
    import javacard.framework.JCSystem;
    import javacard.framework.Util;
    * Very simple applet for chaining data to and from a card.
    * @author shane
    public class ChainingApplet extends Applet {
        private final static byte INS_GET_RESPONSE = (byte) 0xC0;
        private final static byte INS_PUT_DATA = 0x00;
        private final static byte INS_GET_DATA = 0x01;
        private final static byte OFFSET_SENT = 0x00;
        private final static byte OFFSET_RECV = 0x01;
        private static short[] offset;
        private static byte[] fileBuffer;
        private static short fileSize = 0;
        private final static short FILE_SIZE = 2048; // 2KB file
        private final static short MAX_APDU = 255;
         * Default constructor that initialises all memory to be used by the applet.
        public ChainingApplet() {
            offset = JCSystem.makeTransientShortArray((short) 2, JCSystem.CLEAR_ON_RESET);
            fileBuffer = new byte[FILE_SIZE];
         * {@inheritDoc}
        public static void install(byte[] bArray, short bOffset, byte bLength) {
            // GP-compliant JavaCard applet registration
            new ChainingApplet().register(bArray, (short) (bOffset + 1), bArray[bOffset]);
         * {@inheritDoc}
        public void process(APDU apdu) {
            // Good practice: Return 9000 on SELECT
            if (selectingApplet()) {
                return;
            short len = apdu.setIncomingAndReceive(); // This is the amount of data read from the OS.
            byte[] buf = apdu.getBuffer();
            byte cla = buf[ISO7816.OFFSET_CLA];
            byte ins = buf[ISO7816.OFFSET_INS];
            short lc = (short) (buf[ISO7816.OFFSET_LC] & 0x00ff); // this is the LC from the APDU.
            // get all bytes from the buffer
            while (len < lc) {
                len += apdu.receiveBytes(len);
            // validate the INS byte (basic check that tests for valid GET-RESPONSE or GET-DATA)
            if (offset[OFFSET_SENT] > 0 && ins != INS_GET_RESPONSE) {
                ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
            } else if (ins == INS_GET_RESPONSE && offset[OFFSET_SENT] == 0) {
                ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
            switch (buf[ISO7816.OFFSET_INS]) {
                case INS_PUT_DATA:
                    saveData(buf, ISO7816.OFFSET_CDATA, offset[OFFSET_RECV], len);
                    if ((cla & 0x10) != 0x00) {
                        offset[OFFSET_RECV] += len;
                    } else {
                        // last command in the chain
                        fileSize = (short) (offset[OFFSET_RECV] + len);
                        offset[OFFSET_RECV] = 0;
                    break;
                case INS_GET_DATA:
                case INS_GET_RESPONSE:
                    sendData(apdu);
                    break;
                default:
                    // good practice: If you don't know the INStruction, say so:
                    ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
         * Simple method to save the data somewhere. Add real implementation here.
         * @param source
         *            buffer containing data to copy
         * @param sourceOff
         *            offset into source buffer to the data
         * @param destOff
         *            offset into the destination buffer
         * @param len
         *            length of the data to copy.
        private static void saveData(byte[] source, short sourceOff, short destOff, short len) {
            // prevent buffer overflow
            if ((short) (destOff + len) > FILE_SIZE) {
                ISOException.throwIt(ISO7816.SW_FILE_FULL);
            Util.arrayCopy(source, sourceOff, fileBuffer, destOff, len);
         * Simple method to send chainined data to the client application (if required).
         * @param apdu
         *            current APDU
        private void sendData(APDU apdu) {
            // work out how many bytes to send this time and how many will be left
            short remain = (short) (fileSize - offset[OFFSET_SENT]);
            boolean chain = remain > MAX_APDU;
            short sendLen = chain ? MAX_APDU : remain;
            // Get ready to send
            apdu.setOutgoing();
            apdu.setOutgoingLength(sendLen);
            apdu.sendBytesLong(fileBuffer, offset[OFFSET_SENT], sendLen);
            // Check to see if there are more APDU's to send
            if (chain) {
                offset[OFFSET_SENT] += sendLen; // count the bytes sent
                ISOException.throwIt(ISO7816.SW_BYTES_REMAINING_00); // indicate there are more bytes to come
            } else {
                offset[OFFSET_SENT] = 0; // no more bytes to send
    }

  • Still having problems storing bytes...

    Ok, I tried using the Util.CopyArray and CopyArrayNonAtomic methods with the following arguments:
    Util.CopyArrayNonAtomic(buffer, ISO7816_CDATA, first, (short)0, byteRead);
    I am still receiving the same error and I'm sure that it must be from this section. This is the code that I use for my method that writes data:
    byte[] buffer = apdu.getBuffer();
    byte numBytes = buffer[ISO7816.OFFSET_LC];
    byte byteRead = (byte)(apdu.setIncomingAndReceive());
    if (numBytes != byteRead){
    ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    Util.CopyArrayNonAtomic(buffer, ISO7816_CDATA, first, (short)0, byteRead);
    I'm wondering if it's possible for me to use a for loop as I had originally intended since this method isn't working?

    Allocate memory for first byte array.
    Also check the return value on the CopyArray..() method.

  • Unable to delete applet.....

    Hi all,
    I am unable to delete one applet which I have loaded in the card.
    There are 2 applets, one is purse and other is loyalty. And am using shareable interface in which loyalty is the server and purse is the client. I can delete the purse applet but i can't delete the loyalty from the card.
    Here is my code : There are in all 3 codes, one is purse, second is loyalty code and third is the shareable interface code. Can some one look at the code and tell me what's wrong in this programs.
    package com.gemplus.examples.loyalty;
    import javacard.framework.*;
    import visa.openplatform.*;
    public class Loyalty extends javacard.framework.Applet implements TestInterface
    static byte points ;
    protected Loyalty(byte[] buffer, short offset, byte length)
    // data offset is used for application specific parameter.
    // initialization with default offset (AID offset).
    short dataOffset = offset;
    if(length > 9) {
    // Install parameter detail. Compliant with OP 2.0.1.
    // | size | content
    // |------|---------------------------
    // | 1 | [AID_Length]
    // | 5-16 | [AID_Bytes]
    // | 1 | [Privilege_Length]
    // | 1-n | [Privilege_Bytes] (normally 1Byte)
    // | 1 | [Application_Proprietary_Length]
    // | 0-m | [Application_Proprietary_Bytes]
    // shift to privilege offset
    dataOffset += (short)(1 + buffer[offset]);
    // finally shift to Application specific offset
    dataOffset += (short)(1 + buffer[dataOffset]);
    // checks wrong data length
    if(buffer[dataOffset] != 4)
    // return received proprietary data length in the reason
    ISOException.throwIt((short)(ISO7816.SW_WRONG_LENGTH + offset + length - dataOffset));
    // go to proprietary data
    dataOffset++;
    // points = 0;
    // register this instance
    register(buffer, (short)(offset + 1), (byte)buffer[offset]);
    * Method installing the applet.
    * @param bArray the array constaining installation parameters
    * @param bOffset the starting offset in bArray
    * @param bLength the length in bytes of the data parameter in bArray
    public static void install(byte[] bArray, short bOffset, byte bLength) throws ISOException
    /* applet instance creation */
    new Loyalty (bArray, bOffset, (byte)bLength);
    * Select method returning true if applet selection is supported.
    * @return boolean status of selection.
    public boolean select()
    /* return status of selection */
    return true;
    * Deselect method.
    public void deselect()
    return;
    public void process(APDU apdu) throws ISOException
              // check valid Applet state
    if(OPSystem.getCardContentState() == OPSystem.APPLET_BLOCKED)
              ISOException.throwIt(ISO7816.SW_COMMAND_NOT_ALLOWED);
                   apdu.setIncomingAndReceive();
              byte[] apduBuffer = apdu.getBuffer();
    // writes the balance into the APDU buffer after the APDU command part
              creditPoints((byte)0x00);     
              apduBuffer[5] = (byte)(points >> 8) ;
              apduBuffer[6] = (byte)points ;
    // sends the APDU response
    // switches to output mode
              apdu.setOutgoing() ;
    // 2 bytes to return
              apdu.setOutgoingLength((short)2) ;
    // offset and length of bytes to return in the APDU buffer
              apdu.sendBytes((short)5, (short)2) ;
         public void creditPoints(byte pTobeCredited)
    points += pTobeCredited;
    public Shareable getShareableInterfaceObject(AID client, byte param){
              if(param != (byte)0x00)
                   return null;
         return (this);
    second code is :
    package com.gemplus.examples.oppurse;
    * Imported packages
    import javacard.framework.*;
    import visa.openplatform.*;
    import com.gemplus.examples.loyalty.*;
    public class OPPurse extends javacard.framework.Applet
    // the APDU constants for all the commands.
         private final static byte INS_GET_BALANCE = (byte)0x30 ;
         private final static byte INS_DEBIT      = (byte)0x31 ;
         private final static byte INS_CREDIT      = (byte)0x32 ;
         private final static byte INS_VERIFY_PIN = (byte)0x33 ;
         private final static byte INS_SET_NAME                    = (byte)0x34 ;
         private final static byte INS_GET_NAME                    = (byte)0x35 ;
    // the OP/VOP specific instruction set for mutual authentication
         private final static byte CLA_INIT_UPDATE = (byte)0x80 ;
         private final static byte INS_INIT_UPDATE = (byte)0x50 ;
         private final static byte CLA_EXTERNAL_AUTHENTICATE = (byte)0x84 ;
         private final static byte INS_EXTERNAL_AUTHENTICATE = (byte)0x82 ;
    // the PIN validity flag
    private boolean validPIN = false;
    // SW bytes for PIN Failed condition
         // the last nibble is replaced with the number of remaining tries
         private final static short      SW_PIN_FAILED = (short)0x63C0;
         private final static short SW_FAILED_TO_OBTAIN_SIO = (short)0x63D0;
         private final static short SW_LOYALTY_APP_NOT_EXIST = (short)0x63E0;
    // the illegal amount value for the exceptions.
    private final static short ILLEGAL_AMOUNT = 1;
    // the maximum balance in this purse.
    private static final short maximumBalance = 10000;
    // the current balance in this purse.
    private static short balance;
    /*     byte[] loyaltyAID = new byte[]{ (byte)0xA0,(byte)0x00,(byte)0x00,(byte)0x00,
              (byte)0x19,(byte)0xFF,(byte)0x00,(byte)0x00,
              (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,
              (byte)0x00,(byte)0x00,(byte)0x02,(byte)0x02};*/
    /* Security part of declarations */
    // the Security Object necessary to credit the purse
    private ProviderSecurityDomain securityObject = null;
    // the security channel number
    byte secureChannel = (byte)0xFF;
    // the authentication status
    private boolean authenticationDone = false;
    // the secure channel status
    private boolean channelOpened = false;
         private byte[] nameBuffer = new byte[6];
    * Only this class's install method should create the applet object.
    protected OPPurse(byte[] buffer, short offset, byte length)
    // data offset is used for application specific parameter.
    // initialization with default offset (AID offset).
    short dataOffset = offset;
    if(length > 9) {
    // Install parameter detail. Compliant with OP 2.0.1.
    // | size | content
    // |------|---------------------------
    // | 1 | [AID_Length]
    // | 5-16 | [AID_Bytes]
    // | 1 | [Privilege_Length]
    // | 1-n | [Privilege_Bytes] (normally 1Byte)
    // | 1 | [Application_Proprietary_Length]
    // | 0-m | [Application_Proprietary_Bytes]
    // shift to privilege offset
    dataOffset += (short)( 1 + buffer[offset]);
    // finally shift to Application specific offset
    dataOffset += (short)( 1 + buffer[dataOffset]);
    // checks wrong data length
    if(buffer[dataOffset] != 2)
    // return received proprietary data length in the reason
    ISOException.throwIt((short)(ISO7816.SW_WRONG_LENGTH + offset + length - dataOffset));
    // go to proprietary data
    dataOffset++;
    } else {
    // Install parameter compliant with OP 2.0.
    if(length != 2)
    ISOException.throwIt((short)(ISO7816.SW_WRONG_LENGTH + length));
              // retreive the balance value from the APDU buffer
    short value = (short)(((buffer[(short)(dataOffset + 1)]) & 0xFF)
              | ((buffer[dataOffset] & 0xFF) << 8));
    // checks initial balance value
    if(value > maximumBalance)
    ISOException.throwIt(ISO7816.SW_DATA_INVALID);
              // initializes the balance with the APDU buffer contents
    balance = value;
    // register this instance as an installed Applet
    register();
    // ask the system for the Security Object associated to the Applet
    securityObject = OPSystem.getSecurityDomain();
    // applet is personalized and its state can change
    OPSystem.setCardContentState(OPSystem.APPLET_PERSONALIZED);
    // build the new ATR historical bytes
    byte[] newATRHistory = new byte[]
    // put "OPPurse" in historical bytes.
    (byte)0x4F, (byte)0x50, (byte)0x50, (byte)0x75, (byte)0x72, (byte)0x73, (byte)0x65
    // !!! ACTIVATED IF INSTALL PRIVILEGE IS "Default Selected" (0x04). !!!
    // change the default ATR to a personalized's one
    OPSystem.setATRHistBytes(newATRHistory, (short)0, (byte)newATRHistory.length);
    * Method installing the applet.
    * @param installparam the array constaining installation parameters
    * @param offset the starting offset in installparam
    * @param length the length in bytes of the data parameter in installparam
    public static void install(byte[] installparam, short offset, byte length )
    throws ISOException
    // applet instance creation with the initial balance
    new OPPurse(installparam, offset, length );
    * Select method returning true if applet selection is supported.
    * @return boolean status of selection.
    public boolean select()
    validPIN = false;
    // reset security if used.
    // In case of reset deselect is not called
    reset_security();
    // return status of selection
    return true;
    * Deselect method.
    public void deselect()
    // reset security if used.
    reset_security();
    return;
    * Method processing an incoming APDU.
    * @see APDU
    * @param apdu the incoming APDU
    * @exception ISOException with the response bytes defined by ISO 7816-4
    public void process(APDU apdu) throws ISOException
    // get the APDU buffer
    // the APDU data is available in 'apduBuffer'
    byte[] apduBuffer = apdu.getBuffer();
    // the "try" is mandatory because the debit method
    // can throw a javacard.framework.UserException
    try
         switch(apduBuffer[ISO7816.OFFSET_INS])
    case INS_VERIFY_PIN :
         verifyPIN(apdu);
    break ;
    case INS_GET_BALANCE :
         getBalance(apdu) ;
    break ;
    case INS_DEBIT :
         debit(apdu) ;
    break ;
                        case INS_SET_NAME :
                             setName(apdu);
                        break;
                        case INS_GET_NAME :
                             getName(apdu);
                        break ;
    case INS_CREDIT :
         credit(apdu) ;
    break ;
    case INS_INIT_UPDATE :
    if(apduBuffer[ISO7816.OFFSET_CLA] == CLA_INIT_UPDATE)
    // call initialize/update security method
         init_update(apdu) ;
    else
    // wrong CLA received
    ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
    break ;
    case INS_EXTERNAL_AUTHENTICATE :
    if(apduBuffer[ISO7816.OFFSET_CLA] == CLA_EXTERNAL_AUTHENTICATE)
    // call external/authenticate security method
         external_authenticate(apdu) ;
    else
    // wrong CLA received
    ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
    break ;
    case ISO7816.INS_SELECT :
    break ;
    default :
    // The INS code is not supported by the dispatcher
         ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED) ;
    break ;
         }     // end of the switch
    } // end of the try
              catch(UserException e)
    // translates the UserException in an ISOException.
              if(e.getReason() == ILLEGAL_AMOUNT)
    throw new ISOException ( ISO7816.SW_DATA_INVALID ) ;
    //- P R I V A T E M E T H O D S -
         * Handles Verify Pin APDU.
         * @param apdu APDU object
         private void verifyPIN(APDU apdu)
    // get APDU data
              apdu.setIncomingAndReceive();
    // get APDU buffer
    byte[] apduBuffer = apdu.getBuffer();
    // check that the PIN is not blocked
    if(OPSystem.getTriesRemaining() == 0)
    OPSystem.setCardContentState(OPSystem.APPLET_BLOCKED);
    // Pin format for OP specification
    // |type(2),length|nible(1),nible(2)|nible(3),nible(4)|...|nible(n-1),nible(n)|
    // get Pin length
    byte length = (byte)(apduBuffer[ISO7816.OFFSET_LC] & 0x0F);
    // pad the PIN ASCII value
    for(byte i=length; i<0x0E; i++)
    // only low nibble of padding is used
    apduBuffer[ISO7816.OFFSET_CDATA + i] = 0x3F;
    // fill header TAG
    apduBuffer[0] = (byte)((0x02 << 4) | length);
    // parse ASCII Pin code
    for(byte i=0; i<0x0E; i++)
    // fill bytes with ASCII Pin nibbles
    if((i & 0x01) == 0)
    // high nibble
    apduBuffer[(i >> 1)+1] = (byte)((apduBuffer[ISO7816.OFFSET_CDATA + i] & 0x0F) << 4);
    else
    // low nibble
    apduBuffer[(i >> 1)+1] |= (byte)(apduBuffer[ISO7816.OFFSET_CDATA + i] & 0x0F);
    // verify the received PIN
    // !!! WARNING PIN HAS TO BE INITIALIZED BEFORE USE !!!
    if(OPSystem.verifyPin(apdu, (byte)0))
    // set PIN validity flag
    validPIN = true;
    // if applet state is BLOCKED then restore previous state (PERSONALIZED)
    if(OPSystem.getCardContentState() == OPSystem.APPLET_BLOCKED)
    OPSystem.setCardContentState(OPSystem.APPLET_PERSONALIZED);
    return;
         // the last nibble of returned code is the number of remaining tries
              ISOException.throwIt((short)(SW_PIN_FAILED + OPSystem.getTriesRemaining()));
    * Performs the "getBalance" operation on this counter.
    * @param apdu The APDU to process.
    private void getBalance( APDU apdu )
    // check valid Applet state
    if(OPSystem.getCardContentState() == OPSystem.APPLET_BLOCKED)
                   ISOException.throwIt(ISO7816.SW_COMMAND_NOT_ALLOWED);
    // get the APDU buffer
    byte[] apduBuffer = apdu.getBuffer();
    // writes the balance into the APDU buffer after the APDU command part
              apduBuffer[5] = (byte)(balance >> 8) ;
              apduBuffer[6] = (byte)balance ;
    // sends the APDU response
    // switches to output mode
              apdu.setOutgoing() ;
    // 2 bytes to return
              apdu.setOutgoingLength((short)2) ;
    // offset and length of bytes to return in the APDU buffer
              apdu.sendBytes((short)5, (short)2) ;
         private void setName(APDU apdu)
              // check valid Applet state
    if(OPSystem.getCardContentState() == OPSystem.APPLET_BLOCKED)
                   ISOException.throwIt(ISO7816.SW_COMMAND_NOT_ALLOWED);
              // the operation is allowed only if master pin is validated
         if(!validPIN)
    ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
              byte[] apduBuffer = apdu.getBuffer();
              apdu.setIncomingAndReceive();     
              for(short i=0,k=5;i<6;i++,k++)
                   nameBuffer[i] = apduBuffer[k];
         }//end of setName
         private void getName(APDU apdu)
              // check valid Applet state
    if(OPSystem.getCardContentState() == OPSystem.APPLET_BLOCKED)
                   ISOException.throwIt(ISO7816.SW_COMMAND_NOT_ALLOWED);
                   byte[] apduBuffer = apdu.getBuffer();
                   for(short i=5, k=0;i<11;i++,k++)
                        apduBuffer=nameBuffer[k];
                   apdu.setOutgoing();
                   apdu.setOutgoingLength((short)6);
                   apdu.sendBytes((short)5,(short)6);
         }//end of storeName
    * Performs the "debit" operation on this counter.
    * @param apdu The APDU to process.
    * @exception ISOException If the APDU is invalid.
    * @exception UserException If the amount to debit is invalid.
    private void debit(APDU apdu) throws ISOException, UserException
    // check valid Applet state
    if(OPSystem.getCardContentState() == OPSystem.APPLET_BLOCKED)
                   ISOException.throwIt(ISO7816.SW_COMMAND_NOT_ALLOWED);
    // the operation is allowed only if master pin is validated
         if(!validPIN)
    ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
    // get the APDU buffer
    byte[] apduBuffer = apdu.getBuffer();
         // Gets the length of bytes to recieved from the terminal and receives them
    // If does not receive 4 bytes throws an ISO.SW_WRONG_LENGTH exception
              if(apduBuffer[4] != 2 || apdu.setIncomingAndReceive() != 2)
              ISOException.throwIt(ISO7816.SW_WRONG_LENGTH) ;
              // Reads the debit amount from the APDU buffer
    // Starts at offset 5 in the APDU buffer since the 5 first bytes
    // are used by the APDU command part
              short amount = (short)(((apduBuffer[6]) & (short)0x000000FF)
    | ((apduBuffer[5] << 8 ) & (short)0x0000FF00));
    // tests if the debit is valid
    if((balance >= amount) && (amount > 0))
    // does the debit operation
    balance -= amount ;
    // writes the new balance into the APDU buffer
    // (writes after the debit amount in the APDU buffer)
    apduBuffer[7] = (byte)(balance >> 8) ;
    apduBuffer[8] = (byte)balance ;
    // sends the APDU response
    apdu.setOutgoing() ; // Switches to output mode
    apdu.setOutgoingLength((short)2) ; // 2 bytes to return
    // offset and length of bytes to return in the APDU buffer
    apdu.sendBytes((short)7, (short)2) ;
              /*short points = 10;
    AID loyaltyID = JCSystem.lookupAID(loyaltyAID, (short)0, (byte)loyaltyAID.length);
              if(loyaltyID == null)
                   ISOException.throwIt((short)(SW_LOYALTY_APP_NOT_EXIST));
              TestInterface sio = (TestInterface)(JCSystem.getAppletShareableInterfaceObject(loyaltyID, (byte)0x00));
              if(sio == null)
                   ISOException.throwIt((short)(SW_FAILED_TO_OBTAIN_SIO));
              sio.creditPoints(points);*/
    else
    // throw a UserException with illegal amount as reason
    throw new UserException(ILLEGAL_AMOUNT) ;
    /* byte points = (byte)0x0A;
              //short points = 10;
    AID loyaltyID = JCSystem.lookupAID(loyaltyAID, (short)0, (byte)loyaltyAID.length);
              if(loyaltyID == null)
                   ISOException.throwIt((short)(SW_LOYALTY_APP_NOT_EXIST));
              TestInterface sio = (TestInterface)JCSystem.getAppletShareableInterfaceObject(loyaltyID, (byte)0x00);
              if(sio == null)
                   ISOException.throwIt((short)(SW_FAILED_TO_OBTAIN_SIO));
              sio.creditPoints(points);*/
    * Performs the "credit" operation on this counter. The operation is allowed only
    * if master pin is validated
    * @param apdu The APDU to process.
    * @exception ISOException If the APDU is invalid or if the amount to credit
    * is invalid.
    private void credit(APDU apdu) throws ISOException
    // check valid Applet state
    if(OPSystem.getCardContentState() == OPSystem.APPLET_BLOCKED)
                   ISOException.throwIt(ISO7816.SW_COMMAND_NOT_ALLOWED);
    // the operation is allowed only if master pin is validated and authentication is done
         if (!validPIN || !authenticationDone)
    ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
    // get the APDU buffer
    byte[] apduBuffer = apdu.getBuffer();
              // gets the length of bytes to recieved from the terminal and receives them
    // if does not receive 2 bytes throws an ISO.SW_WRONG_LENGTH exception
              if(apduBuffer[4] != 2 || apdu.setIncomingAndReceive() != 2)
    throw new ISOException(ISO7816.SW_WRONG_LENGTH) ;
              // reads the credit amount from the APDU buffer
    // starts at offset 5 in the APDU buffer since the 5 first bytes
    // are used by the APDU command part
              short amount = (short)(((apduBuffer[6]) & (short)0x000000FF)
    | ((apduBuffer[5] << 8) & (short)0x0000FF00));
    // tests if the credit is valid
    if(((short)(balance + amount) > maximumBalance) || (amount <= (short)0))
    throw new ISOException(ISO7816.SW_DATA_INVALID) ;
    else
    // does the credit operation
    balance += amount ;
    * Performs the "init_update" security operation.
    * @param apdu The APDU to process.
    private void init_update( APDU apdu )
    // receives data
    apdu.setIncomingAndReceive();
    // checks for existing active secure channel
    if(channelOpened)
    // close the openned security channel
    try
    securityObject.closeSecureChannel(secureChannel);
    catch(CardRuntimeException cre2)
    // channel number is invalid. this case is ignored
    // set the channel flag to close
    channelOpened = false;
    try
    // open a new security channel
    secureChannel = securityObject.openSecureChannel(apdu);
    // set the channel flag to open
    channelOpened = true;
    // get expected length
    short expected = apdu.setOutgoing();
    // send authentication result
    // expected length forced to 0x1C
    apdu.setOutgoingLength((byte)0x1C);
    apdu.sendBytes(ISO7816.OFFSET_CDATA, (byte)0x1c);
    catch(CardRuntimeException cre)
    // no available channel or APDU is invalid
    ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
    * Performs the "external_authenticate" security operation.
    * @param apdu The APDU to process.
    private void external_authenticate( APDU apdu )
    // receives data
    apdu.setIncomingAndReceive();
    // checks for existing active secure channel
    if(channelOpened)
    try
    // try to authenticate the client
    securityObject.verifyExternalAuthenticate(secureChannel, apdu);
    // authentication succeed
    authenticationDone = true;
    catch(CardRuntimeException cre)
    // authentication fails
    // set authentication flag to fails
    authenticationDone = false;
    // close the openned security channel
    try {
    securityObject.closeSecureChannel(secureChannel);
    } catch(CardRuntimeException cre2) {
    // channel number is invalid. this case is ignored
    // set the channel flag to close
    channelOpened = false;
    // send authentication result
    ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
    // send authentication result
    ISOException.throwIt(ISO7816.SW_NO_ERROR);
    else
    ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
    * The "reset_security" method close an opened secure channel if exist.
    * @return void.
    public void reset_security()
    // close the secure channel if openned.
    if(secureChannel != (byte)0xFF)
    try
    // close the openned security channel
    securityObject.closeSecureChannel(secureChannel);
    catch(CardRuntimeException cre2)
    // channel number is invalid. this case is ignored
    // reset security parameters
    secureChannel = (byte)0xFF;
    channelOpened = false;
    authenticationDone = false;
    return;
    and the 3rd code is:
    package com.gemplus.examples.loyalty;
    import javacard.framework.Shareable;
    public interface TestInterface extends Shareable
    // public void creditPoints(byte points) ;
              public void creditPoints(byte points) ;
    Thanks in advance......

    Thanks. I know they are not the same thing. A package cannot be deleted if it contains one or more applets.
    I tried to delete by typing in the applet AID first, but it just doesn't work. And of course it doesn't work for package AID.
    Both the package and applet AID are generated in JBuilder, which looks like this, package AID(6D 79 70 61 63 6B 61 67 31),
    applet AID(6D 79 70 61 63 30 30 30 31),
    instance AID(6D 79 70 61 63 30 30 30 31)
    I've tried those three AIDs, it's not working.
    Thanks.

  • Is there ANYONE who have REAL knowelage with JAVA CARD OS?

    It is serious problem. Same problem like this one:
    http://forums.sun.com/thread.jspa?threadID=5344671&tstart=30
    Anyway. Main problem is that if you want to use several times encryption using different key every time
    soon or later card will BLOCK itself!!!
    Well it will return code 6F00 and ONLY whole reprograming of card will help!!!
    Here is simple code:
    package com.cpit.javacard;
    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 javacard.security.AESKey;
    import javacard.security.DESKey;
    import javacard.security.Key;
    import javacard.security.KeyBuilder;
    import javacard.security.MessageDigest;
    import javacard.security.RSAPrivateCrtKey;
    import javacardx.crypto.Cipher;
    public class DES3a extends Applet
    byte[] staticKey = {0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47};
    byte[] inData ={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
    byte[] outData ={(byte) 0xF1,(byte) 0xD7,(byte) 0x5E,(byte) 0x4F,(byte) 0x0D,(byte) 0x37,(byte) 0xC2,(byte) 0x2C,(byte) 0xB8,(byte) 0xD5,(byte) 0x4E,(byte) 0x62,(byte) 0x53,(byte) 0xBB,(byte) 0x40,(byte) 0xB1};
    byte[] dummy = new byte[4024];
    //constructor
    private DES3a (byte bArray[], short bOffset, byte bLength)
    register(bArray, (short) (bOffset + 1), bArray[bOffset]);
    // install
    public static void install(byte bArray[], short bOffset, byte bLength)
    new DES3a (bArray, bOffset, bLength);
    public void process(APDU apdu)
         byte[] buf = apdu.getBuffer();
         // Good practice: Return 9000 on SELECT
    if (selectingApplet())
    return;
    if (buf[ISO7816.OFFSET_CLA] != (byte) (0xB0)) ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
    if (buf[ISO7816.OFFSET_INS] != (byte) (0xAA)) ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
    byte buffer[] = apdu.getBuffer();
    Crypt_DES(apdu);
    private void Crypt_DES(APDU apdu)
    byte[] buffer = apdu.getBuffer();
    for( short i = 0; i<(short)50; i++) {
    generateSessionKey(inData, staticKey, buffer);
    if (Util.arrayCompare(buffer,(short) 0, outData, (short)0x0, (short)16) != 0 ) break;
    Util.arrayCopy(outData, (short)(0), buffer, (short)16, (short)16);
    apdu.setOutgoing();
    apdu.setOutgoingLength((byte) 0x30);
    apdu.sendBytes((short) 0, (byte) 0x30);
         return;
         private void generateSessionKey(byte[] derivationData, byte[] staticKey,byte[] sessionKey){
              DESKey key = ( DESKey )KeyBuilder.buildKey(KeyBuilder.TYPE_DES, KeyBuilder.LENGTH_DES3_2KEY, false );
              key.setKey( staticKey, (short)0 );
              Cipher cipher = Cipher.getInstance( Cipher.ALG_DES_ECB_NOPAD, true );
              cipher.init( key, Cipher.MODE_ENCRYPT );
              cipher.doFinal(derivationData, (short)0, (short)16, sessionKey, (short)0);               
              key.clearKey();
    It seems that problem is in KeyBuilder?! . Is this function allocates EEPROM??? how can be that memory
    deallocated? Even worst is if it used TYPE_DES_TRANSIENT_DESELECT insead TYPE_DES!!!
    In example from above in loop top value is 50. On some cards (depend on EEPROM size) it can be even
    1000 ! but still it will crash on the end!
    Also increasing size of "dummy" it will reduce number of DES runs.
    Here is results:
    cm> /select 11223344556677
    => 00 A4 04 00 07 11 22 33 44 55 66 77 00 ......"3DUfw.
    (20215 usec)
    <= 90 00 ..
    Status: No Error
    cm> send b0aa000000
    => B0 AA 00 00 00 .....
    (14394373 usec)
    <= F1 D7 5E 4F 0D 37 C2 2C B8 D5 4E 62 53 BB 40 B1 ..^O.7.,..NbS.@.
    F1 D7 5E 4F 0D 37 C2 2C B8 D5 4E 62 53 BB 40 B1 ..^O.7.,..NbS.@.
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
    90 00 ..
    Status: No Error
    cm> send b0aa000000
    => B0 AA 00 00 00 .....
    (15024947 usec)
    <= F1 D7 5E 4F 0D 37 C2 2C B8 D5 4E 62 53 BB 40 B1 ..^O.7.,..NbS.@.
    F1 D7 5E 4F 0D 37 C2 2C B8 D5 4E 62 53 BB 40 B1 ..^O.7.,..NbS.@.
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
    90 00 ..
    Status: No Error
    cm> send b0aa000000
    => B0 AA 00 00 00 .....
    (15632306 usec)
    <= F1 D7 5E 4F 0D 37 C2 2C B8 D5 4E 62 53 BB 40 B1 ..^O.7.,..NbS.@.
    F1 D7 5E 4F 0D 37 C2 2C B8 D5 4E 62 53 BB 40 B1 ..^O.7.,..NbS.@.
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
    90 00 ..
    Status: No Error
    cm> send b0aa000000
    => B0 AA 00 00 00 .....
    (8572462 usec)
    <= 6F 00 o.
    Status: No precise diagnosis
    As you can see that card (jcop41) can run correct less than 200 times!!!
    On gemplus 64k it can run less than 1200 times!!!
    So is there any method for dealocating EEPROM that is used by KeyBuilder?
    Or to use RAM (Using TYPE_DES_TRANSIENT_DESELECT is even worst!)
    That is problem with EEPROM here is proof:
    On halted card when is application deleted it takes more time !!!
    ;HALTED CARD
    cm> ext-auth plain
    => 84 82 00 00 10 B0 B9 D5 5A FC D3 BA 3F AE 85 CD ........Z...?...
    9F 24 25 A5 04 .$%..
    (123134 usec)
    <= 90 00 ..
    Status: No Error
    cm> delete 11223344556677
    => 80 E4 00 00 09 4F 07 11 22 33 44 55 66 77 00 .....O.."3DUfw.
    (3235735 usec)
    <= 00 90 00 ...
    Status: No Error
    cm> delete 112233445566
    => 80 E4 00 00 08 4F 06 11 22 33 44 55 66 00 .....O.."3DUf.
    (940978 usec)
    <= 00 90 00 ...
    Status: No Error
    NORMAL CARD
    cm> ext-auth plain
    => 84 82 00 00 10 96 4D 17 94 84 41 0B 03 62 BF AC ......M...A..b..
    3D 72 41 E0 D4 =rA..
    (67224 usec)
    <= 90 00 ..
    Status: No Error
    cm> delete 11223344556677
    => 80 E4 00 00 09 4F 07 11 22 33 44 55 66 77 00 .....O.."3DUfw.
    (930056 usec)
    <= 00 90 00 ...
    Status: No Error
    cm> delete 112233445566
    => 80 E4 00 00 08 4F 06 11 22 33 44 55 66 00 .....O.."3DUf.
    (946824 usec)
    <= 00 90 00 ...
    Status: No Error
    As you can see 3235735 usec vs 930056 usec
    Any help?
    regards

    Ok, thanks for hints & help, here is a tested working example:
    static byte DES_flag = 0xa5;
    DESKey key ;
    Cipher cipher;
    //constructor
    // because I dont know how "install" handles functions i've use "selectingApplet"
    if (selectingApplet())
    if (DES_flag ==0xa5){
    cipher = Cipher.getInstance( Cipher.ALG_DES_ECB_NOPAD, false );     //instead true!     
    key = (DESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_DES_TRANSIENT_DESELECT , KeyBuilder.LENGTH_DES3_2KEY, true );
    DES_flag =0;
         return;
         private void generateSessionKey(byte[] derivationData, byte[] staticKey,byte[] sessionKey){
              key.setKey( staticKey, (short)0 );
              cipher.init( key, Cipher.MODE_ENCRYPT );
              cipher.doFinal(derivationData, (short)0, (short)16, sessionKey, (short)0);               
              key.clearKey();
    Regards

  • Rsa Decrypt Not Working.. Please Help

    Hi everyone,
         I am new to java card development. I have been trying to use RSA encryption in my Applet. I finally got the encryption working but the decryption is showing Illegal Use Error. Any kind of help is appreciated.
    public class RSAsample extends Applet{
    byte[] rsaPublic = new byte[4];
    byte[] rsaPrivate = new byte[4];
    byte[] rsaPublicMod = new byte[4];
    RSAPrivateKey pri ;
    RSAPublicKey pub ;
    private final static byte INS_ENCRYPT = (byte) 0x20;
    private final static byte INS_DECRYPT = (byte) 0x30;
    KeyPair pair ;
    private RSAsample() {
      super();
      register();
    public static void install(byte bArray[], short bOffset, byte bLength)
      throws ISOException {
      new RSAsample();
    public boolean select() {
      pair = new KeyPair(KeyPair.ALG_RSA, (short) 512);
      pair.genKeyPair();
    pri = (RSAPrivateKey) pair.getPrivate();
    pub = (RSAPublicKey) pair.getPublic();
      return super.select();
    public void deselect() {
      super.deselect();
       public void process(APDU apdu) throws ISOException {
        byte[] buffer = apdu.getBuffer();
        switch(buffer[ISO7816.OFFSET_INS])
        case INS_ENCRYPT:
        encrypt(apdu);
        break;
        case INS_DECRYPT:
        decrypt(apdu);
        break;
    private void decrypt(APDU apdu) {
      byte[] buffer = apdu.getBuffer();
      byte byteRead = (byte)(apdu.setIncomingAndReceive());
      short size = 0;
      try{
      Cipher cipher = Cipher.getInstance(Cipher.ALG_RSA_PKCS1, false);
      cipher.init(pri, Cipher.MODE_DECRYPT);
      size =  cipher.doFinal(buffer, ISO7816.OFFSET_CDATA, (short)byteRead, buffer,
      (short) 0);
      catch(CryptoException e)
      switch(e.getReason())
      case CryptoException.ILLEGAL_USE:
      ISOException.throwIt(ISO7816.SW_DATA_INVALID);
      break;
      case CryptoException.ILLEGAL_VALUE:
      ISOException.throwIt(ISO7816.SW_FILE_INVALID);
      break;
      case CryptoException.INVALID_INIT:
      ISOException.throwIt(ISO7816.SW_FILE_NOT_FOUND);
      break;
      case CryptoException.NO_SUCH_ALGORITHM:
      ISOException.throwIt(ISO7816.SW_FILE_INVALID);
      break;
      case CryptoException.UNINITIALIZED_KEY:
      ISOException.throwIt(ISO7816.SW_FILE_FULL);
      break;
      default:
      ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
      break;
      apdu.setOutgoing();
      apdu.setOutgoingLength(size);
      apdu.sendBytes((short)0, size);
    private void encrypt(APDU apdu) {
      byte[] buffer = apdu.getBuffer();
      byte byteRead = (byte)(apdu.setIncomingAndReceive());
      short size = 0;
      try{
      Cipher cipher = Cipher.getInstance(Cipher.ALG_RSA_PKCS1, false);
      cipher.init(pub, Cipher.MODE_ENCRYPT);
      size =  cipher.doFinal(buffer, ISO7816.OFFSET_CDATA, (short)byteRead, buffer,
      (short) 0);
      catch(CryptoException e)
      switch(e.getReason())
      case CryptoException.ILLEGAL_USE:
      ISOException.throwIt(ISO7816.SW_DATA_INVALID);
      break;
      case CryptoException.ILLEGAL_VALUE:
      ISOException.throwIt(ISO7816.SW_FILE_INVALID);
      break;
      case CryptoException.INVALID_INIT:
      ISOException.throwIt(ISO7816.SW_FILE_NOT_FOUND);
      break;
      case CryptoException.NO_SUCH_ALGORITHM:
      ISOException.throwIt(ISO7816.SW_FILE_INVALID);
      break;
      case CryptoException.UNINITIALIZED_KEY:
      ISOException.throwIt(ISO7816.SW_FILE_FULL);
      break;
      default:
      ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
      break;
      apdu.setOutgoing();
      apdu.setOutgoingLength(size);
      apdu.sendBytes((short)0, size);
    Also if this is wrong can you share a sample code using RSA Encryption and Decryption.
    Thanks

    Hi,
    You code looks perfectly fine.
    Looking at the error code i think you are sending some invalid data for decryption operation.
    You should send data which was encrypted using the same PublicKey other wise it will fail while matching the Padding or Data Blocks.
    For better understanding Encrypt some data and immediately use the output data for Decrypt operation and it should work fine.
    Let me know if you face any difficulties.
    BR,
    PPT

Maybe you are looking for

  • Please Help Me!!! I have problem while installing 11g RAC on Windows!!!

    Guys, I have to configure a test environment on my pc. I need a 2-node RAC system which will run on Windows. Problem is this: I'm creating two networks on my nodes, public and private but when i come to grid installation, Oracle can not identify my n

  • Handycam Sony HDR-UX5 to iMovie08

    OX (10.4.11) mit iMovie 08 erkennt den Camorder HDR-UX5 nicht. Liegt das am Betriebssystem 10.4.? Brauche ich zusätzliche FinalCut4.0? Muß ich bei der Aufnahme in HD auf MiniDVD etwas spezielles am Camcorder einstellen werden? Brauche ich noch eine A

  • Gracenote Server Error Message

    Hi, Suddenly, obtaining track info from Gracenote when importing a CD no longer works for me. Just to be sure, I played with all firewall settings but made no change. Does anyone have any suggestions to what the cause may be? Better yet, is there any

  • Suppressing IE Address Bar (Location Bar) - Weird event

    Hi. We use the following code to call other stand-alone web forms from a single, main application. Each application has it's own web.show_document code. In the example below a call to a form name 'dropper_em' is called. It also passes the username an

  • How synchronize EJB diagram with database

    hi i need synchronize EJBv3.0 entity diagram with database but when i click in diagram the connection of database is deactive. in BC diagram e synchronize entity with database with not problem but ejb entity i not, why? i work in Jdev 11.1.1.0.2. bes