By Ed Ort, Release 2.1.1, January 2001
This section continues the Processing Requests discussion started in Part 1 of this article.
Wallet
Applet Wallet
Applet Wallet
Applet The last steps to processing the request include:
Debit an Amount from the Current Balance
The debit
method in the Wallet
applet debits an amount from the current balance. As is the case for the credit
method, the debit
method is called with one parameter: an APDU object. The APDU object encapsulates an APDU buffer that contains the DEBIT
command APDU. The amount to be debited from the current balance is in the data field of the APDU.
private void debit(APDU apdu) {
The code in the debit
method is similar to that in the credit
method. Both methods:
MAX_TRANSACTION_AMOUNT
constant, or is less than 0For more details about these steps, see Credit an Amount to the Current Balance.
Where debit
differs from credit
is that the data in the APDU reflects the amount to be debited from the current balance (as opposed to credited to the balance). After the debit
method performs the steps above, it subtracts the debit amount from the current balance and checks to ensure that the new balance isn't less than 0. Here is body of the debit
method:
// 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
As is the case for credit
method, the JCRE indicates successful processing of the command APDU by sending a response APDU to the host application that contains the status word value 0x9000.
The getBalance
method in the Wallet
applet returns the value of the current balance. The method is called with one parameter: an APDU object. The APDU object encapsulates an APDU buffer that contains the GET BALANCE
command APDU. The value of the current balance is returned in the data field of the GET BALANCE
response APDU.
private void getBalance(APDU apdu) {
The getBalance
method first gets a reference to the APDU buffer (for more details, see Get a Reference to the APDU buffer):
byte buffer[] = apdu.getBuffer();
Unlike the credit
and debit
methods that read incoming data in a command APDU and then process it, the getBalance
method does its processing (that is, gets the current balance) and then writes data for inclusion in a response APDU. It does this by first calling the APDU method setOutgoing
. This tells the JCRE that the Java Card applet wants to send a response. The setOutgoing
method doesn't send any data. It sets the JCRE to data-send mode. It also accesses and returns the value in the Le byte of the command APDU. As illustrated in APDU Formats, the Le byte indicates the maximum number of bytes expected in response to the command. Notice that the Le byte value for the GET BALANCE
command should be 2. The getBalance
method checks the Le value; if the value is not 2, the method throws an exception with a constant that is returned in the status word of the response APDU:
// 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);
getbalance
then calls the APDU method setOutgoingLength
to specifiy how many bytes of data are actually in the response -- here it's two bytes. The length is specified as a parameter to setOutgoingLength
:
//informs the CAD the actual number of bytes
//returned
apdu.setOutgoingLength((byte)2);
Then getBalance
moves the balance amount into the first two bytes of the APDU buffer. Notice the shift and bitwise "and" operations performed on the balance value before it is moved into the buffer; these operations correctly produce the values for the two bytes.
// move the balance data into the APDU buffer
// starting at the offset 0
buffer[0] = (byte)(balance >> 8);
buffer[1] = (byte)(balance & 0xFF);
An alternative technique for moving the balance data into the APDU buffer is to use the following method call:
Util.setShort(buffer, (short)0, balance);
setShort
is a method defined in the javacard.framework.Util
class. It moves a short value (here, the balance) as two successive bytes at the specified offset (offset 0), into a byte array (the APDU buffer).
The last step in the process is to send the data by calling the APDU method sendBytes
. The sendBytes
method accepts two parameters: the offset into the APDU buffer where the data begins, and the length of the data. Here, the getBalance
method sends the two bytes in the APDU buffer starting at offset 0:
// send the 2-byte balance at the offset
// 0 in the apdu buffer
apdu.sendBytes((short)0, (short)2);
} // end of getBalance method
As is the case for the credit
and debit
methods, the JCRE indicates successful processing of the command APDU by sending a status word value of 0x9000 in the response APDU to the host application.
The verify
method in the Wallet
applet validates the PIN. The method is called with one parameter: an APDU object. The APDU object encapsulates an APDU buffer that contains the VERIFY
command APDU. The PIN to be validated is in the data field of the APDU.
private void verify(APDU apdu) {
The verify
method first gets a reference to the APDU buffer (for more details, see Get a Reference to the APDU buffer):
byte buffer[] = apdu.getBuffer();
verify
then calls the APDU method setIncomingAndReceive
to get the PIN to be validated from the command APDU and put it in the APDU buffer:
// retrieve the PIN data for validation.
byte byteRead =
(byte)(apdu.setIncomingAndReceive());
verify
then checks the PIN by calling the OwnerPIN
method check
:
// 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
} // end of class Wallet
Notice that the check
method is called with three parameters:
OFFSET_CDATA
is used as the indexThe check
method checks the PIN in the APDU buffer against a PIN established when the applet was installed. If the values match, the check
method returns a true
value. It also sets a flag to indicate that the PIN is validated, and resets a try counter to the maximum value for the applet. Recall that for the Wallet
applet the maximum number of tries as set by PIN_TRY_LIMIT
is 3. If the values do not match, check
returns a false
value. In that case, it throws an exception with a constant that is returned in the status word of the response APDU. It also decrements the try counter. If the value of the try counter is 0, check
blocks the PIN; this means that no further processing can be performed by the applet for this user.
Java Card Classes Used in the Wallet
Applet
Class | Purpose |
---|---|
APDU |
Encapsulates the Application Identifier (AID) associated with an applet. |
Applet |
An abstract class that defines an applet in Java Card. |
ISOException |
Encapsulates an ISO7816 status word as its reason code. |
OwnerPIN |
Encapsulates PIN-related data and operations. |
Java Card Methods Used in the Wallet
Applet
The following Java Card methods are used in the Wallet
applet.
javacard.framework.APDU
Methods Used in the Wallet
Applet
Method Summary | |
---|---|
public byte |
getBuffer()
Returns the APDU buffer byte array. |
public void |
sendBytes(short bOff, short len) Sends len more bytes from APDU buffer at specified offset bOff . |
public short |
setIncomingAndReceive() The primary receive method; gets as many bytes as will fit in the APDU buffer without buffer overflow. |
public short |
setOutgoing() Sets the data transfer direction to outbound and obtains the expected length of the response. |
public void |
setOutgoingLength(short len) Sets the actual length of the response data. |
javacard.framework.Applet
Methods Used in the Wallet
Applet
Method Summary | |
---|---|
public void |
deselect() Called by the JCRE to inform the currently selected applet that another (or the same) applet will be selected. |
public static void |
install (byte[] bArray, short bOffset, byte length) To create an instance of the Applet subclass, the JCRE will call this static method first. |
public abstract void |
process (APDU apdu) Called by the JCRE to process an incoming APDU command. |
protected final void |
register() Used by an applet to register this applet instance with the JCRE and to assign an AID to the applet instance. |
public boolean |
select() Called by the JCRE to inform an applet that it has been selected. |
javacard.framework.OwnerPIN
Methods Used in the Wallet
Applet
Method Summary | |
---|---|
public boolean |
check(byte[] pin, short offset, byte length) Compares an OwnerPIN object against a PIN. |
public boolean |
getTriesRemaining() Returns the number of times remaining an incorrect PIN can be presented before the PIN is blocked. |
public boolean |
isValidated() Returns true if a valid PIN has been since the last card reset or the last call to the reset method; it returns false otherwise. |
public boolean |
reset() If the validated flag is set, this method resets it. If the validated flag is not set, this method does nothing. |
public void |
update(byte[] pin, short offset, byte length) Sets a new value for the PIN, resets the PIN try counter to the value of the PIN try limit, and resets the validated flag. |
Java Card Interfaces Used in the Wallet
Applet
Interface | Purpose |
---|---|
ISO7816 |
Encapsulates ISO7816 constants frequently used in Java Card applets. |
PIN |
Represents a Personal Identification Number (PIN). |
The following is the format of a command APDU. The SELECT
APDU command is the only APDU command that is standardized on the Java Card platform. The values in the header of a SELECT
APDU command must be as indicated below. The header values for all other command APDU's are applet specific.
Field | Length (bytes) | Purpose |
---|---|---|
CLA (class of instruction) | 1 |
Indicates a category of command and response APDUs. Values are: 0x0 ( SELECT ) 0xB0 ( CREDIT , VERIFY , DEBIT , GET BALANCE ) |
INS (Instruction code) | 1 |
Specifies the instruction of the command. Values are: 0xA4 ( SELECT ) 0x20 ( VERIFY ) 0x30 ( CREDIT ) 0x40 ( DEBIT ) 0x50 ( GET BALANCE ) |
P1 (Instruction Parameter 1) | 1 |
Qualifies the instruction. Values are: 0x04 ( SELECT ) 0x0 ( VERIFY , CREDIT , DEBIT , GET BALANCE ) |
P2 (Instruction Parameter 2) | 1 |
Further qualifies the instruction. Values are: 0x0 ( SELECT , VERIFY , CREDIT , DEBIT , GET BALANCE ) |
Lc | 1 |
Number of bytes present in the data field of the command. Values are: The length of the AID. For the Wallet applet: 0x08 ( SELECT ) The length of the PIN data ( VERIFY ) 1 ( CREDIT , DEBIT ) Not applicable ( GET BALANCE ) |
Data | value of Lc | A sequence of bytes in the data field of the command. Values are: The AID of an applet. For the Wallet applet: 0xF2, 0x34, 0x12, 0x34, 0x56, 0x10, 0x0, 0x1 ( SELECT ) PIN data ( VERIFY ) Credit amount ( CREDIT ) Debit amount ( DEBIT ) Not applicable ( GET BALANCE ) |
Le | 1 |
Maximum number of bytes expected in the data field of the response to the command. Values are: Not applicable ( SELECT , VERIFY , CREDIT , DEBIT ) 2 ( GET BALANCE ) |
The following is the format of a response APDU:
Field | Length (bytes) | Purpose |
---|---|---|
Data | variable length | A sequence of bytes received in the data field of the response. Values are: Not applicable ( SELECT , VERIFY , CREDIT , DEBIT , GET BALANCE ) |
SW1 and SW2 (collectively, called the status word) | 1 (SW1); 1 (SW2) |
Denotes the processing state in the card. 0x9000 successful processing ( SELECT , VERIFY , CREDIT , DEBIT , GET BALANCE ) 0x6999 applet selection failed ( SELECT ) 0x6300 verification failed ( VERIFY ) 0x6301 PIN verification required ( CREDIT , DEBIT ) 0x6A83 Invalid credit or debit amount ( CREDIT , DEBIT ) 0x6A84 Exceeded the maximum amount ( CREDIT ) 0x6A85 Negative balance ( DEBIT ) |
Java Card 2.1.1 Specifications
Java Card Technology Questions and Answers with Zhiqun Chen
About the Author: Ed Ort is a staff member of the Java Developer Connection. He has written extensively about relational database technology and programming languages.