diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 7c61d86..15176fc 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -22,6 +22,18 @@ }, "problemMatcher": [] }, + { + "label": "Flash SecretApplet", + "type": "shell", + "command": "${workspaceFolder}/scripts/flash.cmd", + "options": { + "env": { + "PACKAGE": "hwb1", + "APPLET": "SecretApplet" + } + }, + "problemMatcher": [] + }, { "label": "Test MyApplet", "type": "shell", diff --git a/hwb1/.javacard_project b/hwb1/.javacard_project index 01d0ddb..455faf1 100644 --- a/hwb1/.javacard_project +++ b/hwb1/.javacard_project @@ -16,10 +16,19 @@ src/hwb1/MyApplet.java + + IsJavaCardApplet + 1 + AID 52C4C7C95C0420 + + + + src/hwb1/SecretApplet.java + IsJavaCardApplet 1 diff --git a/hwb1/configurations/hwb1.conf b/hwb1/configurations/hwb1.conf index e093435..b556cef 100644 --- a/hwb1/configurations/hwb1.conf +++ b/hwb1/configurations/hwb1.conf @@ -1,6 +1,7 @@ -i -classdir ..\bin -applet 0x52:0xC4:0xC7:0xC9:0x5C:0x04:0x20 hwb1.MyApplet +-applet 0x52:0xC4:0xC7:0xC9:0x5C:0x82:0x28 hwb1.SecretApplet -out CAP JCA EXP -d ..\deliverables\hwb1 -debug diff --git a/hwb1/configurations/hwb1.scriptgen b/hwb1/configurations/hwb1.scriptgen index be348a2..460a569 100644 --- a/hwb1/configurations/hwb1.scriptgen +++ b/hwb1/configurations/hwb1.scriptgen @@ -1,5 +1,5 @@ -#Thu Oct 12 17:03:08 CEST 2023 -SCRIPTGEN_NO_POWER_UP=false -SCRIPTGEN_NO_POWER_DOWN=true -SCRIPTGEN_NO_BANNER=false +#Sat Nov 04 21:00:23 CET 2023 SCRIPTGEN_NO_BEGIN_END=false +SCRIPTGEN_NO_BANNER=false +SCRIPTGEN_NO_POWER_DOWN=true +SCRIPTGEN_NO_POWER_UP=false diff --git a/hwb1/src/hwb1/SecretApplet.java b/hwb1/src/hwb1/SecretApplet.java new file mode 100644 index 0000000..8ed0610 --- /dev/null +++ b/hwb1/src/hwb1/SecretApplet.java @@ -0,0 +1,138 @@ +/** + * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * + */ + +package hwb1; + +import javacard.framework.*; +import javacard.security.AESKey; +import javacard.security.CryptoException; +import javacard.security.KeyBuilder; +import javacard.security.Signature; +import javacardx.crypto.Cipher; + +/** + * Applet class + * + * @author + */ +public class SecretApplet extends Applet { + private AESKey encryptionKey; + private AESKey macKey; + + /** + * Installs this applet. + * + * @param bArray 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 SecretApplet(); + } + + /** + * Only this class's install method should create the applet object. + */ + protected SecretApplet() { + register(); + encryptionKey = initializeKey(new byte[] { 0x59, (byte)0xA3, (byte)0xFA, 0x76, 0x35, 0x40, 0x01, (byte)0x82, (byte)0xA5, (byte)0xC0, (byte)0xAB, (byte)0xE0, 0x1F, 0x30, (byte)0x89, (byte)0xFA }); + macKey = initializeKey(new byte[] { 0x58, (byte)0x9F, 0x61, 0x62, (byte)0xBB, 0x10, (byte)0x89, (byte)0xD8, 0x1A, 0x16, (byte)0xD3, 0x2A, 0x3F, 0x06, 0x27, (byte)0xC6 }); + } + + /** + * Processes an incoming APDU. + * + * @see APDU + * @param apdu the incoming APDU + */ + public void process(APDU apdu) { + short length; + byte[] buffer = apdu.getBuffer(); + + if (selectingApplet()) { + ISOException.throwIt(ISO7816.SW_NO_ERROR); + } else { + if (buffer[ISO7816.OFFSET_CLA] != (byte)0x80) { + ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED); + } else { + byte instruction = buffer[ISO7816.OFFSET_INS]; + + try { + switch (instruction) { + case 0x42: + byte[] encrypted; + length = apdu.setIncomingAndReceive(); + + if (length > 64) { + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); + } else { + encrypted = new byte[(short)(length + 16)]; + Cipher cipher = getEncryptionCipher(Cipher.MODE_ENCRYPT); + cipher.doFinal(buffer, ISO7816.OFFSET_CDATA, length, encrypted, (short)0); + + Signature signature = getMACSignature(Signature.MODE_SIGN); + short totalLength = (short)(length + signature.sign(encrypted, (short)0, length, encrypted, length)); + apdu.setOutgoing(); + apdu.setOutgoingLength(totalLength); + apdu.sendBytesLong(encrypted, (short)0, totalLength); + } + break; + case 0x44: + length = apdu.setIncomingAndReceive(); + + if (length > 80) { + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); + } else { + Signature signature = getMACSignature(Signature.MODE_VERIFY); + short signatureLength = 16; + short messageLength = (short)(length - signatureLength); + short signatureOffset = (short)(ISO7816.OFFSET_CDATA + messageLength); + + if (!signature.verify(buffer, ISO7816.OFFSET_CDATA, messageLength, buffer, signatureOffset, signatureLength)) { + ISOException.throwIt(ISO7816.SW_WRONG_DATA); + } else { + byte[] decrypted = new byte[messageLength]; + Cipher cipher = getEncryptionCipher(Cipher.MODE_DECRYPT); + cipher.doFinal(buffer, ISO7816.OFFSET_CDATA, messageLength, decrypted, (short)0); + + apdu.setOutgoing(); + apdu.setOutgoingLength(messageLength); + apdu.sendBytesLong(decrypted, (short)0, messageLength); + } + } + break; + default: + ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED); + break; + } + } catch (CryptoException exception) { + ISOException.throwIt((short)(ISO7816.SW_WRONG_LENGTH | exception.getReason())); + } + + ISOException.throwIt(ISO7816.SW_NO_ERROR); + } + } + } + + protected AESKey initializeKey(byte[] keyBytes) { + AESKey key = (AESKey)KeyBuilder.buildKey(KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_128, false); + key.setKey(keyBytes, (short)0); + return key; + } + + protected Cipher getEncryptionCipher(byte mode) { + byte[] initializationVector = new byte[] { 0x18, 0x24, 0x57, (byte)0xD6, (byte)0x97, 0x33, 0x69, (byte)0xED, 0x05, 0x4D, 0x6E, 0x14, (byte)0x93, (byte)0xE4, (byte)0xB7, 0x45 }; + Cipher cipher = Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_CBC_NOPAD, false); + cipher.init(encryptionKey, mode, initializationVector, (short)0, (short)initializationVector.length); + return cipher; + } + + protected Signature getMACSignature(byte mode) { + byte[] initializationVector = new byte[] { (byte)0xB6, 0x6C, (byte)0xAC, (byte)0xC7, (byte)0xD6, 0x78, (byte)0x88, 0x18, 0x07, (byte)0x88, (byte)0xA4, 0x27, 0x07, 0x55, 0x50, 0x2A }; + Signature signature = Signature.getInstance(Signature.ALG_AES_MAC_128_NOPAD, false); + signature.init(macKey, mode, initializationVector, (short)0, (short)initializationVector.length); + return signature; + } +}