Page 1 of 1

What' wrong with my applet

Posted: Thu Sep 28, 2017 10:45 pm
by AmigoJack
I am experiencing a strange problem. I am using a JCOP J3D081 card to encrypt/decrypt messages and to store user information data. Everything works fine, but after some time the card does not give me the info, e.g. the stored exponent back. I guess there must be something wrong with the my javacard application. Could anyone help me figure out what happened to my applet?

Code: Select all

public class TestApplet extends Applet {
     
     final static byte Test_CLA                =(byte)0x00;
     final static byte VERIFY                = (byte) 0x20;
     final static byte GET_FIRSTNAME      = (byte) 0x30;
     final static byte GET_LASTNAME           = (byte) 0x40;
     final static byte GET_TITLE           = (byte) 0x50;
     final static byte GET_CARD_ID           = (byte) 0x45;
     final static byte BLOCK_CARD           = (byte) 0x35;
     final static byte GET_PUBLIC_KEY      = (byte) 0x60;
     final static byte DECRYPT                = (byte) 0x55;
     final static byte SET_PRIVATE_KEY     = (byte) 0x22;
     final static byte SET_PUBLIC_KEY     = (byte) 0x23;
     
     final static short   SW_DATA_NOT_FOUND = (short) 0x6A88;  // referenced data not found

     final static byte PIN_TRY_LIMIT =(byte)0x03;
     final static byte MAX_PIN_SIZE =(byte)0x04;
     
     final static byte[] defaultPIN = { 0x30, 0x30, 0x30, 0x30 };

     final static short SW_VERIFICATION_FAILED = 0x6300;

     final static short SW_PIN_VERIFICATION_REQUIRED = 0x6301;
     
     final static short SW_CARD_BLOCKED = 0x6302;

     final static short MAX_ID_SIZE = ( short )5;
     final static short MAX_NAME_SIZE = ( short )20;
     final static short MAX_TITLE_SIZE = ( short )10;
         
     byte[] cardID = null;
     byte[] defaultPin = null;
     byte[] firstName = null;
     byte[] lastName = null;
     byte[] title = null;
     boolean BLOCKED = false;
     
     OwnerPIN pin;
     short key;
     private RSAPrivateCrtKey PrivateRSAKey1024;
     private RSAPublicKey PublicRSAKey1024;
     private KeyPair keypair;
    private static Cipher cipher;

private TestApplet (byte[] bArray,short bOffset,byte bLength)
{
      cardID      = new byte[ MAX_ID_SIZE ];
     defaultPin      = new byte[ MAX_PIN_SIZE ];
     firstName      = new byte[ MAX_NAME_SIZE ];
     lastName     = new byte[ MAX_NAME_SIZE ];
     title           = new byte[ MAX_TITLE_SIZE ];
     pin           = new OwnerPIN(PIN_TRY_LIMIT, MAX_PIN_SIZE);
     /*
     // The installation parameters contain the PIN
     // initialization value
     pin.update(bArray, bOffset, bLength);*/
     short offset = ( short )( bOffset + bArray[bOffset] + 4 );  // AID+4 bytes
     Util.arrayCopyNonAtomic( bArray, offset, cardID, ( short )0,  MAX_ID_SIZE );
     offset+=MAX_ID_SIZE;
     
     Util.arrayCopyNonAtomic( bArray, offset, defaultPin, ( short )0, MAX_PIN_SIZE );
     offset+=MAX_PIN_SIZE;
     
     Util.arrayCopyNonAtomic( bArray, offset, firstName, ( short )0, MAX_NAME_SIZE );
     offset+=MAX_NAME_SIZE;
     
     Util.arrayCopyNonAtomic( bArray, offset, lastName, ( short )0, MAX_NAME_SIZE );
     offset+=MAX_NAME_SIZE;
     
     Util.arrayCopyNonAtomic( bArray, offset, title, ( short )0, MAX_TITLE_SIZE );
     offset+=MAX_TITLE_SIZE;
     
     byte iLen = bArray[bOffset];
     bOffset = (short) (bOffset + iLen + 1);
     byte cLen = bArray[bOffset];
     bOffset = (short) (bOffset + cLen + 1);
     byte aLen = bArray[bOffset];
     
     final byte PIN_SIZE = 0x04;

     pin.update(defaultPin, (short) 0, PIN_SIZE);
   
        cipher = Cipher.getInstance(Cipher.ALG_RSA_PKCS1, false );
   
        PrivateRSAKey1024 = (RSAPrivateCrtKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_CRT_PRIVATE, (short)1024, false);
        PublicRSAKey1024 = (RSAPublicKey)KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PUBLIC, KeyBuilder.LENGTH_RSA_1024, false);
          register();

}

public static void install(byte[] bArray, short bOffset, byte bLength) {
          new TestApplet(bArray, bOffset, bLength);
     }
.......

private void decrypt(APDU apdu)
     {
          short byteRead = (short)(apdu.setIncomingAndReceive());

          cipher.init(PrivateRSAKey1024, Cipher.MODE_DECRYPT);
          short outbytes;
          byte[] apduBuffer = apdu.getBuffer();
          short     Lc = (short) (apduBuffer[ISO7816.OFFSET_LC] & 0x00FF);
          byte[] outBuff = new byte[Lc];
         
          outbytes = cipher.doFinal(apduBuffer,(short)ISO7816.OFFSET_CDATA, byteRead, outBuff, (short)ISO7816.OFFSET_CDATA);
          apdu.setOutgoing();
          apdu.sendBytesLong(outBuff, (short)ISO7816.OFFSET_CDATA, (short)outbytes);
     }


private void getPublicKey(APDU apdu){
         
        byte[] apduBuffer = apdu.getBuffer();
     
        byte    keyElement = (byte)(apduBuffer[ISO7816.OFFSET_P2] & 0xFF);
        if((keyElement != 0x00) && (keyElement != 0x01))
            ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
     
        byte[] temp = new byte[4];
       
        byte[] tempMod = new byte[128];

        if(keyElement == 0) {
              apduBuffer[0] = (byte)((RSAPublicKey)PublicRSAKey1024).getModulus(apduBuffer, (short)1);

                   } else
        {
              apduBuffer[0] = (byte)((RSAPublicKey)PublicRSAKey1024).getExponent(apduBuffer, (short)1);

                     }

        apdu.setOutgoingAndSend((short)0, (short)((apduBuffer[0] & 0xFF) + 1));
    }

Re: What' wrong with my applet

Posted: Fri Sep 29, 2017 3:37 am
by Thelogan
It's memory problem.
JCOP supports object deletion . Please check JC 2.2.1 API doc, JCSystem.isObjectDeletionSupported() and requestObjectDeletion().

Re: What' wrong with my applet

Posted: Fri Sep 29, 2017 3:38 am
by AmigoJack
Thelogan wrote:It's memory problem.
JCOP supports object deletion . Please check JC 2.2.1 API doc, JCSystem.isObjectDeletionSupported() and requestObjectDeletion().


Thank you for your help. But where should I call requestObjectDeletion() ? And should I try to initialize all variables in constructor?

Re: What' wrong with my applet

Posted: Fri Sep 29, 2017 5:47 am
by Thelogan
AmigoJack wrote:Thank you for your help. But where should I call requestObjectDeletion() ? And should I try to initialize all variables in constructor?


Keep in mind that you should try to avoid memory leaks like that. Create a temp buffer array and allocate memory in the constructor. If you really cannot circumvent to allocate memory in a method, you need to analyze first what the worst case scenario is and call the object deletion mechanism only when the memory is close to full.