summaryrefslogtreecommitdiff
path: root/src/cz/crcs/ectester/reader/CardMngr.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/cz/crcs/ectester/reader/CardMngr.java')
-rw-r--r--src/cz/crcs/ectester/reader/CardMngr.java179
1 files changed, 134 insertions, 45 deletions
diff --git a/src/cz/crcs/ectester/reader/CardMngr.java b/src/cz/crcs/ectester/reader/CardMngr.java
index e11bcb3..1e42c52 100644
--- a/src/cz/crcs/ectester/reader/CardMngr.java
+++ b/src/cz/crcs/ectester/reader/CardMngr.java
@@ -2,11 +2,12 @@ package cz.crcs.ectester.reader;
import com.licel.jcardsim.io.CAD;
import com.licel.jcardsim.io.JavaxSmartCardInterface;
+import cz.crcs.ectester.common.util.ByteUtil;
import javacard.framework.AID;
+import javacard.framework.ISO7816;
import javax.smartcardio.*;
-import java.util.List;
-import java.util.Scanner;
+import java.util.*;
/**
* @author Petr Svenda petr@svenda.com
@@ -79,7 +80,7 @@ public class CardMngr {
//reset the card
if (verbose)
- System.out.println(Util.bytesToHex(card.getATR().getBytes()));
+ System.out.println(ByteUtil.bytesToHex(card.getATR().getBytes()));
cardFound = true;
}
@@ -108,7 +109,7 @@ public class CardMngr {
try {
card = terminal.connect("*");
ATR atr = card.getATR();
- System.out.println(terminalIndex + " : " + terminal.getName() + " - " + Util.bytesToHex(atr.getBytes()));
+ System.out.println(terminalIndex + " : " + terminal.getName() + " - " + ByteUtil.bytesToHex(atr.getBytes()));
terminalIndex++;
} catch (CardException ex) {
ex.printStackTrace(System.out);
@@ -164,50 +165,138 @@ public class CardMngr {
}
}
- public byte[] getCPLCData() throws Exception {
- byte[] data;
+ // Functions for CPLC taken and modified from https://github.com/martinpaljak/GlobalPlatformPro
+ private static final byte CLA_GP = (byte) 0x80;
+ private static final byte ISO7816_INS_GET_DATA = (byte) 0xCA;
+ private static final byte[] FETCH_GP_CPLC_APDU = {CLA_GP, ISO7816_INS_GET_DATA, (byte) 0x9F, (byte) 0x7F, (byte) 0x00};
+ private static final byte[] FETCH_ISO_CPLC_APDU = {ISO7816.CLA_ISO7816, ISO7816_INS_GET_DATA, (byte) 0x9F, (byte) 0x7F, (byte) 0x00};
+ private static final byte[] FETCH_GP_CARDDATA_APDU = {CLA_GP, ISO7816_INS_GET_DATA, (byte) 0x00, (byte) 0x66, (byte) 0x00};
- // 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;
+ public byte[] fetchCPLC() throws CardException {
+ // Try CPLC via GP
+ ResponseAPDU resp = send(FETCH_GP_CPLC_APDU);
+ // If GP CLA fails, try with ISO
+ if (resp.getSW() == (ISO7816.SW_CLA_NOT_SUPPORTED & 0xffff)) {
+ resp = send(FETCH_ISO_CPLC_APDU);
+ }
+ if (resp.getSW() == (ISO7816.SW_NO_ERROR & 0xffff)) {
+ return resp.getData();
+ }
+ return null;
+ }
- ResponseAPDU resp = send(apdu);
- if (resp.getSW() != 0x9000) { // 0x9000 is "OK"
- System.err.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
+ public static final class CPLC {
+ public enum Field {
+ ICFabricator,
+ ICType,
+ OperatingSystemID,
+ OperatingSystemReleaseDate,
+ OperatingSystemReleaseLevel,
+ ICFabricationDate,
+ ICSerialNumber,
+ ICBatchIdentifier,
+ ICModuleFabricator,
+ ICModulePackagingDate,
+ ICCManufacturer,
+ ICEmbeddingDate,
+ ICPrePersonalizer,
+ ICPrePersonalizationEquipmentDate,
+ ICPrePersonalizationEquipmentID,
+ ICPersonalizer,
+ ICPersonalizationDate,
+ ICPersonalizationEquipmentID
}
- return data;
- }
+ private Map<Field, byte[]> values = new TreeMap<>();
- 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;
+ public CPLC(byte[] data) {
+ if (data == null) {
+ return;
+ }
+ if (data.length < 3 || data[2] != 0x2A) {
+ throw new IllegalArgumentException("CPLC must be 0x2A bytes long");
+ }
+ //offset = TLVUtils.skipTag(data, offset, (short)0x9F7F);
+ short offset = 3;
+ values.put(Field.ICFabricator, Arrays.copyOfRange(data, offset, offset + 2));
+ offset += 2;
+ values.put(Field.ICType, Arrays.copyOfRange(data, offset, offset + 2));
+ offset += 2;
+ values.put(Field.OperatingSystemID, Arrays.copyOfRange(data, offset, offset + 2));
+ offset += 2;
+ values.put(Field.OperatingSystemReleaseDate, Arrays.copyOfRange(data, offset, offset + 2));
+ offset += 2;
+ values.put(Field.OperatingSystemReleaseLevel, Arrays.copyOfRange(data, offset, offset + 2));
+ offset += 2;
+ values.put(Field.ICFabricationDate, Arrays.copyOfRange(data, offset, offset + 2));
+ offset += 2;
+ values.put(Field.ICSerialNumber, Arrays.copyOfRange(data, offset, offset + 4));
+ offset += 4;
+ values.put(Field.ICBatchIdentifier, Arrays.copyOfRange(data, offset, offset + 2));
+ offset += 2;
+ values.put(Field.ICModuleFabricator, Arrays.copyOfRange(data, offset, offset + 2));
+ offset += 2;
+ values.put(Field.ICModulePackagingDate, Arrays.copyOfRange(data, offset, offset + 2));
+ offset += 2;
+ values.put(Field.ICCManufacturer, Arrays.copyOfRange(data, offset, offset + 2));
+ offset += 2;
+ values.put(Field.ICEmbeddingDate, Arrays.copyOfRange(data, offset, offset + 2));
+ offset += 2;
+ values.put(Field.ICPrePersonalizer, Arrays.copyOfRange(data, offset, offset + 2));
+ offset += 2;
+ values.put(Field.ICPrePersonalizationEquipmentDate, Arrays.copyOfRange(data, offset, offset + 2));
+ offset += 2;
+ values.put(Field.ICPrePersonalizationEquipmentID, Arrays.copyOfRange(data, offset, offset + 4));
+ offset += 4;
+ values.put(Field.ICPersonalizer, Arrays.copyOfRange(data, offset, offset + 2));
+ offset += 2;
+ values.put(Field.ICPersonalizationDate, Arrays.copyOfRange(data, offset, offset + 2));
+ offset += 2;
+ values.put(Field.ICPersonalizationEquipmentID, Arrays.copyOfRange(data, offset, offset + 4));
+ offset += 4;
+ }
- ResponseAPDU resp = send(apdu);
+ public Map<Field, byte[]> values() {
+ return values;
+ }
+ }
- if (verbose)
- System.out.println("Response: " + Integer.toHexString(resp.getSW()));
+ public CPLC getCPLC() throws CardException {
+ byte[] data = fetchCPLC();
+ return new CPLC(data);
+ }
- if (resp.getSW() != 0x6D00) { // Note: 0x6D00 is SW_INS_NOT_SUPPORTED
- // something?
- }
+ public static String mapCPLCField(CPLC.Field field, byte[] value) {
+ switch (field) {
+ case ICFabricator:
+ String id = ByteUtil.bytesToHex(value, false);
+ String fabricatorName = "unknown";
+ if (id.equals("3060")) {
+ fabricatorName = "Renesas";
+ }
+ if (id.equals("4090")) {
+ fabricatorName = "Infineon";
+ }
+ if (id.equals("4180")) {
+ fabricatorName = "Atmel";
+ }
+ if (id.equals("4250")) {
+ fabricatorName = "Samsung";
+ }
+ if (id.equals("4790")) {
+ fabricatorName = "NXP";
+ }
+ return id + " (" + fabricatorName + ")";
+ default:
+ return ByteUtil.bytesToHex(value, false);
+ }
+ }
+
+ public ATR getATR() {
+ if (simulate) {
+ return new ATR(simulator.getATR());
+ } else {
+ return card.getATR();
}
}
@@ -226,7 +315,7 @@ public class CardMngr {
System.out.println(">>>>");
System.out.println(apdu);
- System.out.println(Util.bytesToHex(apdu.getBytes()));
+ System.out.println(ByteUtil.bytesToHex(apdu.getBytes()));
}
long elapsed = -System.nanoTime();
@@ -237,7 +326,7 @@ public class CardMngr {
if (verbose) {
System.out.println(responseAPDU);
- System.out.println(Util.bytesToHex(responseAPDU.getBytes()));
+ System.out.println(ByteUtil.bytesToHex(responseAPDU.getBytes()));
}
if (responseAPDU.getSW1() == (byte) 0x61) {
@@ -247,7 +336,7 @@ public class CardMngr {
responseAPDU = channel.transmit(apduToSend);
if (verbose)
- System.out.println(Util.bytesToHex(responseAPDU.getBytes()));
+ System.out.println(ByteUtil.bytesToHex(responseAPDU.getBytes()));
}
if (verbose) {
@@ -276,7 +365,7 @@ public class CardMngr {
if (verbose) {
System.out.println(">>>>");
System.out.println(apdu);
- System.out.println(Util.bytesToHex(apdu.getBytes()));
+ System.out.println(ByteUtil.bytesToHex(apdu.getBytes()));
}
ResponseAPDU response = simulator.transmitCommand(apdu);
@@ -284,7 +373,7 @@ public class CardMngr {
if (verbose) {
System.out.println(response);
- System.out.println(Util.bytesToHex(responseBytes));
+ System.out.println(ByteUtil.bytesToHex(responseBytes));
System.out.println("<<<<");
}