Page 1 of 1

What is the alternative of ISO7816.SW_PIN_REQUIRED in JavaCard 2.2.2?

Posted: Fri Jun 12, 2015 5:59 am
by Robert
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?

Code: Select all

package testpackage;

import javacard.framework.*;

public class test 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 test()
    {
        // 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 test();
    }

    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;
    }

    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);
             break;
        }
    }

    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;
        }

    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);
        }
    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 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);
        }
    }

Re: What is the alternative of ISO7816.SW_PIN_REQUIRED in JavaCard 2.2.2?

Posted: Fri Jun 12, 2015 7:07 am
by Tolice
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

Code: Select all

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).

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.