Advertisement
Guest User

Untitled

a guest
Apr 22nd, 2019
104
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.60 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.sun.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. final static short MAX_LP = 0x2710;
  25. // code of CLA byte in the command APDU header
  26. static int tries = 0;
  27. final static byte Wallet_CLA = (byte) 0x80;
  28.  
  29. // codes of INS byte in the command APDU header
  30. final static byte VERIFY = (byte) 0x20;
  31. final static byte CREDIT = (byte) 0x30;
  32. final static byte DEBIT = (byte) 0x40;
  33. final static byte GET_BALANCE = (byte) 0x50;
  34. final static byte UPDATE_PIN = (byte) 0x70;
  35.  
  36. // maximum balance
  37. final static short MAX_BALANCE = 0x7FFF;
  38. // maximum transaction amount
  39. final static short MAX_TRANSACTION_AMOUNT = 600;
  40.  
  41. // maximum number of incorrect tries before the
  42. // PIN is blocked
  43. final static byte PIN_TRY_LIMIT = (byte) 0x03;
  44. // maximum size PIN
  45. final static byte MAX_PIN_SIZE = (byte) 0x08;
  46.  
  47. // signal that the PIN verification failed
  48. final static short SW_VERIFICATION_FAILED = 0x6300;
  49. // signal the the PIN validation is required
  50. // for a credit or a debit transaction
  51. final static short SW_PIN_VERIFICATION_REQUIRED = 0x6301;
  52. // signal invalid transaction amount
  53. // amount > MAX_TRANSACTION_AMOUNT or amount < 0
  54. final static short SW_INVALID_TRANSACTION_AMOUNT = 0x6A83;
  55.  
  56. // signal that the balance exceed the maximum
  57. final static short SW_EXCEED_MAXIMUM_BALANCE = 0x6A84;
  58. // signal the the balance becomes negative
  59. final static short SW_NEGATIVE_BALANCE = 0x6A85;
  60. final static short SW_SECURITY_STATUS_NOT_SATISFIED = 0x6982;
  61.  
  62. /* instance variables declaration */
  63. OwnerPIN pin;
  64. OwnerPIN updatedPin;
  65. short balance;
  66. short actual_lp = 0;
  67.  
  68. private Wallet(byte[] bArray, short bOffset, byte bLength) {
  69.  
  70. // It is good programming practice to allocate
  71. // all the memory that an applet needs during
  72. // its lifetime inside the constructor
  73. pin = new OwnerPIN(PIN_TRY_LIMIT, MAX_PIN_SIZE);
  74.  
  75. byte iLen = bArray[bOffset]; // aid length
  76. bOffset = (short) (bOffset + iLen + 1);
  77. byte cLen = bArray[bOffset]; // info length
  78. bOffset = (short) (bOffset + cLen + 1);
  79. byte aLen = bArray[bOffset]; // applet data length
  80.  
  81. // The installation parameters contain the PIN
  82. // initialization value
  83. pin.update(bArray, (short) (bOffset + 1), aLen);
  84. register();
  85.  
  86. } // end of the constructor
  87.  
  88. public static void install(byte[] bArray, short bOffset, byte bLength) {
  89. // create a Wallet applet instance
  90. new Wallet(bArray, bOffset, bLength);
  91. } // end of install method
  92.  
  93. @Override
  94. public boolean select() {
  95.  
  96. // The applet declines to be selected
  97. // if the pin is blocked.
  98. if (pin.getTriesRemaining() == 0) {
  99. return false;
  100. }
  101.  
  102. return true;
  103.  
  104. }// end of select method
  105.  
  106. @Override
  107. public void deselect() {
  108.  
  109. // reset the pin value
  110. pin.reset();
  111.  
  112. }
  113.  
  114. @Override
  115. public void process(APDU apdu) {
  116.  
  117. // APDU object carries a byte array (buffer) to
  118. // transfer incoming and outgoing APDU header
  119. // and data bytes between card and CAD
  120.  
  121. // At this point, only the first header bytes
  122. // [CLA, INS, P1, P2, P3] are available in
  123. // the APDU buffer.
  124. // The interface javacard.framework.ISO7816
  125. // declares constants to denote the offset of
  126. // these bytes in the APDU buffer
  127.  
  128. byte[] buffer = apdu.getBuffer();
  129. // check SELECT APDU command
  130.  
  131. if (apdu.isISOInterindustryCLA()) {
  132. if (buffer[ISO7816.OFFSET_INS] == (byte) (0xA4)) {
  133. return;
  134. }
  135. ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
  136. }
  137.  
  138. // verify the reset of commands have the
  139. // correct CLA byte, which specifies the
  140. // command structure
  141. if (buffer[ISO7816.OFFSET_CLA] != Wallet_CLA) {
  142. ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
  143. }
  144.  
  145. switch (buffer[ISO7816.OFFSET_INS]) {
  146. case GET_BALANCE:
  147. getBalance(apdu);
  148. return;
  149. case DEBIT:
  150. debit(apdu);
  151. return;
  152. case CREDIT:
  153. credit(apdu);
  154. return;
  155. case VERIFY:
  156. verify(apdu);
  157. return;
  158. case UPDATE_PIN:
  159. updatePin(apdu);
  160. return;
  161. default:
  162. ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
  163. }
  164.  
  165. } // end of process method
  166.  
  167. private void updatePin(APDU apdu) {
  168. byte[] buffer = apdu.getBuffer();
  169.  
  170. byte currentPinSize = buffer[ISO7816.OFFSET_CDATA];
  171.  
  172. byte newPinSize = buffer[ISO7816.OFFSET_CDATA + 1 + currentPinSize];
  173.  
  174. if (pin.check(buffer, (short) (ISO7816.OFFSET_CDATA + 1), ISO7816.OFFSET_CDATA) == false) {
  175. ISOException.throwIt(SW_VERIFICATION_FAILED);
  176. tries = tries + 1;
  177. if (tries >= 3) {
  178. ISOException.throwIt(SW_SECURITY_STATUS_NOT_SATISFIED);
  179. }
  180. return;
  181. }
  182.  
  183. if (!pin.isValidated()) {
  184. ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
  185. }
  186.  
  187. // updatedPin.update(buffer, (short) (ISO7816.OFFSET_CDATA + 2 + currentPinSize ), newPinSize);
  188. pin.update(buffer, (short) (ISO7816.OFFSET_CDATA + 2 + currentPinSize ), newPinSize);
  189. }
  190.  
  191. private void credit(APDU apdu) {
  192.  
  193. // access authentication
  194. if (!pin.isValidated()) {
  195. ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
  196. }
  197.  
  198. byte[] buffer = apdu.getBuffer();
  199.  
  200. // Lc byte denotes the number of bytes in the
  201. // data field of the command APDU
  202. byte numBytes = buffer[ISO7816.OFFSET_LC];
  203.  
  204. // indicate that this APDU has incoming data
  205. // and receive data starting from the offset
  206. // ISO7816.OFFSET_CDATA following the 5 header
  207. // bytes.
  208. byte byteRead = (byte) (apdu.setIncomingAndReceive());
  209.  
  210. // it is an error if the number of data bytes
  211. // read does not match the number in Lc byte
  212. if ((numBytes != 2) || (byteRead != 2)) {
  213. ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
  214. }
  215.  
  216. // get the credit amount
  217. // short creditAmount = buffer[ISO7816.OFFSET_CDATA];
  218. short creditAmount = (short) ((buffer[ISO7816.OFFSET_CDATA] & 0xFF) << 8
  219. | (buffer[ISO7816.OFFSET_CDATA + 1] & 0xFF));
  220. // check the credit amount
  221. if ((creditAmount > MAX_TRANSACTION_AMOUNT) || (creditAmount < 0)) {
  222. ISOException.throwIt(SW_INVALID_TRANSACTION_AMOUNT);
  223. }
  224.  
  225. // check the new balance
  226. if ((short) (balance + creditAmount) > MAX_BALANCE) {
  227. ISOException.throwIt(SW_EXCEED_MAXIMUM_BALANCE);
  228. }
  229.  
  230. // credit the amount
  231. balance = (short) (balance + creditAmount);
  232.  
  233. } // end of deposit method
  234.  
  235. private void debit(APDU apdu) {
  236.  
  237. // access authentication
  238. if (!pin.isValidated()) {
  239. ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
  240. }
  241.  
  242. byte[] buffer = apdu.getBuffer();
  243.  
  244. byte numBytes = (buffer[ISO7816.OFFSET_LC]);
  245.  
  246. byte byteRead = (byte) (apdu.setIncomingAndReceive());
  247.  
  248. if ((numBytes != 3) || (byteRead != 3)) {
  249. ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
  250. }
  251.  
  252. if(buffer[ISO7816.OFFSET_CDATA] == 0x01) {
  253. byte firstPart = buffer[ISO7816.OFFSET_CDATA + 1];
  254. byte secondPart = buffer[ISO7816.OFFSET_CDATA + 2];
  255.  
  256. if ((((short)((short)(firstPart) << 8 + secondPart)) > MAX_TRANSACTION_AMOUNT) || (secondPart < 0)) {
  257. ISOException.throwIt(SW_INVALID_TRANSACTION_AMOUNT);
  258. }
  259.  
  260. // check the new balance
  261. if ((short) (balance - ((short)((short)(firstPart) << 8 + secondPart))) < (short) 0) {
  262. ISOException.throwIt(SW_NEGATIVE_BALANCE);
  263. }
  264.  
  265. balance = (short) (balance - (firstPart << 8) - secondPart);
  266. actual_lp = (short) (actual_lp + (short) ((short) ((firstPart << 8) + secondPart) / 20));
  267. }
  268. else {
  269. byte firstPart = buffer[ISO7816.OFFSET_CDATA + 1];
  270. byte secondPart = buffer[ISO7816.OFFSET_CDATA + 2];
  271.  
  272. if ((((short)((short)(firstPart << 8) + secondPart)) > MAX_LP) || (secondPart < 0)) {
  273. ISOException.throwIt(SW_INVALID_TRANSACTION_AMOUNT);
  274. }
  275.  
  276. // check the new balance
  277. if ( actual_lp < (short) secondPart ) {
  278. ISOException.throwIt(SW_EXCEED_MAXIMUM_BALANCE);
  279. }
  280.  
  281. // credit the amount
  282. actual_lp = (short) (actual_lp - (firstPart << 8) - secondPart);
  283. }
  284.  
  285. // // get debit amount
  286. // short debitAmount = buffer[ISO7816.OFFSET_CDATA];
  287. //
  288. // // check debit amount
  289. // if ((debitAmount > MAX_TRANSACTION_AMOUNT) || (debitAmount < 0)) {
  290. // ISOException.throwIt(SW_INVALID_TRANSACTION_AMOUNT);
  291. // }
  292. //
  293. // // check the new balance
  294. // if ((short) (balance - debitAmount) < (short) 0) {
  295. // ISOException.throwIt(SW_NEGATIVE_BALANCE);
  296. // }
  297. //
  298. // balance = (short) (balance - debitAmount);
  299.  
  300. } // end of debit method
  301.  
  302. private void getBalance(APDU apdu) {
  303.  
  304. byte[] buffer = apdu.getBuffer();
  305.  
  306. // inform system that the applet has finished
  307. // processing the command and the system should
  308. // now prepare to construct a response APDU
  309. // which contains data field
  310. short le = apdu.setOutgoing();
  311.  
  312. if (le < 2) {
  313. ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
  314. }
  315.  
  316. // informs the CAD the actual number of bytes
  317. // returned
  318. apdu.setOutgoingLength((byte) 2);
  319.  
  320. if(buffer[ISO7816.OFFSET_CDATA] == 0x01) {
  321. buffer[0] = (byte) (balance >> 8);
  322. buffer[1] = (byte) (balance & 0xFF);
  323. }
  324. else {
  325. buffer[0] = (byte) (actual_lp >> 8);
  326. buffer[1] = (byte) (actual_lp & 0xFF);
  327. }
  328. // buffer[0] = (byte) (balance >> 8);
  329. // buffer[1] = (byte) (balance & 0xFF);
  330.  
  331. // send the 2-byte balance at the offset
  332. // 0 in the apdu buffer
  333. apdu.sendBytes((short) 0, (short) 2);
  334.  
  335. } // end of getBalance method
  336.  
  337. private void verify(APDU apdu) {
  338.  
  339. byte[] buffer = apdu.getBuffer();
  340. // retrieve the PIN data for validation.
  341. byte byteRead = (byte) (apdu.setIncomingAndReceive());
  342.  
  343. // check pin
  344. // the PIN data is read into the APDU buffer
  345. // at the offset ISO7816.OFFSET_CDATA
  346. // the PIN data length = byteRead
  347. if (pin.check(buffer, ISO7816.OFFSET_CDATA, byteRead) == false) {
  348. ISOException.throwIt(SW_VERIFICATION_FAILED);
  349. }
  350.  
  351. } // end of validate method
  352. } // end of class Wallet
  353.  
  354.  
  355.  
  356.  
  357.  
  358. output on;
  359.  
  360. // create wallet applet
  361. 0x80 0xB8 0x00 0x00 0x14 0x0a 0xa0 0x0 0x0 0x0 0x62 0x3 0x1 0xc 0x6 0x1 0x08 0x0 0x0 0x05 0x01 0x02 0x03 0x04 0x05 0x7F;
  362.  
  363.  
  364. /////////////////////////////////////////////////////////////////////
  365. // Initialize Wallet
  366. /////////////////////////////////////////////////////////////////////
  367.  
  368. //Select Wallet
  369. 0x00 0xA4 0x04 0x00 0x0a 0xa0 0x0 0x0 0x0 0x62 0x3 0x1 0xc 0x6 0x1 0x7F;
  370. // 90 00 = SW_NO_ERROR
  371.  
  372. //Verify user pin
  373. 0x80 0x20 0x00 0x00 0x05 0x01 0x02 0x03 0x04 0x05 0x7F;
  374.  
  375. //Credit $100 to the empty account
  376. 0x80 0x30 0x00 0x00 0x02 0x00 0x64 0x7F;
  377.  
  378. //get balance money
  379. 0x80 0x50 0x00 0x00 0x01 0x01 0x02;
  380.  
  381. //get balance lp
  382. 0x80 0x50 0x00 0x00 0x01 0x02 0x02;
  383.  
  384. //debit with money
  385. 0x80 0x40 0x00 0x00 0x03 0x01 0x00 0x32 0x7F;
  386.  
  387. //get balance lp
  388. 0x80 0x50 0x00 0x00 0x01 0x02 0x02;
  389.  
  390. //get balance money
  391. 0x80 0x50 0x00 0x00 0x01 0x01 0x02;
  392.  
  393. //debit with lp
  394. 0x80 0x40 0x00 0x00 0x03 0x02 0x00 0x01 0x7F;
  395.  
  396. //get balance lp
  397. 0x80 0x50 0x00 0x00 0x01 0x02 0x02;
  398.  
  399. //debit lp
  400. 0x80 0x40 0x00 0x00 0x03 0x02 0x00 0xfa 0x7F;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement