FileDocCategorySizeDatePackage
Wallet.javaAPI DocJava Card8687Wed Mar 22 21:07:22 GMT 2006com.sun.javacard.samples.wallet

Wallet

public class Wallet extends Applet

Fields Summary
static final byte
Wallet_CLA
static final byte
VERIFY
static final byte
CREDIT
static final byte
DEBIT
static final byte
GET_BALANCE
static final short
MAX_BALANCE
static final byte
MAX_TRANSACTION_AMOUNT
static final byte
PIN_TRY_LIMIT
static final byte
MAX_PIN_SIZE
static final short
SW_VERIFICATION_FAILED
static final short
SW_PIN_VERIFICATION_REQUIRED
static final short
SW_INVALID_TRANSACTION_AMOUNT
static final short
SW_EXCEED_MAXIMUM_BALANCE
static final short
SW_NEGATIVE_BALANCE
OwnerPIN
pin
short
balance
Constructors Summary
private Wallet(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
        
        // The installation parameters contain the PIN
        // initialization value
        pin.update(bArray, (short)(bOffset+1), aLen);
        register();
    
    
Methods Summary
private voidcredit(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);
    
    
private voiddebit(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);
    
    
public voiddeselect()

        
        // reset the pin value
        pin.reset();
        
    
private voidgetBalance(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)2);
    
    
public static voidinstall(byte[] bArray, short bOffset, byte bLength)

        // create a Wallet applet instance
        new Wallet(bArray, bOffset, bLength);
    
public voidprocess(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;
        default:
            ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
        }
        
    
public booleanselect()

        
        // The applet declines to be selected
        // if the pin is blocked.
        if ( pin.getTriesRemaining() == 0 )
           return false;
        
        return true;
        
    
private voidverify(APDU apdu)

        
        byte[] buffer = apdu.getBuffer();
        // 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);