Our Online Store have the new products: RFID antenna board. Currently it can work with JC10M24R and JCOP4 card chips.
Compared with normal cards, the antenna board module has a smaller size and fixed holes, which is easy to integrate in the IOT(Internet Of Things) project.

[resolved]GET_BALANCE return 6E 00 or 6F 00

JavaCard Applet Development Related Questions and Answers.
andromeda92
Posts: 38
Joined: Tue Aug 18, 2020 6:08 pm
Points :320
Contact:

[resolved]GET_BALANCE return 6E 00 or 6F 00

Post by andromeda92 » Mon Aug 31, 2020 5:28 pm

Hi, i have an applet, running on simulator or on real card, method getbalance return always 6E00

veryfy pin i ok
credit is ok
debit is ok
change is ok

but getbalance return 6E00
the code:

Code: Select all

package PackageWallet ;

import javacard.framework.APDU;
import javacard.framework.Applet;
import javacard.framework.ISO7816;
import javacard.framework.ISOException;
import javacard.framework.OwnerPIN;



public class AppletWallet extends Applet {
 
    /* constants declaration */
    
    // code of CLA byte in the command APDU header
    final static byte Wallet_CLA =(byte)0xB0;
    
    // codes of INS byte in the command APDU header
    final static byte VERIFY = (byte) 0x20;
    final static byte CREDIT = (byte) 0x30;
    final static byte DEBIT = (byte) 0x40;
    final static byte GET_BALANCE = (byte) 0x50;
    final static byte CHANGE = (byte) 0x60;
    
    // maximum balance
    final static short MAX_BALANCE = 0x7FFF;
    // maximum transaction amount
    final static byte MAX_TRANSACTION_AMOUNT = 127;
    
    // maximum number of incorrect tries before the
    // PIN is blocked
    final static byte PIN_TRY_LIMIT =(byte)0x03;
    // maximum size PIN
    final static byte MAX_PIN_SIZE =(byte)0x08;
    final static byte MIN_PIN_SIZE = (byte)0x04;
    
    // signal that the PIN verification failed
    final static short SW_VERIFICATION_FAILED =
    0x6300;
    // signal the the PIN validation is required
    // for a credit or a debit transaction
    final static short SW_PIN_VERIFICATION_REQUIRED =
                                            0x6301;
	// pin is locked
	final static short SW_CARD_IS_LOCKED = 0x6304; 
	final static short SW_NEW_PIN_TOO_LONG = 0x6307;
	final static short SW_NEW_PIN_TOO_SHORT = 0x6308;  
	                                        
    // signal invalid transaction amount
    // amount > MAX_TRANSACTION_AMOUNT or amount < 0
    final static short SW_INVALID_TRANSACTION_AMOUNT = 0x6A83;
    
    // signal that the balance exceed the maximum
    final static short SW_EXCEED_MAXIMUM_BALANCE = 0x6A84;
    // signal the the balance becomes negative
    final static short SW_NEGATIVE_BALANCE = 0x6A85;
    
    /* instance variables declaration */
    OwnerPIN pin;
    short balance;
    
    private AppletWallet (byte[] bArray,short bOffset,byte bLength) {
      
        // It is good programming practice to allocate
        // all the memory that an applet needs during
        // its lifetime inside the constructor
        pin = new OwnerPIN(PIN_TRY_LIMIT,   MAX_PIN_SIZE);
        
        byte iLen = bArray[bOffset]; // aid length
        bOffset = (short) (bOffset+iLen+1);
        byte cLen = bArray[bOffset]; // info length
        bOffset = (short) (bOffset+cLen+1);
        byte aLen = bArray[bOffset]; // applet data length
        
		pin = new OwnerPIN(PIN_TRY_LIMIT, MAX_PIN_SIZE);
		pin.update(bArray, (short)(bOffset + 1), aLen);
		// Above command causes error.
				
		register();
    
    } // end of the constructor
    
    public static void install(byte[] bArray, short bOffset, byte bLength) {
        // create a Wallet applet instance
        new AppletWallet(bArray, bOffset, bLength);
    } // end of install method
    
    public boolean select() {
        
        // The applet declines to be selected
        // if the pin is blocked.
        if ( pin.getTriesRemaining() == 0 )
           return false;
        
        return true;
        
    }// end of select method
    
