SHARE
TWEET

Untitled

a guest Mar 26th, 2020 110 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /**
  2.  * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
  3.  *
  4.  */
  5.  
  6. /*
  7.  */
  8.  
  9. /*
  10.  * @(#)Wallet.java  1.11 06/01/03
  11.  */
  12.  
  13. package com.oracle.jcclassic.samples.wallet;
  14.  
  15. import javacard.framework.APDU;
  16. import javacard.framework.Applet;
  17. import javacard.framework.ISO7816;
  18. import javacard.framework.ISOException;
  19. import javacard.framework.OwnerPIN;
  20.  
  21. public class Wallet extends Applet {
  22.  
  23.     /* constants declaration */
  24.  
  25.     // code of CLA byte in the command APDU header
  26.     final static byte Wallet_CLA = (byte) 0x80;
  27.  
  28.     // codes of INS byte in the command APDU header
  29.     final static byte VERIFY = (byte) 0x20;
  30.     final static byte CREDIT = (byte) 0x30;
  31.     final static byte DEBIT = (byte) 0x40;
  32.     final static byte GET_BALANCE = (byte) 0x50;
  33.  
  34.     // maximum balance
  35.     final static short MAX_BALANCE = 0x7FFF;
  36.     // maximum transaction amount
  37.     final static byte MAX_TRANSACTION_AMOUNT = 127;
  38.  
  39.     // maximum number of incorrect tries before the
  40.     // PIN is blocked
  41.     final static byte PIN_TRY_LIMIT = (byte) 0x03;
  42.     // maximum size PIN
  43.     final static byte MAX_PIN_SIZE = (byte) 0x08;
  44.  
  45.     // signal that the PIN verification failed
  46.     final static short SW_VERIFICATION_FAILED = 0x6300;
  47.     // signal the the PIN validation is required
  48.     // for a credit or a debit transaction
  49.     final static short SW_PIN_VERIFICATION_REQUIRED = 0x6301;
  50.     // signal invalid transaction amount
  51.     // amount > MAX_TRANSACTION_AMOUNT or amount < 0
  52.     final static short SW_INVALID_TRANSACTION_AMOUNT = 0x6A83;
  53.  
  54.     // signal that the balance exceed the maximum
  55.     final static short SW_EXCEED_MAXIMUM_BALANCE = 0x6A84;
  56.     // signal the the balance becomes negative
  57.     final static short SW_NEGATIVE_BALANCE = 0x6A85;
  58.  
  59.     /* instance variables declaration */
  60.     OwnerPIN pin;
  61.     short balance;
  62.  
  63.     private Wallet(byte[] bArray, short bOffset, byte bLength) {
  64.  
  65.         // It is good programming practice to allocate
  66.         // all the memory that an applet needs during
  67.         // its lifetime inside the constructor
  68.         pin = new OwnerPIN(PIN_TRY_LIMIT, MAX_PIN_SIZE);
  69.  
  70.         byte iLen = bArray[bOffset]; // aid length
  71.         bOffset = (short) (bOffset + iLen + 1);
  72.         byte cLen = bArray[bOffset]; // info length
  73.         bOffset = (short) (bOffset + cLen + 1);
  74.         byte aLen = bArray[bOffset]; // applet data length
  75.  
  76.         // The installation parameters contain the PIN
  77.         // initialization value
  78.         pin.update(bArray, (short) (bOffset + 1), aLen);
  79.         register();
  80.  
  81.     } // end of the constructor
  82.  
  83.     public static void install(byte[] bArray, short bOffset, byte bLength) {
  84.         // create a Wallet applet instance
  85.         new Wallet(bArray, bOffset, bLength);
  86.     } // end of install method
  87.  
  88.     @Override
  89.     public boolean select() {
  90.  
  91.         // The applet declines to be selected
  92.         // if the pin is blocked.
  93.         if (pin.getTriesRemaining() == 0) {
  94.             return false;
  95.         }
  96.  
  97.         return true;
  98.  
  99.     }// end of select method
  100.  
  101.     @Override
  102.     public void deselect() {
  103.  
  104.         // reset the pin value
  105.         pin.reset();
  106.  
  107.     }
  108.  
  109.     @Override
  110.     public void process(APDU apdu) {
  111.  
  112.         // APDU object carries a byte array (buffer) to
  113.         // transfer incoming and outgoing APDU header
  114.         // and data bytes between card and CAD
  115.  
  116.         // At this point, only the first header bytes
  117.         // [CLA, INS, P1, P2, P3] are available in
  118.         // the APDU buffer.
  119.         // The interface javacard.framework.ISO7816
  120.         // declares constants to denote the offset of
  121.         // these bytes in the APDU buffer
  122.  
  123.         byte[] buffer = apdu.getBuffer();
  124.         // check SELECT APDU command
  125.  
  126.         if (apdu.isISOInterindustryCLA()) {
  127.             if (buffer[ISO7816.OFFSET_INS] == (byte) (0xA4)) {
  128.                 return;
  129.             }
  130.             ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
  131.         }
  132.  
  133.         // verify the reset of commands have the
  134.         // correct CLA byte, which specifies the
  135.         // command structure
  136.         if (buffer[ISO7816.OFFSET_CLA] != Wallet_CLA) {
  137.             ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
  138.         }
  139.  
  140.         switch (buffer[ISO7816.OFFSET_INS]) {
  141.             case GET_BALANCE:
  142.                 getBalance(apdu);
  143.                 return;
  144.             case DEBIT:
  145.                 debit(apdu);
  146.                 return;
  147.             case CREDIT:
  148.                 credit(apdu);
  149.                 return;
  150.             case VERIFY:
  151.                 verify(apdu);
  152.                 return;
  153.             default:
  154.                 ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
  155.         }
  156.  
  157.     } // end of process method
  158.  
  159.     private void credit(APDU apdu) {
  160.  
  161.         // access authentication
  162.         if (!pin.isValidated()) {
  163.             ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
  164.         }
  165.  
  166.         byte[] buffer = apdu.getBuffer();
  167.  
  168.         // Lc byte denotes the number of bytes in the
  169.         // data field of the command APDU
  170.         byte numBytes = buffer[ISO7816.OFFSET_LC];
  171.  
  172.         // indicate that this APDU has incoming data
  173.         // and receive data starting from the offset
  174.         // ISO7816.OFFSET_CDATA following the 5 header
  175.         // bytes.
  176.         byte byteRead = (byte) (apdu.setIncomingAndReceive());
  177.  
  178.         // it is an error if the number of data bytes
  179.         // read does not match the number in Lc byte
  180.         if ((numBytes != 1) || (byteRead != 1)) {
  181.             ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
  182.         }
  183.  
  184.         // get the credit amount
  185.         byte creditAmount = buffer[ISO7816.OFFSET_CDATA];
  186.  
  187.         // check the credit amount
  188.         if ((creditAmount > MAX_TRANSACTION_AMOUNT) || (creditAmount < 0)) {
  189.             ISOException.throwIt(SW_INVALID_TRANSACTION_AMOUNT);
  190.         }
  191.  
  192.         // check the new balance
  193.         if ((short) (balance + creditAmount) > MAX_BALANCE) {
  194.             ISOException.throwIt(SW_EXCEED_MAXIMUM_BALANCE);
  195.         }
  196.  
  197.         // credit the amount
  198.         balance = (short) (balance + creditAmount);
  199.  
  200.     } // end of deposit method
  201.  
  202.     private void debit(APDU apdu) {
  203.  
  204.         // access authentication
  205.         if (!pin.isValidated()) {
  206.             ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
  207.         }
  208.  
  209.         byte[] buffer = apdu.getBuffer();
  210.  
  211.         byte numBytes = (buffer[ISO7816.OFFSET_LC]);
  212.  
  213.         byte byteRead = (byte) (apdu.setIncomingAndReceive());
  214.  
  215.         if ((numBytes != 1) || (byteRead != 1)) {
  216.             ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
  217.         }
  218.  
  219.         // get debit amount
  220.         byte debitAmount = buffer[ISO7816.OFFSET_CDATA];
  221.  
  222.         // check debit amount
  223.         if ((debitAmount > MAX_TRANSACTION_AMOUNT) || (debitAmount < 0)) {
  224.             ISOException.throwIt(SW_INVALID_TRANSACTION_AMOUNT);
  225.         }
  226.  
  227.         // check the new balance
  228.         if ((short) (balance - debitAmount) < (short) 0) {
  229.             ISOException.throwIt(SW_NEGATIVE_BALANCE);
  230.         }
  231.  
  232.         balance = (short) (balance - debitAmount);
  233.  
  234.     } // end of debit method
  235.  
  236.     private void getBalance(APDU apdu) {
  237.  
  238.         byte[] buffer = apdu.getBuffer();
  239.  
  240.         // inform system that the applet has finished
  241.         // processing the command and the system should
  242.         // now prepare to construct a response APDU
  243.         // which contains data field
  244.         short le = apdu.setOutgoing();
  245.  
  246.         if (le < 2) {
  247.             ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
  248.         }
  249.  
  250.         // informs the CAD the actual number of bytes
  251.         // returned
  252.         apdu.setOutgoingLength((byte) 2);
  253.  
  254.         // move the balance data into the APDU buffer
  255.         // starting at the offset 0
  256.         buffer[0] = (byte) (balance >> 8);
  257.         buffer[1] = (byte) (balance & 0xFF);
  258.  
  259.         // send the 2-byte balance at the offset
  260.         // 0 in the apdu buffer
  261.         apdu.sendBytes((short) 0, (short) 2);
  262.  
  263.     } // end of getBalance method
  264.  
  265.     private void verify(APDU apdu) {
  266.  
  267.         byte[] buffer = apdu.getBuffer();
  268.         // retrieve the PIN data for validation.
  269.         byte byteRead = (byte) (apdu.setIncomingAndReceive());
  270.  
  271.         // check pin
  272.         // the PIN data is read into the APDU buffer
  273.         // at the offset ISO7816.OFFSET_CDATA
  274.         // the PIN data length = byteRead
  275.         if (pin.check(buffer, ISO7816.OFFSET_CDATA, byteRead) == false) {
  276.             ISOException.throwIt(SW_VERIFICATION_FAILED);
  277.         }
  278.  
  279.     } // end of validate method
  280. } // end of class Wallet
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Top