package com.st; import javacard.framework.APDU; import javacard.framework.Applet; import javacard.framework.ISO7816; import javacard.framework.ISOException; import javacard.framework.Util; public class Ppse2Pay extends Applet { private static final long serialVersionUID = 1L; //FCI_TEMPLATE - DEFAULT private byte[] ADF = {(byte)0xA0,(byte)0x00,(byte)0x00,(byte)0x00, //Visa (byte)0x03,(byte)0x10,(byte)0x10 }; //DF - Dedicated File (AID) - '2PAY.SYS.DDF01' public final byte[] DF = { (byte) 0x32, (byte) 0x50, (byte) 0x41, (byte) 0x59, (byte) 0x2E, (byte) 0x53, (byte) 0x59, (byte) 0x53, (byte) 0x2E, (byte) 0x44, (byte) 0x44, (byte) 0x46, (byte) 0x30, (byte) 0x31 }; public byte[] FCI_TEMPLATE = null; public Ppse2Pay(byte[] bArray, short bOffset, byte bLength) { if (bLength > 0) { ADF = new byte[bLength]; } Util.arrayCopyNonAtomic(bArray, bOffset, ADF, (short)0, bLength); } public static void install(byte[] bArray, short bOffset, byte bLength) { new Ppse2Pay(bArray, bOffset, bLength).register(bArray, bOffset, bLength); } @Override public void process(APDU apdu) throws ISOException { byte[] buf = apdu.getBuffer(); if (selectingApplet()) { //check that LC is 0x0E if((short)(buf[ISO7816.OFFSET_LC] & 0xFF) != 0x0E) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); //get the rest of the apdu and check length if((short)(buf[ISO7816.OFFSET_LC] & 0xFF) != apdu.setIncomingAndReceive()) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); if(FCI_TEMPLATE==null) { FCI_TEMPLATE = new byte[12 + ADF.length]; FCI_TEMPLATE[0]=(byte)0xA5; //FCI Proprietary Template FCI_TEMPLATE[1]=(byte)(10 + ADF.length); //length FCI_TEMPLATE[2]=(byte)0xBF; //FCI Issuer Discretionary Data FCI_TEMPLATE[3]=(byte)0x0C; FCI_TEMPLATE[4]=(byte)(7 + ADF.length); //length FCI_TEMPLATE[5]=(byte)0x61; //Directory Entry FCI_TEMPLATE[6]=(byte)(ADF.length + 5); //length FCI_TEMPLATE[7]=(byte)0x4F; //ADF Name FCI_TEMPLATE[8]=(byte)(ADF.length); //length for(short i=0;i<ADF.length;i++) FCI_TEMPLATE[9+i] = ADF[i]; FCI_TEMPLATE[9 + ADF.length]=(byte)0x87; //Application Priority Indicator FCI_TEMPLATE[10 + ADF.length]=(byte)1; //length FCI_TEMPLATE[11 + ADF.length]=(byte)0x01; } //return FCI upon successful select apdu.setOutgoing(); buf[0]=(byte)0x6F; //FCI Template buf[1]=(byte)(2 + DF.length + FCI_TEMPLATE.length); //length buf[2]=(byte)0x84; //DF Name buf[3]=(byte)DF.length; //length for(short i=0;i<DF.length;i++) buf[4+i] = DF[i]; for(short i=0;i<FCI_TEMPLATE.length;i++) buf[4 + DF.length + i] = FCI_TEMPLATE[i]; apdu.setOutgoingLength((short)(4 + DF.length + FCI_TEMPLATE.length)); apdu.sendBytes((short)0,(short)(4 + DF.length + FCI_TEMPLATE.length)); return; } switch (buf[ISO7816.OFFSET_INS]) { case (byte) 0xA4: //select PPSE //check that P1 & P2 are correct if(buf[ISO7816.OFFSET_P1] != (byte) 0x04 || buf[ISO7816.OFFSET_P2] != (byte) 0x00) ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2); //check that LC is 0x0E if((short)(buf[ISO7816.OFFSET_LC] & 0xFF) != 0x0E) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); //get the rest of the apdu and check length if((short)(buf[ISO7816.OFFSET_LC] & 0xFF) != apdu.setIncomingAndReceive()) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); //otherwise, the file name was wrong for this select else ISOException.throwIt(ISO7816.SW_FILE_NOT_FOUND); case (byte) 0xEE: //loopback //check that P1 & P2 are correct if(buf[ISO7816.OFFSET_P1] != (byte) 0x00 || buf[ISO7816.OFFSET_P2] != (byte) 0x00) ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2); //check that the length byte is within the spec (1-250) if((short)(buf[ISO7816.OFFSET_LC] & 0xFF) < 1 || (short)(buf[ISO7816.OFFSET_LC] & 0xFF) > 250) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); //get the rest of the apdu and check length if((short)(buf[ISO7816.OFFSET_LC] & 0xFF) != apdu.setIncomingAndReceive()) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); short len = buf[ISO7816.OFFSET_LC]; for(short i=0;i<len;i++) buf[i] = buf[i+5]; apdu.setOutgoingLength(len); apdu.sendBytes((short)0,len); break; default: // good practice: If you don't know the INStruction, say so: ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED); } } }