summaryrefslogtreecommitdiff
path: root/smcc/src/main/java/at/gv/egiz/smcc/util/MSCMService.java
diff options
context:
space:
mode:
Diffstat (limited to 'smcc/src/main/java/at/gv/egiz/smcc/util/MSCMService.java')
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/util/MSCMService.java273
1 files changed, 273 insertions, 0 deletions
diff --git a/smcc/src/main/java/at/gv/egiz/smcc/util/MSCMService.java b/smcc/src/main/java/at/gv/egiz/smcc/util/MSCMService.java
new file mode 100644
index 00000000..0c705447
--- /dev/null
+++ b/smcc/src/main/java/at/gv/egiz/smcc/util/MSCMService.java
@@ -0,0 +1,273 @@
+package at.gv.egiz.smcc.util;
+
+import iaik.me.security.Cipher;
+import iaik.me.security.CryptoBag;
+import iaik.me.security.CryptoException;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import javax.smartcardio.CardChannel;
+import javax.smartcardio.CardException;
+
+public class MSCMService implements MSCMConstants {
+
+ MSCMTransfer transfer;
+
+ public MSCMService(CardChannel channel) {
+ transfer = new MSCMTransfer(channel);
+ }
+
+ public String[] getFiles(String path) throws IOException, CardException, MSCMException {
+
+ byte[] cmd = buildAPDU(DEFAULT_SERVICE_PORT,
+ HIVECODE_NAMESPACE_GEMALTO, HIVECODE_TYPE_DEFAULT,
+ HIVECODE_METHOD_GETFILES, URI, MSCMDecoder.encodeString(path));
+
+ return MSCMDecoder.decodeStringArray(
+ transfer.transfer(cmd, HIVECODE_TYPE_SYSTEM_STRING_ARRAY), 0);
+
+ }
+
+ public byte[] getFileProperties(String path) throws IOException, CardException, MSCMException {
+ byte[] cmd = buildAPDU(DEFAULT_SERVICE_PORT,
+ HIVECODE_NAMESPACE_GEMALTO, HIVECODE_TYPE_DEFAULT,
+ HIVECODE_METHOD_GETFILEPROPERTIES, URI,
+ MSCMDecoder.encodeString(path));
+
+ return MSCMDecoder.decodeByteArray(
+ transfer.transfer(cmd, HIVECODE_TYPE_SYSTEM_BYTE_ARRAY), 0);
+ }
+
+ public void verifyPin(byte role, byte[] pin) throws IOException, CardException, MSCMException {
+ byte[] cmd = buildAPDU(DEFAULT_SERVICE_PORT,
+ HIVECODE_NAMESPACE_GEMALTO, HIVECODE_TYPE_DEFAULT,
+ HIVECODE_METHOD_VERIFYPIN, URI,
+ MSCMDecoder.concatByteArrays(new byte[] { role },
+ MSCMDecoder.encodeByteArray(pin)));
+
+ transfer.transfer(cmd, HIVECODE_TYPE_SYSTEM_VOID);
+ }
+
+ public void changePIN(byte role, byte[] oldpin , byte[] newpin, int maxtries) throws IOException, CardException, MSCMException {
+ byte[] p = MSCMDecoder.concatByteArrays(new byte[] { (byte)0, role },
+ MSCMDecoder.encodeByteArray(oldpin));
+ byte[] pr = MSCMDecoder.concatByteArrays(p, MSCMDecoder.encodeByteArray(newpin));
+ byte[] pre = MSCMDecoder.concatByteArrays(pr, intToBytes(maxtries));
+
+ byte[] cmd = buildAPDU(DEFAULT_SERVICE_PORT,
+ HIVECODE_NAMESPACE_GEMALTO, HIVECODE_TYPE_DEFAULT,
+ HIVECODE_METHOD_CHANGEREFDATA, URI,
+ pre);
+
+ transfer.transfer(cmd, HIVECODE_TYPE_SYSTEM_VOID);
+ }
+
+ public void unblockPIN(byte role, byte[] oldpin , byte[] newpin, int maxtries) throws IOException, CardException, MSCMException {
+ byte[] p = MSCMDecoder.concatByteArrays(new byte[] { (byte)1, role },
+ MSCMDecoder.encodeByteArray(oldpin));
+ byte[] pr = MSCMDecoder.concatByteArrays(p, MSCMDecoder.encodeByteArray(newpin));
+ byte[] pre = MSCMDecoder.concatByteArrays(pr, intToBytes(maxtries));
+
+ byte[] cmd = buildAPDU(DEFAULT_SERVICE_PORT,
+ HIVECODE_NAMESPACE_GEMALTO, HIVECODE_TYPE_DEFAULT,
+ HIVECODE_METHOD_CHANGEREFDATA, URI,
+ pre);
+
+ transfer.transfer(cmd, HIVECODE_TYPE_SYSTEM_VOID);
+ }
+
+ public int[] queryFreeSpace() throws IOException, CardException, MSCMException {
+ byte[] cmd = buildAPDU(DEFAULT_SERVICE_PORT,
+ HIVECODE_NAMESPACE_GEMALTO, HIVECODE_TYPE_DEFAULT,
+ HIVECODE_METHOD_QUERYFREESPACE, URI,
+ null);
+
+ return MSCMDecoder.decodeIntArray(
+ transfer.transfer(cmd, HIVECODE_TYPE_SYSTEM_INT32_ARRAY), 0);
+ }
+
+ public void forceGC() throws IOException, CardException, MSCMException {
+ byte[] cmd = buildAPDU(DEFAULT_SERVICE_PORT,
+ HIVECODE_NAMESPACE_GEMALTO, HIVECODE_TYPE_DEFAULT,
+ HIVECODE_METHOD_FORCEGC, URI,
+ null);
+ transfer.transfer(cmd, HIVECODE_TYPE_SYSTEM_VOID);
+ }
+
+ public byte[] readFile(String path) throws IOException, CardException, MSCMException {
+ byte[] cmd = buildAPDU(DEFAULT_SERVICE_PORT,
+ HIVECODE_NAMESPACE_GEMALTO, HIVECODE_TYPE_DEFAULT,
+ HIVECODE_METHOD_READFILE, URI,
+ MSCMDecoder.concatByteArrays(MSCMDecoder.encodeString(path),
+ intToBytes(0) ));
+
+ return MSCMDecoder.decodeByteArray(
+ transfer.transfer(cmd, HIVECODE_TYPE_SYSTEM_BYTE_ARRAY), 0);
+ }
+
+ public byte[] privateKeyDecrypt(byte ctrIdx, byte keyType, byte[] data)
+ throws IOException, CardException, MSCMException {
+ byte[] cmd = buildAPDU(DEFAULT_SERVICE_PORT,
+ HIVECODE_NAMESPACE_GEMALTO, HIVECODE_TYPE_DEFAULT,
+ HIVECODE_METHOD_PRIVATEKEYDECRYPT, URI,
+ MSCMDecoder.concatByteArrays(new byte[] { ctrIdx,
+ keyType }, MSCMDecoder.encodeByteArray(data)));
+
+ return MSCMDecoder.decodeByteArray(
+ transfer.transfer(cmd, HIVECODE_TYPE_SYSTEM_BYTE_ARRAY), 0);
+ }
+
+ public int getTriesRemaining(byte role) throws IOException, CardException, MSCMException {
+ byte[] cmd = buildAPDU(DEFAULT_SERVICE_PORT,
+ HIVECODE_NAMESPACE_GEMALTO, HIVECODE_TYPE_DEFAULT,
+ HIVECODE_METHOD_GETTRIESREMAINING, URI, new byte[] { role });
+
+ return bytesToInt(transfer.transfer(cmd, HIVECODE_TYPE_SYSTEM_INT32), 0);
+ }
+
+ public String getVersion() throws IOException, CardException, MSCMException {
+
+ byte[] cmd = buildAPDU(DEFAULT_SERVICE_PORT,
+ HIVECODE_NAMESPACE_GEMALTO, HIVECODE_TYPE_DEFAULT,
+ HIVECODE_METHOD_GETVERSION, URI, null);
+
+ return MSCMDecoder.decodeString(
+ transfer.transfer(cmd, HIVECODE_TYPE_SYSTEM_STRING), 0);
+
+ }
+
+ public byte[] getContainerProperty(byte ctrIndex, byte property, byte flags)
+ throws IOException, CardException, MSCMException {
+ byte[] cmd = buildAPDU(DEFAULT_SERVICE_PORT,
+ HIVECODE_NAMESPACE_GEMALTO, HIVECODE_TYPE_DEFAULT,
+ HIVECODE_METHOD_GETCONTAINERPROPERTY, URI, new byte[] {
+ ctrIndex, property, flags });
+
+ return transfer.transfer(cmd, HIVECODE_TYPE_SYSTEM_BYTE_ARRAY);
+ }
+
+ public byte[] getCardProperty(byte property, byte flags)
+ throws IOException, CardException, MSCMException {
+
+ byte[] cmd = buildAPDU(DEFAULT_SERVICE_PORT,
+ HIVECODE_NAMESPACE_GEMALTO, HIVECODE_TYPE_DEFAULT,
+ HIVECODE_METHOD_GETCARDPROPERTY, URI, new byte[] { property,
+ flags });
+
+ return transfer.transfer(cmd, HIVECODE_TYPE_SYSTEM_BYTE_ARRAY);
+ }
+
+ public static String bytArrayToHex(byte[] a) {
+ StringBuilder sb = new StringBuilder();
+ for (byte b : a)
+ sb.append(String.format("%02X ", b & 0xff));
+ return sb.toString();
+ }
+
+ public static String bytArrayToHex(byte[] a, int offset) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = offset; i < a.length; i++) {
+ byte b = a[i];
+ sb.append(String.format("%02X ", b & 0xff));
+ }
+ return sb.toString();
+ }
+
+ public static byte[] shortToBytes(short x) {
+ byte[] ret = new byte[2];
+ ret[1] = (byte) (x & 0xff);
+ ret[0] = (byte) ((x >> 8) & 0xff);
+ return ret;
+ }
+
+ public static byte[] intToBytes(int x) {
+ byte[] ret = new byte[4];
+ ret[3] = (byte) (x & 0xff);
+ ret[2] = (byte) ((x >> 8) & 0xff);
+ ret[1] = (byte) ((x >> 16) & 0xff);
+ ret[0] = (byte) ((x >> 24) & 0xff);
+ return ret;
+ }
+
+ public static int bytesToInt(byte[] by, int offset) {
+ int value = 0;
+ for (int i = 0; i < 4 && i + offset < by.length; i++) {
+ value <<= 8;
+ value |= (int) by[offset + i] & 0xFF;
+ }
+ return value;
+ }
+
+ public static short bytesToShort(byte[] by, int offset) {
+ short value = 0;
+ for (int i = 0; i < 2 && i + offset < by.length; i++) {
+ value <<= 8;
+ value |= (short) by[i + offset] & 0xFF;
+ }
+ return value;
+ }
+
+ public byte[] buildAPDU(short servicePort, int hiveServiceNamespace,
+ short hiveServiceType, short hiveMethod, String serviceName,
+ byte[] arguments) throws IOException {
+ byte[] c1 = new byte[1];
+ byte[] c2 = new byte[1];
+ byte[] encodedServiceName = serviceName.getBytes("UTF-8");
+ c1[0] = (byte) 0xD8;
+ c2[0] = (byte) 0x6F;
+
+ ByteArrayOutputStream payloadbuffer = new ByteArrayOutputStream();
+
+ payloadbuffer.write(c1);
+ payloadbuffer.write(shortToBytes(servicePort));
+ payloadbuffer.write(c2);
+ payloadbuffer.write(intToBytes(hiveServiceNamespace));
+ payloadbuffer.write(shortToBytes(hiveServiceType));
+ payloadbuffer.write(shortToBytes(hiveMethod));
+ payloadbuffer.write(shortToBytes((short) encodedServiceName.length));
+ payloadbuffer.write(encodedServiceName);
+ if (arguments != null) {
+ payloadbuffer.write(arguments);
+ }
+
+ return payloadbuffer.toByteArray();
+ }
+
+
+ public byte[] cryptoResponse(byte[] challenge, byte[] key) {
+ try {
+ Cipher cipher = Cipher.getInstance("DESede/ECB/NoPadding");
+ cipher.init(Cipher.ENCRYPT_MODE, CryptoBag.makeSecretKey(key));
+
+ /*System.out.println("Crypto IV: "
+ + MSCMService.bytArrayToHex(cipher.getIV().getEncoded()));*/
+ byte[] result = cipher.doFinal(challenge);
+ System.out.println("Crypto result: " + MSCMService.bytArrayToHex(result));
+ return result;
+ } catch (CryptoException e) {
+ System.out.println("Failed to get crypto stuff" + e.getMessage());
+ return null;
+ }
+ }
+
+ public void doExternalAuthentication(byte[] response)
+ throws IOException, CardException, MSCMException {
+ byte[] cmd = buildAPDU(DEFAULT_SERVICE_PORT,
+ HIVECODE_NAMESPACE_GEMALTO, HIVECODE_TYPE_DEFAULT,
+ HIVECODE_METHOD_EXTAUTH, URI,
+ MSCMDecoder.encodeByteArray(response));
+
+ transfer.transfer(cmd, HIVECODE_TYPE_SYSTEM_VOID);
+ }
+
+ public byte[] getChallenge() throws IOException, CardException, MSCMException {
+ byte[] cmd = buildAPDU(DEFAULT_SERVICE_PORT,
+ HIVECODE_NAMESPACE_GEMALTO, HIVECODE_TYPE_DEFAULT,
+ HIVECODE_METHOD_GETCHALLENGE, URI,
+ null);
+
+ return MSCMDecoder.decodeByteArray(
+ transfer.transfer(cmd, HIVECODE_TYPE_SYSTEM_BYTE_ARRAY), 0);
+ }
+}