diff options
Diffstat (limited to 'src/simpleapdu/CardMngr.java')
| -rw-r--r-- | src/simpleapdu/CardMngr.java | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/src/simpleapdu/CardMngr.java b/src/simpleapdu/CardMngr.java new file mode 100644 index 0000000..d3ff86b --- /dev/null +++ b/src/simpleapdu/CardMngr.java @@ -0,0 +1,209 @@ +package simpleapdu; + +import com.licel.jcardsim.io.CAD; +import com.licel.jcardsim.io.JavaxSmartCardInterface; +import java.util.List; +import javacard.framework.AID; +import javax.smartcardio.*; + +/** + * + * @author xsvenda + */ +public class CardMngr { + CardTerminal m_terminal = null; + CardChannel m_channel = null; + Card m_card = null; + + // Simulator related attributes + private static CAD m_cad = null; + private static JavaxSmartCardInterface m_simulator = null; + + + private final byte selectCM[] = { + (byte) 0x00, (byte) 0xa4, (byte) 0x04, (byte) 0x00, (byte) 0x07, (byte) 0xa0, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x18, (byte) 0x43, (byte) 0x4d}; + + public static final byte OFFSET_CLA = 0x00; + public static final byte OFFSET_INS = 0x01; + public static final byte OFFSET_P1 = 0x02; + public static final byte OFFSET_P2 = 0x03; + public static final byte OFFSET_LC = 0x04; + public static final byte OFFSET_DATA = 0x05; + public static final byte HEADER_LENGTH = 0x05; + public final static short DATA_RECORD_LENGTH = (short) 0x80; // 128B per record + public final static short NUMBER_OF_RECORDS = (short) 0x0a; // 10 records + + public boolean ConnectToCard() throws Exception { + // TRY ALL READERS, FIND FIRST SELECTABLE + List terminalList = GetReaderList(); + + if (terminalList.isEmpty()) { + System.out.println("No terminals found"); + } + + //List numbers of Card readers + boolean cardFound = false; + for (int i = 0; i < terminalList.size(); i++) { + System.out.println(i + " : " + terminalList.get(i)); + m_terminal = (CardTerminal) terminalList.get(i); + if (m_terminal.isCardPresent()) { + m_card = m_terminal.connect("*"); + System.out.println("card: " + m_card); + m_channel = m_card.getBasicChannel(); + + //reset the card + ATR atr = m_card.getATR(); + System.out.println(bytesToHex(m_card.getATR().getBytes())); + + cardFound = true; + } + } + + return cardFound; + } + + public void DisconnectFromCard() throws Exception { + if (m_card != null) { + m_card.disconnect(false); + m_card = null; + } + } + + public byte[] GetCPLCData() throws Exception { + byte[] data; + + // TODO: Modify to obtain CPLC data + byte apdu[] = new byte[HEADER_LENGTH]; + apdu[OFFSET_CLA] = (byte) 0x00; + apdu[OFFSET_INS] = (byte) 0x00; + apdu[OFFSET_P1] = (byte) 0x00; + apdu[OFFSET_P2] = (byte) 0x00; + apdu[OFFSET_LC] = (byte) 0x00; + + ResponseAPDU resp = sendAPDU(apdu); + if (resp.getSW() != 0x9000) { // 0x9000 is "OK" + System.out.println("Fail to obtain card's response data"); + data = null; + } else { + byte temp[] = resp.getBytes(); + data = new byte[temp.length - 2]; + System.arraycopy(temp, 0, data, 0, temp.length - 2); + // Last two bytes are status word (also obtainable by resp.getSW()) + // Take a look at ISO7816_status_words.txt for common codes + } + + return data; + } + + public void ProbeCardCommands() throws Exception { + // TODO: modify to probe for instruction + for (int i = 0; i <= 0; i++) { + byte apdu[] = new byte[HEADER_LENGTH]; + apdu[OFFSET_CLA] = (byte) 0x00; + apdu[OFFSET_INS] = (byte) 0x00; + apdu[OFFSET_P1] = (byte) 0x00; + apdu[OFFSET_P2] = (byte) 0x00; + apdu[OFFSET_LC] = (byte) 0x00; + + ResponseAPDU resp = sendAPDU(apdu); + + System.out.println("Response: " + Integer.toHexString(resp.getSW())); + + if (resp.getSW() != 0x6D00) { // Note: 0x6D00 is SW_INS_NOT_SUPPORTED + // something? + } + } + } + + public List GetReaderList() { + try { + TerminalFactory factory = TerminalFactory.getDefault(); + List readersList = factory.terminals().list(); + return readersList; + } catch (Exception ex) { + System.out.println("Exception : " + ex); + return null; + } + } + + public ResponseAPDU sendAPDU(byte apdu[]) throws Exception { + CommandAPDU commandAPDU = new CommandAPDU(apdu); + + System.out.println(">>>>"); + System.out.println(commandAPDU); + + System.out.println(bytesToHex(commandAPDU.getBytes())); + + long elapsed = -System.nanoTime(); + + ResponseAPDU responseAPDU = m_channel.transmit(commandAPDU); + + elapsed += System.nanoTime(); + + System.out.println(responseAPDU); + System.out.println(bytesToHex(responseAPDU.getBytes())); + + if (responseAPDU.getSW1() == (byte) 0x61) { + CommandAPDU apduToSend = new CommandAPDU((byte) 0x00, + (byte) 0xC0, (byte) 0x00, (byte) 0x00, + (int) responseAPDU.getSW1()); + + responseAPDU = m_channel.transmit(apduToSend); + System.out.println(bytesToHex(responseAPDU.getBytes())); + } + + System.out.println("<<<<"); + System.out.println("Elapsed time (ms): " + elapsed / 1000000); + return (responseAPDU); + } + + public String byteToHex(byte data) { + StringBuilder buf = new StringBuilder(); + buf.append(toHexChar((data >>> 4) & 0x0F)); + buf.append(toHexChar(data & 0x0F)); + return buf.toString(); + } + + public char toHexChar(int i) { + if ((0 <= i) && (i <= 9)) { + return (char) ('0' + i); + } else { + return (char) ('a' + (i - 10)); + } + } + + public String bytesToHex(byte[] data) { + StringBuilder buf = new StringBuilder(); + for (int i = 0; i < data.length; i++) { + buf.append(byteToHex(data[i])); + buf.append(" "); + } + return (buf.toString()); + } + + + public boolean prepareLocalSimulatorApplet(byte[] appletAIDArray, byte[] installData, Class appletClass) { + System.setProperty("com.licel.jcardsim.terminal.type", "2"); + m_cad = new CAD(System.getProperties()); + m_simulator = (JavaxSmartCardInterface) m_cad.getCardInterface(); + AID appletAID = new AID(appletAIDArray, (short) 0, (byte) appletAIDArray.length); + + AID appletAIDRes = m_simulator.installApplet(appletAID, appletClass, installData, (short) 0, (byte) installData.length); + return m_simulator.selectApplet(appletAID); + } + + public byte[] sendAPDUSimulator(byte apdu[]) throws Exception { + System.out.println(">>>>"); + System.out.println(bytesToHex(apdu)); + + byte[] responseBytes = m_simulator.transmitCommand(apdu); + + System.out.println(bytesToHex(responseBytes)); + System.out.println("<<<<"); + + return responseBytes; + } + + +} |
