Search code examples
appletjavacardapdusim-card

how can i store data in sim card from sim card application?


i am writing a sim card applet and i need to store data on sim card.

but i didnt do it. i found an example and use it but data disappear always when simulator restart. i use "cmdPUTDATA(apdu);" method for save data and i use "cmdGETDATA(apdu);" method for save data.

here is my code and response;

     public void process(APDU apdu) {

        byte[] buffer = apdu.getBuffer();

        if (apdu.isISOInterindustryCLA()) {
            if (buffer[ISO7816.OFFSET_INS] == (byte) (0xA4)) {
                return;
            }
            ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
        }

        switch (buffer[ISO7816.OFFSET_INS]) {
            case INS_GET_BALANCE:
                getBalance(apdu);
                return;
            case INS_CREDIT:
                credit(apdu);
                return;
            case INS_CHARGE:
                charge(apdu);
                return;
//            case INS_SELECT:                      // it is a SELECT FILE instruction
//                cmdSELECT(apdu);
//                break;
//            case INS_VERIFY:                      // it is a VERIFY instruction
//                cmdVERIFY(apdu);
//                break;
//            case INS_PUTDATA:                     // it is a PUT DATA instruction
//                cmdPUTDATA(apdu);
//                break;
//            case INS_GETDATA:                     // it is a GET DATA instruction
//                cmdGETDATA(apdu);
//                break;
            default:
                ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
        }
    }

//    @TransactionType(REQUIRED)
    //synchronized 
    private void credit(APDU apdu) {

        byte[] buffer = apdu.getBuffer();
        byte numBytes = buffer[ISO7816.OFFSET_LC];
        byte byteRead = (byte) (apdu.setIncomingAndReceive());

        if ((numBytes != 2) || (byteRead != 2)) {
            ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
        }

        short creditAmount = (short) ((short) (buffer[ISO7816.OFFSET_CDATA] << (short) 8) | (buffer[ISO7816.OFFSET_CDATA + 1]));

        if ((creditAmount > MAX_BALANCE) || (creditAmount < (short) 0)) {
            ISOException.throwIt(SW_INVALID_TRANSACTION_AMOUNT);
        }

        if ((short) (balance + creditAmount) > MAX_BALANCE) {
            ISOException.throwIt(SW_MAX_BALANCE_EXCEEDED);
        }
        JCSystem.beginTransaction();
        balance = (short) (balance + creditAmount);
        JCSystem.commitTransaction();
    }

    private void getBalance(APDU apdu) {
        byte[] buffer = apdu.getBuffer();
        buffer[0] = (byte) (balance >> (short) 8);
        buffer[1] = (byte) (balance & (short) 0x00FF);
        //apdu.setOutgoingLength((byte) 2);        
        //apdu.sendBytes((short) 0, (short) 2);
        apdu.setOutgoingAndSend((short)0, (short)2);
    }

    private void charge(APDU apdu) {        
        byte[] buffer = apdu.getBuffer();
        byte numBytes = buffer[ISO7816.OFFSET_LC];
        byte byteRead = (byte) (apdu.setIncomingAndReceive());

        if ((numBytes != 2) || (byteRead != 2)) {
            ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
        }

        short chargeAmount = (short) ((short) (buffer[ISO7816.OFFSET_CDATA] << (short) 8) | (buffer[ISO7816.OFFSET_CDATA + 1]));

        if ((chargeAmount > MAX_BALANCE) || (chargeAmount < (short) 0)) {
            ISOException.throwIt(SW_INVALID_TRANSACTION_AMOUNT);
        }

        if ((short) (balance - chargeAmount) < 0) {
            ISOException.throwIt(SW_MIN_BALANCE_EXCEEDED);
        }
        JCSystem.beginTransaction();
        balance = (short) (balance - chargeAmount);
        JCSystem.commitTransaction();
    }

enter image description here


Solution

  • constructor method and my other method is here. between the "beginTransaction" and "commitTransaction" code, goto EEPROM persitent data. But it run only classic applet(java card api 3.0), it doesnt run Extendet Applet.

     private Akbil_Classic(byte[] bArray, short bOffset, byte bLength) {
                memory = new byte[SIZE_MEMORY];
        }
    
    private void charge(APDU apdu) {        
        byte[] buffer = apdu.getBuffer();
        byte numBytes = buffer[ISO7816.OFFSET_LC];
        byte byteRead = (byte) (apdu.setIncomingAndReceive());
    
        if ((numBytes != 2) || (byteRead != 2)) {
            ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
        }
    
        short chargeAmount = (short) ((short) (buffer[ISO7816.OFFSET_CDATA] << (short) 8) | (buffer[ISO7816.OFFSET_CDATA + 1]));
    
        if ((chargeAmount > MAX_BALANCE) || (chargeAmount < (short) 0)) {
            ISOException.throwIt(SW_INVALID_TRANSACTION_AMOUNT);
        }
    
        if ((short) (balance + chargeAmount) > MAX_BALANCE) {
            ISOException.throwIt(SW_MAX_BALANCE_EXCEEDED);
        }
        JCSystem.beginTransaction();
        balance = (short) (balance - chargeAmount);
        JCSystem.commitTransaction();
    }