    public void deselect() {
        
        // reset the pin value
        pin.reset();
        
    }
    	
  
    public void process(APDU apdu) {
        
        // APDU object carries a byte array (buffer) to
        // transfer incoming and outgoing APDU header
        // and data bytes between card and CAD
        
        // At this point, only the first header bytes
        // [CLA, INS, P1, P2, P3] are available in
        // the APDU buffer.
        // The interface javacard.framework.ISO7816
        // declares constants to denote the offset of
        // these bytes in the APDU buffer
        
        byte[] buffer = apdu.getBuffer();
        // check SELECT APDU command
       
        if (apdu.isISOInterindustryCLA()) {
            if (buffer[ISO7816.OFFSET_INS] == (byte)(0xA4)) {
                return;
            } else {
                ISOException.throwIt (ISO7816.SW_CLA_NOT_SUPPORTED);
            }
        }
            
        // verify the reset of commands have the
        // correct CLA byte, which specifies the
        // command structure
        if (buffer[ISO7816.OFFSET_CLA] != Wallet_CLA)
            ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
       
		switch (buffer[ISO7816.OFFSET_INS]) {
			case GET_BALANCE:
				getBalance(apdu);
				return;
			case DEBIT:
				debit(apdu);
				return;
			case CREDIT:
				credit(apdu);
				return;
			case VERIFY:
				verify(apdu);
				return;
			case CHANGE:
				change(apdu);
				return;
			default:
			ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
		}
        
    }   // end of process method
    
    private void credit(APDU apdu) {
    
        // access authentication
        if ( ! pin.isValidated() )
            ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
        
        byte[] buffer = apdu.getBuffer();
        
        // Lc byte denotes the number of bytes in the
        // data field of the command APDU
        byte numBytes = buffer[ISO7816.OFFSET_LC];
        
        // indicate that this APDU has incoming data
        // and receive data starting from the offset
        // ISO7816.OFFSET_CDATA following the 5 header
        // bytes.
        byte byteRead =
            (byte)(apdu.setIncomingAndReceive());
        
        // it is an error if the number of data bytes
        // read does not match the number in Lc byte
        if ( ( numBytes != 1 ) || (byteRead != 1) )
            ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
        
        // get the credit amount
        byte creditAmount = buffer[ISO7816.OFFSET_CDATA];
        
        // check the credit amount
        if ( ( creditAmount > MAX_TRANSACTION_AMOUNT)
             || ( creditAmount < 0 ) )
            ISOException.throwIt(SW_INVALID_TRANSACTION_AMOUNT);
        
        // check the new balance
        if ( (short)( balance + creditAmount)  > MAX_BALANCE )
           ISOException.throwIt(SW_EXCEED_MAXIMUM_BALANCE);
        
        // credit the amount
        balance = (short)(balance + creditAmount);
    
    } // end of deposit method
    
    private void debit(APDU apdu) {
    
        // access authentication
        if ( ! pin.isValidated() )
            ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
        
        byte[] buffer = apdu.getBuffer();
        
        byte numBytes =
            (byte)(buffer[ISO7816.OFFSET_LC]);
        
        byte byteRead =
            (byte)(apdu.setIncomingAndReceive());
        
        if ( ( numBytes != 1 ) || (byteRead != 1) )
           ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
        
        // get debit amount
        byte debitAmount = buffer[ISO7816.OFFSET_CDATA];
        
        // check debit amount
        if ( ( debitAmount > MAX_TRANSACTION_AMOUNT)
             ||  ( debitAmount < 0 ) )
           ISOException.throwIt(SW_INVALID_TRANSACTION_AMOUNT);
        
        // check the new balance
        if ( (short)( balance - debitAmount ) < (short)0 )
             ISOException.throwIt(SW_NEGATIVE_BALANCE);
        
        balance = (short) (balance - debitAmount);
    
    } // end of debit method
    
    private void getBalance(APDU apdu) {
        
        byte[] buffer = apdu.getBuffer();
        
        // inform system that the applet has finished
        // processing the command and the system should
        // now prepare to construct a response APDU
        // which contains data field
        short le = apdu.setOutgoing();
        
        if ( le < 2 )
           ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
        
        //informs the CAD the actual number of bytes
        //returned
        apdu.setOutgoingLength((byte)2);
        
        // move the balance data into the APDU buffer
        // starting at the offset 0
        buffer[0] = (byte)(balance >> 8);
        buffer[1] = (byte)(balance & 0xFF);
        
        // send the 2-byte balance at the offset
        // 0 in the apdu buffer
        apdu.sendBytes((short)0, (short)4);
    
    } // end of getBalance method
    
