Reputation: 17016
I am using JavaCard 2.2.2.
The following program is not working,because, ISO7816.SW_PIN_REQUIRED
is not finding any library to resolve itself.
How can I replace ISO7816.SW_PIN_REQUIRED
with any other constant to make the program to run?
package monpackage;
import javacard.framework.*;
//import javacardx.framework.*;
public class Wallet 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 Deposit = (byte) 0x10;
final static byte Debit = (byte) 0x20;
final static byte Balance = (byte) 0x30;
final static byte Validate = (byte) 0x40;
// maximum number of incorrect tries before the
// PIN is blocked
final static byte PinTryLimit =(byte)0x03;
// maximum size PIN
final static byte MaxPinSize =(byte)0x04;
// status word (SW1-SW2) to signal that the
// balance becomes negative;
final static short SW_NEGATIVE_BALANCE = (short)0x6910;
/* instance variables declaration */
OwnerPIN pin;
byte balance;
byte buffer[]; // APDU buffer
private Wallet()
{
// It is good programming practice to allocate
// all the memory that an applet needs during
// its lifetime inside the constructor
pin = new OwnerPIN(PinTryLimit, MaxPinSize);
balance = 0;
register();
} // end of the constructor
public static void install(APDU apdu)
{
// create a Wallet applet instance
new Wallet();
} // end of install method
public boolean select()
{
// reset validation flag in the PIN object to
// false
pin.reset();
// returns true to JCRE to indicate that the
// applet is ready to accept incoming APDUs.
return true;
}// end of select method
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
buffer = apdu.getBuffer();
// verify that if the applet can accept this
// APDU message
if (buffer[ISO7816.OFFSET_CLA] !== Wallet_CLA)
{
ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
}
switch (buffer[ISO7816.OFFSET_INS])
{
case Balance: getBalance(apdu); return;
case Debit: debit(apdu); return;
case Deposit: deposit(apdu);return;
case Validate: validate(apdu);return
default: ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
}
} // end of process method
private void deposit(APDU apdu) {
// access authentication
if ( ! pin.isValidated() )
ISOException.throwIt (ISO7816.SW_PIN_REQUIRED);
// Lc byte denotes the number of bytes in the
// data field of the comamnd APDU
byte numBytes = (byte) (buffer[ISO7816.OFFSET_LC]);
// indicate that this APDU has incoming data and
// receive data starting from the offset
// ISO.OFFSET_CDATA
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 (byteRead != 1)
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
// increase the balance by the amount specified
// in the data field of the command APDU.
balance = (byte)
(balance + buffer[ISO7816.OFFSET_CDATA]);
// return successfully
return;
} // end of deposit method
private void debit(APDU apdu) {
// access authentication
if ( ! pin.isValidated() )
ISOException.throwIt(ISO7816.SW_PIN_REQUIRED);
byte numBytes = (byte)(buffer[ISO7816.OFFSET_LC]);
byte byteRead =
(byte)(apdu.setIncomingAndReceive());
if (byteRead != 1)
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
// balance can not be negative
if ( ( balance - buffer[ISO7816.OFFSET_CDATA]) < 0 )
ISOException.throwIt(SW_NEGATIVE_BALANCE);
balance = (byte)
(balance - buffer[ISO7816.OFFSET_CDATA]);
} // end of debit method
private void getBalance(APDU apdu) {
// access authentication
if ( ! pin.isValidated() )
ISOException.throwIt(ISO7816.SW_PIN_REQUIRED);
// 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
apdu.setOutgoing();
//indicate the number of bytes in the data field
apdu.setOutgoingLength((byte)1);
// move the data into the APDU buffer starting
// at offset 0
buffer[0] = balance;
// send 1 byte of data at offset 0 in the APDU
// buffer
apdu.sendBytes((short)0, (short)1);
} // end of getBalance method
private void validate(APDU apdu) {
// retrieve the PIN data which requires to be
// valid ated. The user interface data is
// stored in the data field of the APDU
byte byteRead =
(byte)(apdu.setIncomingAndReceive());
// validate user interface and set the
// validation flag in the user interface
// object to be true if the validation.
// succeeds. If user interface validation
// fails, PinException would be thrown from
// the pin.check() method.
pin.check(buffer, ISO7816.OFFSET_CDATA, byteRead);
} // end of validate method
} // end of class Wallet
Upvotes: 0
Views: 423
Reputation: 6136
Check out Java Card 2.2.2 API Specifications - ISO7816 Interface AGAIN. :)
You will see there is no field named SW_PIN_REQUIRED
in this interface. you can simply add the following line in the constant declaration section of your program, and then replace ISO.SW_PIN_REQUIRED
with SW_PIN_REQUIRED
.
final static short SW_PIN_REQUIRED = 0x6968
Moreover you can use the following already defined fields of ISO7816
instead of the undefined field SW_PIN_REQUIRED
:
ISO7816.SW_CONDITIONS_NOT_SATISFIED
or
ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED
BTW these are some special short values that are defined in specifications and you are not forced to use the same values in your program. for example ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED
will replace with 0x6982
(As mentioned in the API spec) in the compilation time by compiler, and you will see this value when you are communicating with your applet on the card. So you can simply define your special status words instead of using these values (NOT RECOMMENDED).
Edit: (Thanks to Mr Bodewes)
As Mr Bodewes said in the comments, we are strongly recommended to keep to the possible status word ranges that are defined in ISO/IEC 7816 - 3 Standard and 4. If we don't we may run into trouble, especially for T=0 (byte oriented contact mode) operation.
From the 7816-3: "If the value is '6X' or '9X', except for '60', it is a SW1 byte. It requests no action on data transfer. The interface device shall wait for a character conveying a SW2 byte. There is no restriction on SW2 value.". So it needs to be 6X or 9X to be compatible with T=0.
Upvotes: 4