From b5f23598814b95cc354776e1e4de1a24b70572ee Mon Sep 17 00:00:00 2001 From: Hladu357 Date: Sun, 20 Oct 2024 17:28:08 +0200 Subject: [PATCH] java card pin --- lab01-03_java_card/Applet1.java | 86 +++++++++++++++++++++++++++++++ lab01-03_java_card/Applet2.java | 89 +++++++++++++++++++++++++++++++++ lab01-03_java_card/test1.script | 40 +++++++++++++++ lab01-03_java_card/test2.script | 40 +++++++++++++++ 4 files changed, 255 insertions(+) create mode 100644 lab01-03_java_card/Applet1.java create mode 100644 lab01-03_java_card/Applet2.java create mode 100755 lab01-03_java_card/test1.script create mode 100755 lab01-03_java_card/test2.script diff --git a/lab01-03_java_card/Applet1.java b/lab01-03_java_card/Applet1.java new file mode 100644 index 0000000..85fdac2 --- /dev/null +++ b/lab01-03_java_card/Applet1.java @@ -0,0 +1,86 @@ +package hwb1; + +import javacard.framework.*; +//import javacardx.annotations.*; +import javacard.security.*; +import javacardx.crypto.*; + +public class Applet1 extends Applet { + byte str[] = JCSystem.makeTransientByteArray((short)20, JCSystem.CLEAR_ON_RESET); + OwnerPIN pin; + + public static void install(byte[] bArray, short bOffset, byte bLength) { + new Applet1(bArray, bOffset, bLength); + } + + protected Applet1(byte[] bArray, short bOffset, byte bLength) { + byte iLen = bArray[bOffset]; + byte cLen = bArray[(short)(bOffset + iLen + (short)1)]; + byte aLen = bArray[(short)(bOffset + cLen + (short)1)]; + + pin = new OwnerPIN((byte)3, (byte)4); + pin.update(bArray, (short)(bOffset + iLen + cLen + 3), aLen); + + + str = new byte[21]; + register(); + } + + private void sendName(APDU apdu) { + short len = apdu.setOutgoing(); + byte name[] = {'o','n','d','r','a'}; + if (len > name.length) ISOException.throwIt((short) + (ISO7816.SW_CORRECT_LENGTH_00 + (short)(name.length))); + + apdu.setOutgoingLength((short)len); + apdu.sendBytesLong(name, (short)0, (short)len); + } + + private void storeData(APDU apdu) { + if (!pin.isValidated()) { + ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED); + } + + short bufLen = apdu.setIncomingAndReceive(); + if (bufLen >= str.length) { + short err = ISO7816.SW_WRONG_LENGTH; + err |= (short)(str.length - (short)1); + ISOException.throwIt(err); + } + + byte [] buf = apdu.getBuffer(); + Util.arrayCopyNonAtomic(buf, ISO7816.OFFSET_CDATA, str, (short)0, bufLen); + str[(short)(str.length - (short)1)] = (byte)bufLen; + } + + private void sendData(APDU apdu) { + if (!pin.isValidated()) { + ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED); + } + + short len = apdu.setOutgoing(); + if (len > (short)str[(short)(str.length - (short)1)]) ISOException.throwIt((short) + (ISO7816.SW_CORRECT_LENGTH_00 + (short)(str.length - (short)1))); + apdu.setOutgoingLength((short)(str.length - (short)1)); + apdu.sendBytesLong(str, (short)0, (short)(str.length - (short)1)); + + } + + public void process(APDU apdu) { + byte [] buf = apdu.getBuffer(); + + if (buf[ISO7816.OFFSET_CLA] != 0x00) { + ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED); + } + + byte ins = buf[ISO7816.OFFSET_INS]; + switch(ins) { + case 0x00: sendName (apdu); return; + case 0x02: storeData(apdu); return; + case 0x04: sendData (apdu); return; + } + + ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED); + + } +} diff --git a/lab01-03_java_card/Applet2.java b/lab01-03_java_card/Applet2.java new file mode 100644 index 0000000..fde727f --- /dev/null +++ b/lab01-03_java_card/Applet2.java @@ -0,0 +1,89 @@ +package hwb1; + +import javacard.framework.*; +//import javacardx.annotations.*; +import javacard.security.*; +import javacardx.crypto.*; + +public class Applet1 extends Applet { + AESKey crypt_key; + AESKey mac_key; + byte crypt_key_bytes[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; + byte mac_key_bytes[] = {15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0}; + Cipher crypt; + Signature mac; + + public static void install(byte[] bArray, short bOffset, byte bLength) { + new Applet1(bArray, bOffset, bLength); + } + + protected Applet1(byte[] bArray, short bOffset, byte bLength) { + crypt_key = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_128, false); + crypt_key.setKey(crypt_key_bytes, (short)0); + crypt = Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_CBC_NOPAD, false); + + mac_key = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_128, false); + mac_key.setKey(mac_key_bytes, (short)0); + mac = Signature.getInstance(Cipher.ALG_AES_MAC_128_NOPAD, false); + register(); + } + +private void encrypt(APDU apdu) { + byte[] buf = apdu.getBuffer(); + short inLen = apdu.setIncomingAndReceive(); + + if (inLen > 64 || (ilen % 16) != 0) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); + + byte[] outBuf = new byte[64]; + byte[] macBuf = new byte[16]; + + crypt.init(crypt_key, Cipher.MODE_ENCRYPT); + crypt.doFinal(buf, ISO7816.OFFSET_CDATA, inLen, outBuf, (short) 0); + + mac.init(mac_key, Signature.MODE_SIGN); + mac.sign(outBuf, (short) 0, (short) inLen, macBuf, (short) 0); + + Util.arrayCopyNonAtomic(outBuf, (short) 0, buf, (short) 0, inLen); + Util.arrayCopyNonAtomic(macBuf, (short) 0, buf, inLen, (short) 16); + + apdu.setOutgoingAndSend((short) 0, (short) (inLen + 16)); + } + + private void decrypt(APDU apdu) { + byte[] buf = apdu.getBuffer(); + short inLen = apdu.setIncomingAndReceive(); + + // 64 encrypted + 16 signature + if (inLen != 80) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); + + short cryptDataLen = (short) (inLen - (short) 16); + byte[] cryptBuf = new byte[64]; + + mac.init(mac_key, Signature.MODE_VERIFY); + boolean isValidMac = mac.verify(buf, (short) 0, cryptDataLen, buf, cryptDataLen, (short) 16); + if (!isValidMac) { + ISOException.throwIt(ISO7816.SW_WRONG_DATA); + } + + crypt.init(crypt_key, Cipher.MODE_DECRYPT); + crypt.doFinal(buf, (short) 0, cryptDataLen, cryptBuf, (short) 0); + + Util.arrayCopyNonAtomic(cryptBuf, (short) 0, buf, (short) 0, cryptDataLen); + apdu.setOutgoingAndSend((short) 0, cryptDataLen); + } + + public void process(APDU apdu) { + byte [] buf = apdu.getBuffer(); + + if (buf[ISO7816.OFFSET_CLA] != 0x00) { + ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED); + } + + byte ins = buf[ISO7816.OFFSET_INS]; + switch(ins) { + case 0x42: encrypt(apdu); ISOException.throwIt(ISO7816.SW_NO_ERROR); + case 0x44: decrypt(apdu); ISOException.throwIt(ISO7816.SW_NO_ERROR); + } + ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED); + } +} \ No newline at end of file diff --git a/lab01-03_java_card/test1.script b/lab01-03_java_card/test1.script new file mode 100755 index 0000000..3ab9de7 --- /dev/null +++ b/lab01-03_java_card/test1.script @@ -0,0 +1,40 @@ +///////////////// +// TEST SCRIPT // +///////////////// +// +// get constant name +0x80 0x00 0x00 0x00 0x00 0x05; +// -> 0x6f, 0x6e, 0x64, 0x72, 0x61 +// +// get constant too large +0x80 0x00 0x00 0x00 0x00 0xab; +// -> 0x6x 0x05 +// +// save +0x80 0x02 0x00 0x00 0x05 +0x01 0x02 0x03 0x04 0x05 +0x00; +// -> 0x00 +// +// load +0x80 0x04 0x00 0x00 0x00 0x05; +// -> 0x01 0x02 0x03 0x04 0x05 +// +// save too large +0x80 0x02 0x00 0x00 0x1e +0x01 0x02 0x03 0x04 0x05 +0x01 0x02 0x03 0x04 0x05 +0x01 0x02 0x03 0x04 0x05 +0x01 0x02 0x03 0x04 0x05 +0x01 0x02 0x03 0x04 0x05 +0x01 0x02 0x03 0x04 0x05 +0x00; +// -> 0x67 0x14 +// +// load too large +0x80 0x04 0x00 0x00 0x00 0x1e; +// -> 0x6c 0x14 +// +// unknown instruction +0x80 0xab 0x00 0x00 0x00 0x00; +// -> 0x6d 0x00 \ No newline at end of file diff --git a/lab01-03_java_card/test2.script b/lab01-03_java_card/test2.script new file mode 100755 index 0000000..9ccb428 --- /dev/null +++ b/lab01-03_java_card/test2.script @@ -0,0 +1,40 @@ +///////////////////// +// AES TEST SCRIPT // +///////////////////// +// +// get constant name +0x80 0x00 0x00 0x00 0x00 0x05; +// -> 0x6f, 0x6e, 0x64, 0x72, 0x61 +// +// get constant too large +0x80 0x00 0x00 0x00 0x00 0xab; +// -> 0x6x 0x05 +// +// save +0x80 0x02 0x00 0x00 0x05 +0x01 0x02 0x03 0x04 0x05 +0x00; +// -> 0x00 +// +// load +0x80 0x04 0x00 0x00 0x00 0x05; +// -> 0x01 0x02 0x03 0x04 0x05 +// +// save too large +0x80 0x02 0x00 0x00 0x1e +0x01 0x02 0x03 0x04 0x05 +0x01 0x02 0x03 0x04 0x05 +0x01 0x02 0x03 0x04 0x05 +0x01 0x02 0x03 0x04 0x05 +0x01 0x02 0x03 0x04 0x05 +0x01 0x02 0x03 0x04 0x05 +0x00; +// -> 0x67 0x14 +// +// load too large +0x80 0x04 0x00 0x00 0x00 0x1e; +// -> 0x6c 0x14 +// +// unknown instruction +0x80 0xab 0x00 0x00 0x00 0x00; +// -> 0x6d 0x00 \ No newline at end of file