Advertisement
Guest User

Untitled

a guest
Mar 26th, 2020
149
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.55 KB | None | 0 0
  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
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement