From 551ac64fa7eb0f5dc03fd868d5f58d3f1ca18596 Mon Sep 17 00:00:00 2001
From: Manuel Thalmann <m@nuth.ch>
Date: Tue, 24 Oct 2023 23:09:30 +0200
Subject: [PATCH] Allow sensitive commands only with PIN

---
 hwb1/src/hwb1/MyApplet.java | 102 +++++++++++++++++++++++-------------
 1 file changed, 65 insertions(+), 37 deletions(-)

diff --git a/hwb1/src/hwb1/MyApplet.java b/hwb1/src/hwb1/MyApplet.java
index 8312b8f..6bd71a2 100644
--- a/hwb1/src/hwb1/MyApplet.java
+++ b/hwb1/src/hwb1/MyApplet.java
@@ -6,27 +6,37 @@
 package hwb1;
 
 import javacard.framework.*;
+
 /**
  * Applet class
  * 
  * @author <user>
  */
 public class MyApplet extends Applet {
+    final static short SW_PIN_VERIFICATION_REQUIRED = 0x6301;
     final static byte PIN_TRY_LIMIT =(byte)0x03;
     final static byte MAX_PIN_SIZE =(byte)0x08;
     private byte[] authorName = new byte[] { 'M', 'a', 'n', 'u', 'e', 'l' };
     private byte[] storage = new byte[] {};
-    OwnerPIN pin;
+    private OwnerPIN pin;
 
     /**
      * Installs this applet.
      * 
-     * @param bArray  the array containing installation parameters
+     * @param buffer  the array containing installation parameters
      * @param bOffset the starting offset in bArray
      * @param bLength the length in bytes of the parameter data in bArray
      */
-    public static void install(byte[] bArray, short bOffset, byte bLength) {
-        new MyApplet(bArray, bOffset, bLength);
+    public static void install(byte[] buffer, short offset, byte length) {
+    	byte aidLength = buffer[offset];
+
+    	short controlInfoOffset = (short)(offset + 1 + aidLength);
+    	byte controlInfoLength = buffer[controlInfoOffset];
+    	
+    	short dataOffset = (short)(controlInfoOffset + 1 + controlInfoLength);
+    	byte dataLength = buffer[dataOffset];
+
+        new MyApplet(buffer, (short)(dataOffset + 1), dataLength);
     }
 
     /**
@@ -36,9 +46,9 @@ public class MyApplet extends Applet {
      * @param bOffset the starting offset in bArray
      * @param bLength the length in bytes of the parameter data in bArray
      */
-    protected MyApplet(byte[] bArray, short bOffset, byte bLength) {
+    protected MyApplet(byte[] appletData, short dataOffset, byte dataLength) {
         pin = new OwnerPIN(PIN_TRY_LIMIT, MAX_PIN_SIZE);
-        pin.update(bArray, bOffset, bLength);
+        pin.update(appletData, dataOffset, dataLength);
         register();
     }
 
@@ -50,6 +60,11 @@ public class MyApplet extends Applet {
         }
     }
 
+    public void deselect() {
+    	super.deselect();
+    	pin.reset();
+    }
+
     /**
      * Processes an incoming APDU.
      * 
@@ -66,44 +81,57 @@ public class MyApplet extends Applet {
             if (buffer[ISO7816.OFFSET_CLA] != (byte)0x80) {
                 ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
             } else {
+            	boolean authenticationRequired = false;
                 byte instruction = buffer[ISO7816.OFFSET_INS];
 
                 switch (instruction) {
-                    case 0x00:
-                    case 0x04:
-                        byte[] response;
-                        length = apdu.setOutgoing();
+                	case 0x04:
+                	case 0x02:
+                		authenticationRequired = !pin.isValidated();
+                		break;
+                }
 
-                        if (instruction == 0x00) {
-                            response = authorName;
-                            length = (short)response.length;
-                        } else {
-                            response = storage;
+                if (authenticationRequired) {
+                	ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
+                }
+                else {
+	                switch (instruction) {
+	                    case 0x00:
+	                    case 0x04:
+	                        byte[] response;
+	                        length = apdu.setOutgoing();
 
-                            if (length > response.length) {
-                                ISOException.throwIt((short)(ISO7816.SW_CORRECT_LENGTH_00 | response.length));
-                            }
-                        }
+	                        if (instruction == 0x00) {
+	                            response = authorName;
+	                            length = (short)response.length;
+	                        } else {
+	                            response = storage;
 
-                        apdu.setOutgoingLength(length);
-                        apdu.sendBytesLong(response, (short) 0, length);
-                        break;
-                    case 0x02:
-                        length = apdu.setIncomingAndReceive();
-                        storage = new byte[length];
+	                            if (length > response.length) {
+	                                ISOException.throwIt((short)(ISO7816.SW_CORRECT_LENGTH_00 | response.length));
+	                            }
+	                        }
 
-                        if (length > 20) {
-                            ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
-                        } else {
-                            Util.arrayCopy(buffer, ISO7816.OFFSET_CDATA, storage, (short) 0, length);
-                        }
-                        break;
-                    case 0x20:
-                        length = apdu.setIncomingAndReceive();
-                        pin.check(buffer, (short) ISO7816.OFFSET_CDATA, (byte)length); 
-                    default:
-                        ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
-                        break;
+	                        apdu.setOutgoingLength(length);
+	                        apdu.sendBytesLong(response, (short) 0, length);
+	                        break;
+	                    case 0x02:
+	                        length = apdu.setIncomingAndReceive();
+	                        storage = new byte[length];
+
+	                        if (length > 20) {
+	                            ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
+	                        } else {
+	                            Util.arrayCopy(buffer, ISO7816.OFFSET_CDATA, storage, (short) 0, length);
+	                        }
+	                        break;
+	                    case 0x20:
+	                        length = apdu.setIncomingAndReceive();
+	                        pin.check(buffer, (short) ISO7816.OFFSET_CDATA, (byte)length); 
+	                    default:
+	                        ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
+	                        break;
+	                }	
                 }
                 
                 ISOException.throwIt(ISO7816.SW_NO_ERROR);