Here is my code. hope somebody help me point out where I did wrong.
Code: Select all
package challengeresponse;
import javacard.framework.APDU;
import javacard.framework.Applet;
import javacard.framework.ISO7816;
import javacard.framework.ISOException;
import javacard.framework.JCSystem;
import javacard.framework.Util;
import javacard.security.AESKey;
import javacard.security.KeyBuilder;
import javacard.security.RandomData;
import javacardx.crypto.Cipher;
public class ChallengeResponse extends Applet {
// Instruction- and class-bytes
final static byte CLASS = (byte) 0x80;
final static byte INS_START = (byte) 0x01;
final static byte INS_CHAL_READER = (byte) 0x02;
// bArray contains (length of AID, AID, length of App. priv., App. priv., installation parameters)
final static byte INST_PARAM_OFFSET = (byte) 0x0F;
final static byte[] PADDING = {0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F};
private AESKey aeskey;
private byte[] id;
private byte[] challenge_card_stored;
private RandomData challenge_card_sent;
private Cipher cipher;
private ChallengeResponse(byte bArray[], short bOffset, byte bLength) {
// Extract AES key form installation parameters and build it
aeskey = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_128, false);
aeskey.setKey(bArray,(short) INST_PARAM_OFFSET);
// Extract ID from installation parameters
id = new byte[5];
Util.arrayCopy(bArray, (short) (INST_PARAM_OFFSET + 16), id, (short) 0, (short) 5);
// Use transient arrays for security reasons
challenge_card_stored = JCSystem.makeTransientByteArray((short)8, JCSystem.CLEAR_ON_DESELECT);
challenge_card_sent = RandomData.getInstance(RandomData.ALG_SECURE_RANDOM);
cipher = Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_ECB_NOPAD,false);
// Register in card manager
register();
}
public static void install(byte bArray[], short bOffset, byte bLength)
throws ISOException {
// Install method has arguments (AES key, ID) in bArray
new ChallengeResponse(bArray,bOffset,bLength);
}
public void process(APDU apdu) throws ISOException {
byte[] apdu_buffer = apdu.getBuffer();
// return if APDU is SELECT command
if (selectingApplet())
return;
switch(apdu_buffer[ISO7816.OFFSET_INS]) {
case INS_START:
// When start command is received do:
// Create challenge and write it into apdu buffer and challenge_card_stored array as reference
challenge_card_sent.generateData(apdu_buffer,(short)(ISO7816.OFFSET_CDATA), (short)8);
Util.arrayCopy(apdu_buffer,(short)(ISO7816.OFFSET_CDATA),challenge_card_stored,(short)0,(short)8);
// Write padding
Util.arrayCopy(PADDING, (short)0, apdu_buffer, (short)(ISO7816.OFFSET_CDATA+8), (short)8);
// Encrypt message
cipher.init(aeskey, Cipher.MODE_ENCRYPT);
cipher.doFinal(apdu_buffer, (short)ISO7816.OFFSET_CDATA, (short)16, apdu_buffer, (short)ISO7816.OFFSET_CDATA);
// Send message AES{challenge_card_stored,PADDING}
apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA, (short)16);
case INS_CHAL_READER:
(...)