2 Replies Latest reply: Jan 15, 2013 1:09 PM by 984980 RSS

    Verify user pin on a smart card & load a cap file on a card (with eclipse)

    984980
      I have been able install JCWDE (Java card development Kit) successfully on eclipse.Basically all I need to do is verify user pin on a smart card.As in first set a pin and then verify it.

      To begin with I have referred many tutorials (here: http://www.javaworld.com/jw-07-1999/jw-07-javacard.html?page=1) and implemented the wallet code in eclipse.I have the cap file generated and the scripts generated.I am not sure how to load it on the smart card with eclipse.
      I tried to deploy the cap file but it keeps saying connected.Also when we initiate the applet I get the same result.

      output:
      Java Card 2.2.2 APDU Tool, Version 1.3
      Copyright 2005 Sun Microsystems, Inc. All rights reserved. Use is subject to license terms.
      Opening connection to localhost on port 9032.
      Connected.


      I have also tried : http://www.cs.ru.nl/E.Poll/hw/practical.html ........ but no luck.



      I have the wallet.cap ,wallet.exp ,wallet.jca ,wallet.opt create.script, select,cap-download.scripts files already generated in eclipse.

      How does a successfully implemented applet code on a smart card work?How does this wallet code work if it is successfully implemented ? Does it have like some GUI which prompts the user to enter the pin?

      Wallet code for reference :


      package com.sun.javacard.samples.wallet;
      import javacard.framework.*;

      public class Wallet extends Applet {

      /* constants declaration */

      // code of CLA byte in the command APDU header
      final static byte Wallet_CLA =(byte)0x80;

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

      // 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 blockedd
      final static byte PIN_TRY_LIMIT =(byte)0x03;
      // maximum size PIN
      final static byte MAX_PIN_SIZE =(byte)0x08;

      // 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;
      // 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 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();

      } // end of the constructor

      public static void install(byte[] bArray, short bOffset, byte bLength) {
      // create a Wallet applet instance
      new Wallet(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;
      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)2);

      } // end of getBalance method

      private void verify(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);

      } // end of validate method
      } // end of class Wallet



      Any help on this would highly appreciated !! :)
        • 1. Re: Verify user pin on a smart card & load a cap file on a card (with eclipse)
          Hana Bizhani
          Hi,

          First of all about
          output:
          Java Card 2.2.2 APDU Tool, Version 1.3
          Copyright 2005 Sun Microsystems, Inc. All rights reserved. Use is subject to license terms.
          Opening connection to localhost on port 9032.
          Connected.
          I'm not sure, but I think you try to load an applet which is already installed before, on the simulator. So, try to delete the simulator first and then deploy your Cap file and load and install it on the card.

          Second,As you can see from here :
          // The installation parameters contain the PIN
          // initialization value
          pin.update(bArray, (short)(bOffset+1), aLen);
          you should send pin initialization value when you are installing the applet, I mean you should send the pin default value as the data byte of install APDU command.

          Regards,
          Hana
          • 2. Re: Verify user pin on a smart card & load a cap file on a card (with eclipse)
            984980
            Hi,



            Thanks a lot for reply.But I am not sure as to how can I delete the simulator.

            All I want to do is write a pin on the smart card and verify it.But I am not being able to deploy the cap file or initiate the applet.

            Also for passing the pin correct me if I am wrong........ according to what you said and what I have understood


            If the code is like this :

            public static void install(byte[] bArray, short bOffset, byte bLength) {
            // create a Wallet applet instance
            new Wallet(bArray, bOffset, bLength);
            } // end of install method


            byte aLen = bArray[bOffset]; // applet data length

            // The installation parameters contain the PIN
            // initialization value
            pin.update(bArray, (short)(bOffset+1), aLen);


            Lets say my pin is : 1234

            then I would pass it here.....

            new Wallet(bArray, 1234, bLength);