    private void verify(APDU apdu) {
        
        byte[] buffer = apdu.getBuffer();
         if(pin.getTriesRemaining() == (byte)0)
           ISOException.throwIt(SW_CARD_IS_LOCKED);
           
        // retrieve the PIN data for validation.
        byte byteRead = (byte)(apdu.setIncomingAndReceive());
        
        // check pin
        // the PIN data is read into the APDU buffer
        // at the offset ISO7816.OFFSET_CDATA
        // the PIN data length = byteRead
        if ( pin.check(buffer, ISO7816.OFFSET_CDATA,
            byteRead) == false )
            ISOException.throwIt(SW_VERIFICATION_FAILED);
        
    } // end of validate method
    
    private void change(APDU apdu) {
        
       byte[] buffer = apdu.getBuffer();
       if(pin.getTriesRemaining() == (byte)0)
           ISOException.throwIt(SW_CARD_IS_LOCKED);
           
       if ( ! pin.isValidated() )
           ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
           
        // retrieve the PIN data for validation.
        byte byteRead = (byte)(apdu.setIncomingAndReceive());
        if(byteRead > MAX_PIN_SIZE)
           ISOException.throwIt(SW_NEW_PIN_TOO_LONG);
           
       if(byteRead < MIN_PIN_SIZE)
           ISOException.throwIt(SW_NEW_PIN_TOO_SHORT);
        
       pin.update(buffer, (short) ISO7816.OFFSET_CDATA, (byte)byteRead); 
        
    } // end of validate method
} // end of class Wallet
i use java card J2A040, JCD2.2.2
i don't undertand the problem.
Thanks for your help.
Last edited by andromeda92 on Mon Aug 31, 2020 6:08 pm, edited 1 time in total.

andromeda92
Posts: 38
Joined: Tue Aug 18, 2020 6:08 pm
Points :320
Contact:

Re: GET_BALANCE return 6E 00 or 6F 00

Post by andromeda92 » Mon Aug 31, 2020 6:08 pm

resolved, i have replaced this line

apdu.sendBytes((short)0, (short)4);

by

apdu.sendBytes((short)0, (short)2);

abuhelweh
Posts: 6
Joined: Wed Feb 17, 2021 4:17 pm
Points :100
Contact:

Re: [resolved]GET_BALANCE return 6E 00 or 6F 00

Post by abuhelweh » Tue Mar 23, 2021 4:16 am

Can you please share the APDU commands used to test this applet? I tried to debug but its not reaching the process method

andromeda92
Posts: 38
Joined: Tue Aug 18, 2020 6:08 pm
Points :320
Contact:

Re: [resolved]GET_BALANCE return 6E 00 or 6F 00

Post by andromeda92 » Sun Apr 25, 2021 12:35 pm

For example, for send sendpin the command is
for credit is 8030000001
get balance 8050000002
reset balance 8004000000
...
all depend to your program

faulknernolan
Posts: 1
Joined: Thu Jun 24, 2021 5:25 am
Points :12
Contact:

Re: [resolved]GET_BALANCE return 6E 00 or 6F 00

Post by faulknernolan » Thu Jun 24, 2021 5:32 am

can i get your code?
moto x3m

andromeda92
Posts: 38
Joined: Tue Aug 18, 2020 6:08 pm
Points :320
Contact:

Re: [resolved]GET_BALANCE return 6E 00 or 6F 00

Post by andromeda92 » Mon Jul 19, 2021 9:50 am

the applet is developed with java card os but to test the applet I use eclipse with javacard and globalplatform. It's a whole environment, you have to install javacard under eclipse as well as globalplatform, swing, awt for the gui part. The principle is to send the INS command of the applet, and the card returns the response that must be analyzed in the client.


The source code of client with eclipse and javacard:
https://mega.nz/file/PB9SRZjL#tz5Jm5coM ... bCjsLfFv9M
You do not have the required permissions to view the files attached to this post. Please login first.

Post Reply Previous topicNext topic

Who is online

Users browsing this forum: Bing [Bot], Google [Bot] and 58 guests

JavaCard OS : Disclaimer