summaryrefslogtreecommitdiff
path: root/smcc/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'smcc/src/main')
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/GemaltoNetV2_0Card.java513
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java12
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/T0CardChannel.java4
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/util/MSCMConstants.java220
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/util/MSCMDecoder.java259
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/util/MSCMException.java23
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/util/MSCMService.java273
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/util/MSCMTransfer.java146
8 files changed, 1448 insertions, 2 deletions
diff --git a/smcc/src/main/java/at/gv/egiz/smcc/GemaltoNetV2_0Card.java b/smcc/src/main/java/at/gv/egiz/smcc/GemaltoNetV2_0Card.java
new file mode 100644
index 00000000..3bea0753
--- /dev/null
+++ b/smcc/src/main/java/at/gv/egiz/smcc/GemaltoNetV2_0Card.java
@@ -0,0 +1,513 @@
+package at.gv.egiz.smcc;
+
+import iaik.me.security.CryptoBag;
+import iaik.me.security.CryptoException;
+import iaik.me.security.MessageDigest;
+import iaik.me.security.cipher.TripleDES;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.util.zip.DataFormatException;
+import java.util.zip.Inflater;
+
+import javax.print.attribute.standard.Severity;
+import javax.smartcardio.Card;
+import javax.smartcardio.CardChannel;
+import javax.smartcardio.CardException;
+import javax.smartcardio.CardTerminal;
+import javax.smartcardio.CommandAPDU;
+import javax.smartcardio.ResponseAPDU;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import sun.security.rsa.RSAPadding;
+import at.gv.egiz.smcc.pin.gui.ModifyPINGUI;
+import at.gv.egiz.smcc.pin.gui.PINGUI;
+import at.gv.egiz.smcc.util.MSCMException;
+import at.gv.egiz.smcc.util.MSCMService;
+
+public class GemaltoNetV2_0Card extends AbstractSignatureCard implements
+ PINMgmtSignatureCard {
+
+ private final Logger log = LoggerFactory
+ .getLogger(GemaltoNetV2_0Card.class);
+
+ PinInfo pinPinInfo;
+ PinInfo pukPinInfo;
+
+ public void init(Card card, CardTerminal cardTerminal) {
+ super.init(card, cardTerminal);
+
+ log.info("GemaltoNetV2 card found");
+
+ pinPinInfo = new PinInfo(4, 64, "[0-9]",
+ "at/gv/egiz/smcc/GemaltoNetV2_0Card", "sig.pin", (byte) 1,
+ new byte[] {}, 5);
+
+ pukPinInfo = new PinInfo(48, 48, "[0-9A-F]",
+ "at/gv/egiz/smcc/GemaltoNetV2_0Card", "sig.puk", (byte) 2,
+ new byte[] {}, 3);
+ }
+
+ public static byte[] hexStringToByteArray(String s) {
+ int len = s.length();
+ byte[] data = new byte[len / 2];
+ for (int i = 0; i < len; i += 2) {
+ data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ + Character.digit(s.charAt(i+1), 16));
+ }
+ return data;
+ }
+
+ @Override
+ public byte[] getCertificate(KeyboxName keyboxName, PINGUI pinGUI)
+ throws SignatureCardException, InterruptedException {
+ try {
+ CardChannel channel = this.getCardChannel();// this.getCard().getBasicChannel();
+ MSCMService service = new MSCMService(channel);
+ byte[] filecnt = service.readFile("mscp\\ksc00");
+
+ Inflater inflater = new Inflater();
+ inflater.setInput(filecnt, 4, filecnt.length - 4);
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ while (!inflater.finished()) {
+ byte[] uncompressedData = new byte[1024];
+ int compressLength = inflater.inflate(uncompressedData, 0,
+ uncompressedData.length);
+ // System.out.println(compressedData);
+ out.write(uncompressedData, 0, compressLength);
+ }
+ byte[] uncompressed = out.toByteArray();
+ return uncompressed;
+ } catch (CardException e) {
+ log.info("Failed to get certificate.", e);
+ throw new SignatureCardException(e);
+ } catch (DataFormatException e) {
+ log.info("Failed to get certificate.", e);
+ throw new SignatureCardException(e);
+ } catch (IOException e) {
+ log.info("Failed to get certificate.", e);
+ throw new SignatureCardException(e);
+ } catch (MSCMException e) {
+ log.info("Failed to get certificate.", e);
+ throw new SignatureCardException(e);
+ }
+ }
+
+ @Override
+ public byte[] getInfobox(String infobox, PINGUI pinGUI, String domainId)
+ throws SignatureCardException, InterruptedException {
+ throw new IllegalArgumentException("Infobox '" + infobox
+ + "' not supported.");
+ }
+
+ @Override
+ public byte[] createSignature(InputStream input, KeyboxName keyboxName,
+ PINGUI pinGUI, String alg) throws SignatureCardException,
+ InterruptedException, IOException {
+
+ MessageDigest md;
+ try {
+ if (KeyboxName.SECURE_SIGNATURE_KEYPAIR.equals(keyboxName)
+ && (alg == null || "http://www.w3.org/2000/09/xmldsig#rsa-sha1"
+ .equals(alg))) {
+ md = MessageDigest.getInstance("SHA-1");
+ } else if (KeyboxName.SECURE_SIGNATURE_KEYPAIR.equals(keyboxName)
+ && ("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"
+ .equals(alg))) {
+ md = MessageDigest.getInstance("SHA-256");
+ } else {
+ throw new SignatureCardException(
+ "Card does not support signature algorithm " + alg
+ + ".");
+ }
+ } catch (CryptoException e) {
+ log.error("Failed to get MessageDigest.", e);
+ throw new SignatureCardException(e);
+ }
+
+ byte[] digest = new byte[md.getDigestLength()];
+ for (int l; (l = input.read(digest)) != -1;) {
+ md.update(digest, 0, l);
+ }
+ digest = md.digest();
+
+ try {
+ RSAPadding padding = RSAPadding.getInstance(
+ RSAPadding.PAD_BLOCKTYPE_1, 256);
+
+ CardChannel channel = this.getCardChannel();
+ MSCMService service = new MSCMService(channel);
+
+ verifyPINLoop(channel, pinPinInfo, pinGUI);
+
+ byte[] paded = padding.pad(digest);
+ byte[] sign = service.privateKeyDecrypt((byte) 0, (byte) 2, paded);
+ return sign;
+ } catch (Throwable e) {
+ log.warn("Failed to execute command.", e);
+ throw new SignatureCardException("Failed to access card.", e);
+ }
+ }
+
+ protected void unblockPINLoop(CardChannel channel,
+ ModifyPINGUI provider, PinInfo pin) throws InterruptedException, CardException, SignatureCardException{
+
+ int retries = -1;
+ do {
+ retries = exec_unblockPIN(channel, provider, pin);
+ } while (retries > 0);
+ }
+
+ /*
+ * Unblock PIN with PUK code
+ */
+ protected int exec_unblockPIN(CardChannel channel, ModifyPINGUI changePINGUI, PinInfo pin)
+ throws InterruptedException, CardException, SignatureCardException {
+
+
+ char[] oldPIN = changePINGUI.providePUK(pin, pukPinInfo,
+ pukPinInfo.retries);
+
+ char[] newPIN = changePINGUI.provideNewPIN(pin);
+
+ byte[] ascii_pin = encodePIN(newPIN);
+
+ MSCMService service = new MSCMService(channel);
+
+ try {
+ byte[] key = hexStringToByteArray(new String(oldPIN));
+ if(key.length != 24) {
+ throw new SignatureCardException("Invalid ADMIN PIN (not 24 bytes long)!");
+ }
+ byte[] challenge = service.getChallenge();
+ byte[] response = service.cryptoResponse(challenge, key);
+ service.unblockPIN((byte) 1, response, ascii_pin, pin.maxRetries);
+ pin.setActive(pin.maxRetries);
+ return -1;
+ } catch (IOException e) {
+ String msg = "SET PIN failed.";
+ log.info(msg);
+ pin.setUnknown();
+ throw new SignatureCardException(msg, e);
+ } catch (MSCMException e) {
+ log.info(e.getMessage());
+ try {
+ return service.getTriesRemaining((byte) 2);
+ } catch (IOException ec) {
+ String msg = "getTriesRemaining failed.";
+ log.info(msg);
+ pin.setUnknown();
+ throw new SignatureCardException(msg, ec);
+ } catch (MSCMException e1) {
+ String msg = "getTriesRemaining failed.";
+ log.info(msg);
+ pin.setUnknown();
+ throw new SignatureCardException(msg, e1);
+ }
+ }
+
+ }
+
+ protected void verifyPINLoop(CardChannel channel, PinInfo spec,
+ PINGUI provider) throws InterruptedException, CardException,
+ SignatureCardException {
+
+ int retries = -1;
+ do {
+ retries = verifyPIN(channel, spec, provider, retries);
+ } while (retries > 0);
+ }
+
+ /*
+ * Verify PIN/PUK entry
+ */
+ protected int verifyPUK(CardChannel channel, PinInfo pinInfo,
+ PINGUI provider, int retries) throws InterruptedException,
+ CardException, SignatureCardException {
+
+ char[] pin = provider.providePIN(pinInfo, pinInfo.retries);
+
+ byte[] ascii_pin = hexStringToByteArray(new String(pin));
+
+ if(ascii_pin.length != 24) {
+ throw new SignatureCardException("Invalid ADMIN PIN (not 24 bytes long)!");
+ }
+
+ MSCMService service = new MSCMService(channel);
+
+ try {
+ byte[] challenge = service.getChallenge();
+ byte[] response = service.cryptoResponse(challenge, ascii_pin);
+ service.doExternalAuthentication(response);
+ pinInfo.setActive(pinInfo.maxRetries);
+ return -1;
+ } catch (MSCMException e) {
+ try {
+ int tries = service.getTriesRemaining(pinInfo.getKID());
+ pinInfo.setActive(tries);
+ return tries;
+ } catch (Exception ex) {
+ log.error("Failed to get remaining tries");
+ throw new SignatureCardException(ex);
+ }
+ } catch (IOException e) {
+ log.error("Failed to verify PIN");
+ throw new SignatureCardException(e);
+ }
+ }
+
+ /*
+ * Verify PIN/PUK entry
+ */
+ protected int verifyPIN(CardChannel channel, PinInfo pinInfo,
+ PINGUI provider, int retries) throws InterruptedException,
+ CardException, SignatureCardException {
+
+ char[] pin = provider.providePIN(pinInfo, pinInfo.retries);
+
+ byte[] ascii_pin = encodePIN(pin);
+ MSCMService service = new MSCMService(channel);
+
+ try {
+ service.verifyPin(pinInfo.getKID(), ascii_pin);
+ pinInfo.setActive(pinInfo.maxRetries);
+ return -1;
+ } catch (MSCMException e) {
+ try {
+ int tries = service.getTriesRemaining(pinInfo.getKID());
+ if(tries == 0) {
+ pinInfo.setBlocked();
+ throw new LockedException();
+ }
+ pinInfo.setActive(tries);
+ return tries;
+ } catch (IOException ex) {
+ log.error("Failed to get remaining tries");
+ throw new SignatureCardException(ex);
+ } catch (MSCMException e1) {
+ log.error("Failed to get remaining tries");
+ throw new SignatureCardException(e1);
+ }
+ } catch (IOException e) {
+ log.error("Failed to verify PIN");
+ throw new SignatureCardException(e);
+ }
+ }
+
+ protected void changePINLoop(CardChannel channel, ModifyPINGUI provider,
+ PinInfo pin) throws InterruptedException, CardException,
+ SignatureCardException {
+
+ int retries = -1;
+ do {
+ if(pin.getKID() == 2) {
+ retries = exec_changePUK(channel, provider, pin);
+ } else {
+ retries = exec_changePIN(channel, provider, pin);
+ }
+ } while (retries > 0);
+ }
+
+ protected byte[] cryptoChallenge(byte[] challenge, byte[] pass) {
+ try {
+ byte[] iv = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00 };
+ TripleDES cip = new TripleDES();
+ cip.init(TripleDES.ENCRYPT_MODE, CryptoBag.makeSecretKey(pass),
+ CryptoBag.makeIV(iv), null);
+ log.info("Crypto IV: "
+ + MSCMService.bytArrayToHex(cip.getIV().getEncoded()));
+ byte[] result = cip.doFinal(challenge);
+ log.info("Crypto result: " + MSCMService.bytArrayToHex(result));
+ return result;
+ } catch (CryptoException e) {
+ log.error("Failed to get crypto stuff", e);
+ return null;
+ }
+ }
+
+ /*
+ * Unblock PIN with PUK code
+ */
+ protected int exec_changePUK(CardChannel channel,
+ ModifyPINGUI changePINGUI, PinInfo pin)
+ throws InterruptedException, CardException, SignatureCardException {
+
+ char[] oldPIN = changePINGUI.providePUK(pin, pukPinInfo,
+ pukPinInfo.retries);
+
+ char[] newPIN = changePINGUI.provideNewPIN(pin);
+
+ MSCMService service = new MSCMService(channel);
+
+ try {
+ byte[] key = hexStringToByteArray(new String(oldPIN));
+ byte[] keynew = hexStringToByteArray(new String(newPIN));
+ if(key.length != 24) {
+ throw new SignatureCardException("Invalid ADMIN PIN (not 24 bytes long)!");
+ }
+ if(keynew.length != 24) {
+ throw new SignatureCardException("Invalid ADMIN PIN (not 24 bytes long)!");
+ }
+ byte[] challenge = service.getChallenge();
+ byte[] response = service.cryptoResponse(challenge, key);
+ service.changePIN((byte) 2, response, keynew, pin.maxRetries);
+ pin.setActive(pin.maxRetries);
+ return -1;
+ } catch (IOException e) {
+ String msg = "SET PIN failed.";
+ log.info(msg);
+ pin.setUnknown();
+ throw new SignatureCardException(msg, e);
+ } catch (MSCMException e) {
+ log.info(e.getMessage());
+ try {
+ int tries = service.getTriesRemaining(pin.getKID());
+ if(tries == 0) {
+ pin.setBlocked();
+ throw new LockedException();
+ }
+ pin.setActive(tries);
+ return tries;
+ } catch (IOException ec) {
+ String msg = "getTriesRemaining failed.";
+ log.info(msg);
+ pin.setUnknown();
+ throw new SignatureCardException(msg, ec);
+ } catch (MSCMException e1) {
+ String msg = "getTriesRemaining failed.";
+ log.info(msg);
+ pin.setUnknown();
+ throw new SignatureCardException(msg, e1);
+ }
+ }
+
+ }
+
+ /*
+ * Unblock PIN with PUK code
+ */
+ protected int exec_changePIN(CardChannel channel,
+ ModifyPINGUI changePINGUI, PinInfo pin)
+ throws InterruptedException, CardException, SignatureCardException {
+
+ char[] oldPIN = changePINGUI.providePUK(pin, pinPinInfo,
+ pinPinInfo.retries);
+
+ char[] newPIN = changePINGUI.provideNewPIN(pin);
+
+ byte[] ascii_puk = encodePIN(oldPIN);
+
+ byte[] ascii_pin = encodePIN(newPIN);
+
+ MSCMService service = new MSCMService(channel);
+
+ try {
+ // service -> change pin
+ service.changePIN((byte) 1, ascii_puk, ascii_pin,
+ pin.maxRetries);
+ pin.setActive(pin.maxRetries);
+ return -1;
+ } catch (IOException e) {
+ String msg = "SET PIN failed.";
+ log.info(msg);
+ pin.setUnknown();
+ throw new SignatureCardException(msg, e);
+ } catch (MSCMException e) {
+ log.info(e.getMessage());
+ try {
+ int tries = service.getTriesRemaining(pin.getKID());
+ if(tries == 0) {
+ pin.setBlocked();
+ throw new LockedException();
+ }
+ pin.setActive(tries);
+ return tries;
+ } catch (IOException ec) {
+ String msg = "getTriesRemaining failed.";
+ log.info(msg);
+ pin.setUnknown();
+ throw new SignatureCardException(msg, ec);
+ } catch (MSCMException e1) {
+ String msg = "getTriesRemaining failed.";
+ log.info(msg);
+ pin.setUnknown();
+ throw new SignatureCardException(msg, e1);
+ }
+ }
+
+ }
+
+ private byte[] encodePIN(char[] pin) {
+ return Charset.forName("ASCII").encode(CharBuffer.wrap(pin)).array();
+ }
+
+ // @Override
+ public PinInfo[] getPinInfos() throws SignatureCardException {
+ return new PinInfo[] { pinPinInfo, pukPinInfo };
+ }
+
+ // @Override
+ public void verifyPIN(PinInfo pinInfo, PINGUI pinGUI)
+ throws LockedException, NotActivatedException, CancelledException,
+ SignatureCardException, InterruptedException {
+
+ try {
+ CardChannel channel = this.getCardChannel();
+ if(pinInfo.getKID() == 2) {
+ verifyPUK(channel, pinInfo, pinGUI, pinInfo.retries);
+ } else {
+ verifyPIN(channel, pinInfo, pinGUI, pinInfo.retries);
+ }
+ } catch (CardException e) {
+ log.error("Failed to verify PIN");
+ throw new SignatureCardException(e);
+ }
+ }
+
+ // @Override
+ public void changePIN(PinInfo pinInfo, ModifyPINGUI changePINGUI)
+ throws LockedException, NotActivatedException, CancelledException,
+ PINFormatException, SignatureCardException, InterruptedException {
+ try {
+ changePINLoop(getCardChannel(), changePINGUI, pinInfo);
+ } catch (CardException e) {
+ log.error("Failed to change PIN");
+ throw new SignatureCardException(e);
+ }
+ }
+
+ // @Override
+ public void activatePIN(PinInfo pinInfo, ModifyPINGUI activatePINGUI)
+ throws CancelledException, SignatureCardException,
+ InterruptedException {
+ log.error("ACTIVATE PIN not supported by Cypriotic EID");
+ throw new SignatureCardException(
+ "PIN activation not supported by this card.");
+ }
+
+ // @Override
+ public void unblockPIN(PinInfo pinInfo, ModifyPINGUI pukGUI)
+ throws CancelledException, SignatureCardException,
+ InterruptedException {
+ if(pinInfo.getKID() == 2) {
+ throw new SignatureCardException("Unable to unblock PUK");
+ } else {
+ CardChannel channel = getCardChannel();
+
+ try {
+ unblockPINLoop(channel, pukGUI, pinInfo);
+ } catch (CardException e) {
+ log.info("Failed to unblock PIN.", e);
+ throw new SignatureCardException("Failed to unblock PIN.", e);
+ }
+ }
+ }
+}
diff --git a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java
index 2d43e375..7c1e56a2 100644
--- a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java
+++ b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java
@@ -405,6 +405,18 @@ public class SignatureCardFactory {
(byte) 0xff, (byte) 0xff, (byte) 0xff},
"at.gv.egiz.smcc.CypriotEID"));
+ // Gemalto .NET V2.0
+ supportedCards.add(new SupportedCard(
+ // ATR [3B:16:96:41:73:74:72:69:64]
+ new byte[] { (byte) 0x3b, (byte) 0x16, (byte) 0x96,
+ (byte) 0x41, (byte) 0x73, (byte) 0x74, (byte) 0x72,
+ (byte) 0x69, (byte) 0x64},
+ // mas (ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff)
+ new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff},
+ "at.gv.egiz.smcc.GemaltoNetV2_0Card"));
+
// ES DNIe
supportedCards.add(new SupportedCard(
// ATR [3b:7f:38:00:00:00:6a:44:4e:49:65:20:02:4c:34:01:13:03:90:00]
diff --git a/smcc/src/main/java/at/gv/egiz/smcc/T0CardChannel.java b/smcc/src/main/java/at/gv/egiz/smcc/T0CardChannel.java
index 9ae85d04..001f6ec9 100644
--- a/smcc/src/main/java/at/gv/egiz/smcc/T0CardChannel.java
+++ b/smcc/src/main/java/at/gv/egiz/smcc/T0CardChannel.java
@@ -26,6 +26,7 @@ package at.gv.egiz.smcc;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.nio.ByteBuffer;
import javax.smartcardio.CardChannel;
import javax.smartcardio.CardException;
@@ -35,10 +36,9 @@ import javax.smartcardio.ResponseAPDU;
public class T0CardChannel extends LogCardChannel {
public T0CardChannel(CardChannel channel) {
-
super(channel);
}
-
+
@Override
public ResponseAPDU transmit(CommandAPDU command) throws CardException {
diff --git a/smcc/src/main/java/at/gv/egiz/smcc/util/MSCMConstants.java b/smcc/src/main/java/at/gv/egiz/smcc/util/MSCMConstants.java
new file mode 100644
index 00000000..fdaff61e
--- /dev/null
+++ b/smcc/src/main/java/at/gv/egiz/smcc/util/MSCMConstants.java
@@ -0,0 +1,220 @@
+package at.gv.egiz.smcc.util;
+
+public interface MSCMConstants {
+ public static final int HIVECODE_METHOD_GET_PROPERTIES = 0x8187;
+
+
+ public static final short DEFAULT_SERVICE_PORT = 5;
+
+ public static final String URI = "MSCM";
+
+ public static final short HIVECODE_TYPE_DEFAULT = (short)0x7FBD;
+
+ // Methods
+ public static final short HIVECODE_METHOD_GETCARDPROPERTY = (short)0x8187;
+ public static final short HIVECODE_METHOD_GETCONTAINERPROPERTY = (short)0x279C;
+ public static final short HIVECODE_METHOD_GETVERSION = (short)0xDEEC;
+ public static final short HIVECODE_METHOD_GETFILES = (short)0xE72B;
+ public static final short HIVECODE_METHOD_GETTRIESREMAINING = (short)0x6D08;
+ public static final short HIVECODE_METHOD_PRIVATEKEYDECRYPT = (short)0x6144;
+ public static final short HIVECODE_METHOD_GETFILEPROPERTIES = (short)0xA01B;
+ public static final short HIVECODE_METHOD_QUERYFREESPACE = (short)0x00E5;
+ public static final short HIVECODE_METHOD_FORCEGC = (short)0x3D38;
+ public static final short HIVECODE_METHOD_READFILE = (short)0x744C;
+ public static final short HIVECODE_METHOD_VERIFYPIN = (short)0x506B;
+ public static final short HIVECODE_METHOD_CHANGEREFDATA = (short)0xE08A;
+ public static final short HIVECODE_METHOD_GETCHALLENGE = (short)0xFA3B;
+ public static final short HIVECODE_METHOD_EXTAUTH = (short)0x24FE;
+
+
+ // Property Fields
+ public static final byte PROPERTY_CARD_FREE_SPACE = (byte)0x00;
+ public static final byte PROPERTY_CARD_KEY_SIZES = (byte)0x02;
+ public static final byte PROPERTY_CARD_READ_ONLY = (byte)0x03;
+ public static final byte PROPERTY_CARD_CACHE_MODE = (byte)0x04;
+ public static final byte PROPERTY_CARD_GUID = (byte)0x05;
+ public static final byte PROPERTY_CARD_SERIAL_NUMBER = (byte)0x06;
+ public static final byte PROPERTY_CARD_PIN_INFO = (byte)0x07;
+ public static final byte PROPERTY_CARD_ROLES_LIST = (byte)0x08;
+ public static final byte PROPERTY_CARD_AUTHENTICATED_ROLES = (byte)0x09;
+ public static final byte PROPERTY_CARD_PIN_STRENGTH = (byte)0x0A;
+ public static final byte PROPERTY_CARD_UNBLOCK_FP_SYNC = (byte)0xF9;
+ public static final byte PROPERTY_CARD_PIN_POLICY = (byte)0x80;
+ public static final byte PROPERTY_CARD_X509_ENROLL = (byte)0x0D;
+ public static final byte PROPERTY_CARD_CHANGE_PIN_FIRST = (byte)0xFA;
+ public static final byte PROPERTY_CARD_IMPORT_ALLOWED = (byte)0x90;
+ public static final byte PROPERTY_CARD_IMPORT_CHANGE_ALLOWED = (byte)0x91;
+ public static final byte PROPERTY_CARD_PKI_OFF = (byte)0xF7;
+ public static final byte PROPERTY_CARD_VERSION_INFO = (byte)0xFF;
+
+ public static final byte PROPERTY_CONTAINER_INFO = (byte)0x00;
+ public static final byte PROPERTY_CONTAINER_PIN_IDENTIFIER = (byte)0x01;
+ public static final byte PROPERTY_CONTAINER_TYPE = (byte)0x80;
+
+ // Types
+ // =============================================================================================
+ public static final short HIVECODE_TYPE_SMARTCARD_CONTENTMANAGER = (short)0xB18C;
+ public static final short HIVECODE_TYPE_SYSTEM_VOID = (short)0xCE81;
+ public static final short HIVECODE_TYPE_SYSTEM_INT32 = (short)0x61C0;
+ public static final short HIVECODE_TYPE_SYSTEM_INT32_ARRAY = (short)0x61C1;
+ public static final short HIVECODE_TYPE_SYSTEM_BOOLEAN = (short)0x2227;
+ public static final short HIVECODE_TYPE_SYSTEM_BOOLEAN_ARRAY = (short)0x2228;
+ public static final short HIVECODE_TYPE_SYSTEM_SBYTE = (short)0x767E;
+ public static final short HIVECODE_TYPE_SYSTEM_SBYTE_ARRAY = (short)0x767F;
+ public static final short HIVECODE_TYPE_SYSTEM_UINT16 = (short)0xD98B;
+ public static final short HIVECODE_TYPE_SYSTEM_UINT16_ARRAY = (short)0xD98C;
+ public static final short HIVECODE_TYPE_SYSTEM_UINT32 = (short)0x95E7;
+ public static final short HIVECODE_TYPE_SYSTEM_UINT32_ARRAY = (short)0x95E8;
+ public static final short HIVECODE_TYPE_SYSTEM_BYTE = (short)0x45A2;
+ public static final short HIVECODE_TYPE_SYSTEM_BYTE_ARRAY = (short)0x45A3;
+ public static final short HIVECODE_TYPE_SYSTEM_CHAR = (short)0x958E;
+ public static final short HIVECODE_TYPE_SYSTEM_CHAR_ARRAY = (short)0x958F;
+ public static final short HIVECODE_TYPE_SYSTEM_INT16 = (short)0xBC39;
+ public static final short HIVECODE_TYPE_SYSTEM_INT16_ARRAY = (short)0xBC3A;
+ public static final short HIVECODE_TYPE_SYSTEM_STRING = (short)0x1127;
+ public static final short HIVECODE_TYPE_SYSTEM_STRING_ARRAY = (short)0x1128;
+ public static final short HIVECODE_TYPE_SYSTEM_INT64 = (short)0xDEFB;
+ public static final short HIVECODE_TYPE_SYSTEM_INT64_ARRAY = (short)0xDEFC;
+ public static final short HIVECODE_TYPE_SYSTEM_UINT64 = (short)0x71AF;
+ public static final short HIVECODE_TYPE_SYSTEM_UINT64_ARRAY = (short)0x71B0;
+ public static final short HIVECODE_TYPE_SYSTEM_IO_MEMORYSTREAM = (short)0xFED7;
+
+
+
+ public static final String HIVECODE_TYPE_SYSTEM_VOID_STRING = "System.Void";
+ public static final String HIVECODE_TYPE_SYSTEM_INT32_STRING = "System.Int32";
+ public static final String HIVECODE_TYPE_SYSTEM_INT32_ARRAY_STRING = "System.Int32[]";
+ public static final String HIVECODE_TYPE_SYSTEM_BOOLEAN_STRING = "System.Boolean";
+ public static final String HIVECODE_TYPE_SYSTEM_BOOLEAN_ARRAY_STRING = "System.Boolean[]";
+ public static final String HIVECODE_TYPE_SYSTEM_SBYTE_STRING = "System.SByte";
+ public static final String HIVECODE_TYPE_SYSTEM_SBYTE_ARRAY_STRING = "System.SByte[]";
+ public static final String HIVECODE_TYPE_SYSTEM_UINT16_STRING = "System.UInt16";
+ public static final String HIVECODE_TYPE_SYSTEM_UINT16_ARRAY_STRING = "System.UInt16[]";
+ public static final String HIVECODE_TYPE_SYSTEM_UINT32_STRING = "System.UInt32";
+ public static final String HIVECODE_TYPE_SYSTEM_UINT32_ARRAY_STRING = "System.UInt32[]";
+ public static final String HIVECODE_TYPE_SYSTEM_BYTE_STRING = "System.Byte";
+ public static final String HIVECODE_TYPE_SYSTEM_BYTE_ARRAY_STRING = "System.Byte[]";
+ public static final String HIVECODE_TYPE_SYSTEM_CHAR_STRING = "System.Char";
+ public static final String HIVECODE_TYPE_SYSTEM_CHAR_ARRAY_STRING = "System.Char[]";
+ public static final String HIVECODE_TYPE_SYSTEM_INT16_STRING = "System.Int16";
+ public static final String HIVECODE_TYPE_SYSTEM_INT16_ARRAY_STRING = "System.Int16[]";
+ public static final String HIVECODE_TYPE_SYSTEM_STRING_STRING = "System.String";
+ public static final String HIVECODE_TYPE_SYSTEM_STRING_ARRAY_STRING = "System.String[]";
+ public static final String HIVECODE_TYPE_SYSTEM_INT64_STRING = "System.Int64";
+ public static final String HIVECODE_TYPE_SYSTEM_INT64_ARRAY_STRING = "System.Int64[]";
+ public static final String HIVECODE_TYPE_SYSTEM_UINT64_STRING = "System.UInt64";
+ public static final String HIVECODE_TYPE_SYSTEM_UINT64_ARRAY_STRING = "System.UInt64[]";
+ public static final String HIVECODE_TYPE_SYSTEM_IO_MEMORYSTREAM_STRING = "System.IO.MemoryStream";
+
+
+ // Namespaces
+ // ==========================================================================================
+ public static final int HIVECODE_NAMESPACE_SYSTEM = 0x00D25D1C;
+ public static final int HIVECODE_NAMESPACE_SYSTEM_IO = 0x00D5E6DB;
+ public static final int HIVECODE_NAMESPACE_SYSTEM_RUNTIME_REMOTING_CHANNELS = 0x0000886E;
+ public static final int HIVECODE_NAMESPACE_NETCARD_FILESYSTEM = 0x00A1AC39;
+ public static final int HIVECODE_NAMESPACE_SYSTEM_RUNTIME_REMOTING = 0x00EB3DD9;
+ public static final int HIVECODE_NAMESPACE_SYSTEM_SECURITY_CRYPTOGRAPHY = 0x00ACF53B;
+ public static final int HIVECODE_NAMESPACE_SYSTEM_COLLECTIONS = 0x00C5A010;
+ public static final int HIVECODE_NAMESPACE_SYSTEM_RUNTIME_REMOTING_CONTEXTS = 0x001F4994;
+ public static final int HIVECODE_NAMESPACE_SYSTEM_SECURITY = 0x00964145;
+ public static final int HIVECODE_NAMESPACE_SYSTEM_REFLECTION = 0x0008750F;
+ public static final int HIVECODE_NAMESPACE_SYSTEM_RUNTIME_SERIALIZATION = 0x008D3B3D;
+ public static final int HIVECODE_NAMESPACE_SYSTEM_RUNTIME_REMOTING_MESSAGING = 0x00DEB940;
+ public static final int HIVECODE_NAMESPACE_SYSTEM_DIAGNOSTICS = 0x0097995F;
+ public static final int HIVECODE_NAMESPACE_SYSTEM_RUNTIME_COMPILERSERVICES = 0x00F63E11;
+ public static final int HIVECODE_NAMESPACE_SYSTEM_TEXT = 0x00702756;
+ public static final int HIVECODE_NAMESPACE_SMARTCARD = 0x00F5EFBF;
+
+ public static final String HIVECODE_NAMESPACE_SYSTEM_STRING = "System";
+ public static final String HIVECODE_NAMESPACE_SYSTEM_IO_STRING = "System.IO";
+ public static final String HIVECODE_NAMESPACE_SYSTEM_RUNTIME_REMOTING_CHANNELS_STRING = "System.Runtime.Remoting.Channels";
+ public static final String HIVECODE_NAMESPACE_NETCARD_FILESYSTEM_STRING = "Netcard.Filesystem";
+ public static final String HIVECODE_NAMESPACE_SYSTEM_RUNTIME_REMOTING_STRING = "System.Runtime.Remoting";
+ public static final String HIVECODE_NAMESPACE_SYSTEM_SECURITY_CRYPTOGRAPHY_STRING = "System.Security.Cryptography";
+ public static final String HIVECODE_NAMESPACE_SYSTEM_COLLECTIONS_STRING = "System.Collections";
+ public static final String HIVECODE_NAMESPACE_SYSTEM_RUNTIME_REMOTING_CONTEXTS_STRING = "System.Runtime.Remoting.Contexts";
+ public static final String HIVECODE_NAMESPACE_SYSTEM_SECURITY_STRING = "System.Security";
+ public static final String HIVECODE_NAMESPACE_SYSTEM_REFLECTION_STRING = "System.Reflection";
+ public static final String HIVECODE_NAMESPACE_SYSTEM_RUNTIME_SERIALIZATION_STRING = "System.Runtime.Serialization";
+ public static final String HIVECODE_NAMESPACE_SYSTEM_RUNTIME_REMOTING_MESSAGING_STRING = "System.Runtime.Remoting.Messaging";
+ public static final String HIVECODE_NAMESPACE_SYSTEM_DIAGNOSTICS_STRING = "System.Diagnostics";
+ public static final String HIVECODE_NAMESPACE_SYSTEM_RUNTIME_COMPILERSERVICES_STRING = "System.Runtime.Compilerservices";
+ public static final String HIVECODE_NAMESPACE_SYSTEM_TEXT_STRING = "System.Text";
+ public static final String HIVECODE_NAMESPACE_SMARTCARD_STRING = "Smartcard";
+
+ public static final int HIVECODE_NAMESPACE_GEMALTO = 0x00C04B4E;
+
+ // Exceptions
+ // ============================================================================================
+ public static final short HIVECODE_EXCEPTION_SYSTEM_EXCEPTION = (short) 0xD4B0;
+ public static final short HIVECODE_EXCEPTION_SYSTEM_SYSTEMEXCEPTION = (short) 0x28AC;
+ public static final short HIVECODE_EXCEPTION_SYSTEM_OUTOFMEMORYEXCEPTION = (short) 0xE14E;
+ public static final short HIVECODE_EXCEPTION_SYSTEM_ARGUMENTEXCEPTION = (short) 0xAB8C;
+ public static final short HIVECODE_EXCEPTION_SYSTEM_ARGUMENTNULLEXCEPTION = (short) 0x2138;
+ public static final short HIVECODE_EXCEPTION_SYSTEM_NULLREFERENCEEXCEPTION = (short) 0xC5B8;
+ public static final short HIVECODE_EXCEPTION_SYSTEM_ARGUMENTOUTOFRANGEEXCEPTION = (short) 0x6B11;
+ public static final short HIVECODE_EXCEPTION_SYSTEM_NOTSUPPORTEDEXCEPTION = (short) 0xAA74;
+ public static final short HIVECODE_EXCEPTION_SYSTEM_INVALIDCASTEXCEPTION = (short) 0xD24F;
+ public static final short HIVECODE_EXCEPTION_SYSTEM_INVALIDOPERATIONEXCEPTION = (short) 0xFAB4;
+ public static final short HIVECODE_EXCEPTION_SYSTEM_NOTIMPLEMENTEDEXCEPTION = (short) 0x3CE5;
+ public static final short HIVECODE_EXCEPTION_SYSTEM_OBJECTDISPOSEDEXCEPTION = (short) 0x0FAC;
+ public static final short HIVECODE_EXCEPTION_SYSTEM_UNAUTHORIZEDACCESSEXCEPTION = (short) 0x4697;
+ public static final short HIVECODE_EXCEPTION_SYSTEM_INDEXOUTOFRANGEEXCEPTION = (short) 0xBF1D;
+ public static final short HIVECODE_EXCEPTION_SYSTEM_FORMATEXCEPTION = (short) 0xF3BF;
+ public static final short HIVECODE_EXCEPTION_SYSTEM_ARITHMETICEXCEPTION = (short) 0x6683;
+ public static final short HIVECODE_EXCEPTION_SYSTEM_OVERFLOWEXCEPTION = (short) 0x20A0;
+ public static final short HIVECODE_EXCEPTION_SYSTEM_BADIMAGEFORMATEXCEPTION = (short) 0x530A;
+ public static final short HIVECODE_EXCEPTION_SYSTEM_APPLICATIONEXCEPTION = (short) 0xB1EA;
+ public static final short HIVECODE_EXCEPTION_SYSTEM_ARRAYTYPEMISMATCHEXCEPTION = (short) 0x3F88;
+ public static final short HIVECODE_EXCEPTION_SYSTEM_DIVIDEBYZEROEXCEPTION = (short) 0xDFCF;
+ public static final short HIVECODE_EXCEPTION_SYSTEM_MEMBERACCESSEXCEPTION = (short) 0xF5F3;
+ public static final short HIVECODE_EXCEPTION_SYSTEM_MISSINGMEMBEREXCEPTION = (short) 0x20BB;
+ public static final short HIVECODE_EXCEPTION_SYSTEM_MISSINGFIELDEXCEPTION = (short) 0x7366;
+ public static final short HIVECODE_EXCEPTION_SYSTEM_MISSINGMEHTODEXCEPTION = (short) 0x905B;
+ public static final short HIVECODE_EXCEPTION_SYSTEM_RANKEXCEPTION = (short) 0xB2AE;
+ public static final short HIVECODE_EXCEPTION_SYSTEM_STACKOVERFLOWEXCEPTION = (short) 0x0844;
+ public static final short HIVECODE_EXCEPTION_SYSTEM_TYPELOADEXCEPTION = (short) 0x048E;
+ public static final short HIVECODE_EXCEPTION_SYSTEM_IO_IOEXCEPTION = (short) 0x3BBE;
+ public static final short HIVECODE_EXCEPTION_SYSTEM_IO_DIRECTORYNOTFOUNDEXCEPTION = (short) 0x975A;
+ public static final short HIVECODE_EXCEPTION_SYSTEM_IO_FILENOTFOUNDEXCEPTION = (short) 0x07EB;
+ public static final short HIVECODE_EXCEPTION_SYSTEM_RUNTIME_REMOTING_REMOTINGEXCEPTION = (short) 0xD52A;
+ public static final short HIVECODE_EXCEPTION_SYSTEM_SECURITY_CRYPTOGRAPHY_CRYPTOGRAPHICEXCEPTION = (short) 0x8FEB;
+
+
+ public static final String HIVECODE_EXCEPTION_SYSTEM_EXCEPTION_STRING = "System.Exception";
+ public static final String HIVECODE_EXCEPTION_SYSTEM_SYSTEMEXCEPTION_STRING = "System.SystemException";
+ public static final String HIVECODE_EXCEPTION_SYSTEM_OUTOFMEMORYEXCEPTION_STRING = "System.OutOfMemoryException";
+ public static final String HIVECODE_EXCEPTION_SYSTEM_ARGUMENTEXCEPTION_STRING = "System.ArgumentException";
+ public static final String HIVECODE_EXCEPTION_SYSTEM_ARGUMENTNULLEXCEPTION_STRING = "System.ArgumentNullException";
+ public static final String HIVECODE_EXCEPTION_SYSTEM_NULLREFERENCEEXCEPTION_STRING = "System.NullReferenceException";
+ public static final String HIVECODE_EXCEPTION_SYSTEM_ARGUMENTOUTOFRANGEEXCEPTION_STRING = "System.ArgumentOutOfRangeException";
+ public static final String HIVECODE_EXCEPTION_SYSTEM_NOTSUPPORTEDEXCEPTION_STRING = "System.NotSupportedException";
+ public static final String HIVECODE_EXCEPTION_SYSTEM_INVALIDCASTEXCEPTION_STRING = "System.InvalidCastException";
+ public static final String HIVECODE_EXCEPTION_SYSTEM_INVALIDOPERATIONEXCEPTION_STRING = "System.InvalidOperationException";
+ public static final String HIVECODE_EXCEPTION_SYSTEM_NOTIMPLEMENTEDEXCEPTION_STRING = "System.NotImplementedException";
+ public static final String HIVECODE_EXCEPTION_SYSTEM_OBJECTDISPOSEDEXCEPTION_STRING = "System.ObjectDisposed Exception";
+ public static final String HIVECODE_EXCEPTION_SYSTEM_UNAUTHORIZEDACCESSEXCEPTION_STRING = "System.UnauthorizedAccessException";
+ public static final String HIVECODE_EXCEPTION_SYSTEM_INDEXOUTOFRANGEEXCEPTION_STRING = "System.IndexOutOfRangeException";
+ public static final String HIVECODE_EXCEPTION_SYSTEM_FORMATEXCEPTION_STRING = "System.FormatException";
+ public static final String HIVECODE_EXCEPTION_SYSTEM_ARITHMETICEXCEPTION_STRING = "System.ArithmeticException";
+ public static final String HIVECODE_EXCEPTION_SYSTEM_OVERFLOWEXCEPTION_STRING = "System.OverflowException";
+ public static final String HIVECODE_EXCEPTION_SYSTEM_BADIMAGEFORMATEXCEPTION_STRING = "System.BadImageFormatException";
+ public static final String HIVECODE_EXCEPTION_SYSTEM_APPLICATIONEXCEPTION_STRING = "System.ApplicationException";
+ public static final String HIVECODE_EXCEPTION_SYSTEM_ARRAYTYPEMISMATCHEXCEPTION_STRING = "System.ArrayTypeMismatchException";
+ public static final String HIVECODE_EXCEPTION_SYSTEM_DIVIDEBYZEROEXCEPTION_STRING = "System.DivideByZeroException";
+ public static final String HIVECODE_EXCEPTION_SYSTEM_MEMBERACCESSEXCEPTION_STRING = "System.MemberAccessException";
+ public static final String HIVECODE_EXCEPTION_SYSTEM_MISSINGMEMBEREXCEPTION_STRING = "System.MissingMemberException";
+ public static final String HIVECODE_EXCEPTION_SYSTEM_MISSINGFIELDEXCEPTION_STRING = "System.MissingFieldException";
+ public static final String HIVECODE_EXCEPTION_SYSTEM_MISSINGMEHTODEXCEPTION_STRING = "System.MissingMethodException";
+ public static final String HIVECODE_EXCEPTION_SYSTEM_RANKEXCEPTION_STRING = "System.RankException";
+ public static final String HIVECODE_EXCEPTION_SYSTEM_STACKOVERFLOWEXCEPTION_STRING = "System.StackOverflowException";
+ public static final String HIVECODE_EXCEPTION_SYSTEM_TYPELOADEXCEPTION_STRING = "System.TypeLoadException";
+ public static final String HIVECODE_EXCEPTION_SYSTEM_IO_IOEXCEPTION_STRING = "System.IO.IOException";
+ public static final String HIVECODE_EXCEPTION_SYSTEM_IO_DIRECTORYNOTFOUNDEXCEPTION_STRING = "System.IO.DirectoryNotFoundException";
+ public static final String HIVECODE_EXCEPTION_SYSTEM_IO_FILENOTFOUNDEXCEPTION_STRING = "System.IO.FileNotFoundException";
+ public static final String HIVECODE_EXCEPTION_SYSTEM_RUNTIME_REMOTING_REMOTINGEXCEPTION_STRING = "System.Runtime.Remoting.RemotingException";
+ public static final String HIVECODE_EXCEPTION_SYSTEM_SECURITY_CRYPTOGRAPHY_CRYPTOGRAPHICEXCEPTION_STRING = "System.Security.Cryptography.CryptographicException";
+
+
+}
diff --git a/smcc/src/main/java/at/gv/egiz/smcc/util/MSCMDecoder.java b/smcc/src/main/java/at/gv/egiz/smcc/util/MSCMDecoder.java
new file mode 100644
index 00000000..5eddbe25
--- /dev/null
+++ b/smcc/src/main/java/at/gv/egiz/smcc/util/MSCMDecoder.java
@@ -0,0 +1,259 @@
+package at.gv.egiz.smcc.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.HashMap;
+import java.util.Map;
+
+public class MSCMDecoder implements MSCMConstants {
+
+ private static Map<Integer, String> namespaces;
+
+ private static Map<Short, String> types;
+
+ private static Map<Short, String> exceptions;
+
+ static {
+ namespaces = new HashMap<Integer, String>();
+ namespaces.put(HIVECODE_NAMESPACE_SYSTEM, HIVECODE_NAMESPACE_SYSTEM_STRING);
+ namespaces.put(HIVECODE_NAMESPACE_SYSTEM_IO, HIVECODE_NAMESPACE_SYSTEM_IO_STRING);
+ namespaces.put(HIVECODE_NAMESPACE_SYSTEM_RUNTIME_REMOTING_CHANNELS, HIVECODE_NAMESPACE_SYSTEM_RUNTIME_REMOTING_CHANNELS_STRING);
+ namespaces.put(HIVECODE_NAMESPACE_NETCARD_FILESYSTEM, HIVECODE_NAMESPACE_NETCARD_FILESYSTEM_STRING);
+ namespaces.put(HIVECODE_NAMESPACE_SYSTEM_RUNTIME_REMOTING, HIVECODE_NAMESPACE_SYSTEM_RUNTIME_REMOTING_STRING);
+ namespaces.put(HIVECODE_NAMESPACE_SYSTEM_SECURITY_CRYPTOGRAPHY, HIVECODE_NAMESPACE_SYSTEM_SECURITY_CRYPTOGRAPHY_STRING);
+ namespaces.put(HIVECODE_NAMESPACE_SYSTEM_COLLECTIONS, HIVECODE_NAMESPACE_SYSTEM_COLLECTIONS_STRING);
+ namespaces.put(HIVECODE_NAMESPACE_SYSTEM_RUNTIME_REMOTING_CONTEXTS, HIVECODE_NAMESPACE_SYSTEM_RUNTIME_REMOTING_CONTEXTS_STRING);
+ namespaces.put(HIVECODE_NAMESPACE_SYSTEM_SECURITY, HIVECODE_NAMESPACE_SYSTEM_SECURITY_STRING);
+ namespaces.put(HIVECODE_NAMESPACE_SYSTEM_REFLECTION, HIVECODE_NAMESPACE_SYSTEM_REFLECTION_STRING);
+ namespaces.put(HIVECODE_NAMESPACE_SYSTEM_RUNTIME_SERIALIZATION, HIVECODE_NAMESPACE_SYSTEM_RUNTIME_SERIALIZATION_STRING);
+ namespaces.put(HIVECODE_NAMESPACE_SYSTEM_RUNTIME_REMOTING_MESSAGING, HIVECODE_NAMESPACE_SYSTEM_RUNTIME_REMOTING_MESSAGING_STRING);
+ namespaces.put(HIVECODE_NAMESPACE_SYSTEM_DIAGNOSTICS, HIVECODE_NAMESPACE_SYSTEM_DIAGNOSTICS_STRING);
+ namespaces.put(HIVECODE_NAMESPACE_SYSTEM_RUNTIME_COMPILERSERVICES, HIVECODE_NAMESPACE_SYSTEM_RUNTIME_COMPILERSERVICES_STRING);
+ namespaces.put(HIVECODE_NAMESPACE_SYSTEM_TEXT, HIVECODE_NAMESPACE_SYSTEM_TEXT_STRING);
+ namespaces.put(HIVECODE_NAMESPACE_SMARTCARD, HIVECODE_NAMESPACE_SMARTCARD_STRING);
+
+
+ types = new HashMap<Short, String>();
+
+ types.put(HIVECODE_TYPE_SYSTEM_VOID, HIVECODE_TYPE_SYSTEM_VOID_STRING);
+ types.put(HIVECODE_TYPE_SYSTEM_INT32, HIVECODE_TYPE_SYSTEM_INT32_STRING);
+ types.put(HIVECODE_TYPE_SYSTEM_INT32_ARRAY, HIVECODE_TYPE_SYSTEM_INT32_ARRAY_STRING);
+ types.put(HIVECODE_TYPE_SYSTEM_BOOLEAN, HIVECODE_TYPE_SYSTEM_BOOLEAN_STRING);
+ types.put(HIVECODE_TYPE_SYSTEM_BOOLEAN_ARRAY, HIVECODE_TYPE_SYSTEM_BOOLEAN_ARRAY_STRING);
+ types.put(HIVECODE_TYPE_SYSTEM_SBYTE, HIVECODE_TYPE_SYSTEM_SBYTE_STRING);
+ types.put(HIVECODE_TYPE_SYSTEM_SBYTE_ARRAY, HIVECODE_TYPE_SYSTEM_SBYTE_ARRAY_STRING);
+ types.put(HIVECODE_TYPE_SYSTEM_UINT16, HIVECODE_TYPE_SYSTEM_UINT16_STRING);
+ types.put(HIVECODE_TYPE_SYSTEM_UINT16_ARRAY, HIVECODE_TYPE_SYSTEM_UINT16_ARRAY_STRING);
+ types.put(HIVECODE_TYPE_SYSTEM_UINT32, HIVECODE_TYPE_SYSTEM_UINT32_STRING);
+ types.put(HIVECODE_TYPE_SYSTEM_UINT32_ARRAY, HIVECODE_TYPE_SYSTEM_UINT32_ARRAY_STRING);
+ types.put(HIVECODE_TYPE_SYSTEM_BYTE, HIVECODE_TYPE_SYSTEM_BYTE_STRING);
+ types.put(HIVECODE_TYPE_SYSTEM_BYTE_ARRAY, HIVECODE_TYPE_SYSTEM_BYTE_ARRAY_STRING);
+ types.put(HIVECODE_TYPE_SYSTEM_CHAR, HIVECODE_TYPE_SYSTEM_CHAR_STRING);
+ types.put(HIVECODE_TYPE_SYSTEM_CHAR_ARRAY, HIVECODE_TYPE_SYSTEM_CHAR_ARRAY_STRING);
+ types.put(HIVECODE_TYPE_SYSTEM_INT16, HIVECODE_TYPE_SYSTEM_INT16_STRING);
+ types.put(HIVECODE_TYPE_SYSTEM_INT16_ARRAY, HIVECODE_TYPE_SYSTEM_INT16_ARRAY_STRING);
+ types.put(HIVECODE_TYPE_SYSTEM_STRING, HIVECODE_TYPE_SYSTEM_STRING_STRING);
+ types.put(HIVECODE_TYPE_SYSTEM_STRING_ARRAY, HIVECODE_TYPE_SYSTEM_STRING_ARRAY_STRING);
+ types.put(HIVECODE_TYPE_SYSTEM_INT64, HIVECODE_TYPE_SYSTEM_INT64_STRING);
+ types.put(HIVECODE_TYPE_SYSTEM_INT64_ARRAY, HIVECODE_TYPE_SYSTEM_INT64_ARRAY_STRING);
+ types.put(HIVECODE_TYPE_SYSTEM_UINT64, HIVECODE_TYPE_SYSTEM_UINT64_STRING);
+ types.put(HIVECODE_TYPE_SYSTEM_UINT64_ARRAY, HIVECODE_TYPE_SYSTEM_UINT64_ARRAY_STRING);
+ types.put(HIVECODE_TYPE_SYSTEM_IO_MEMORYSTREAM, HIVECODE_TYPE_SYSTEM_IO_MEMORYSTREAM_STRING);
+
+ exceptions = new HashMap<Short, String>();
+ exceptions.put(HIVECODE_EXCEPTION_SYSTEM_EXCEPTION, HIVECODE_EXCEPTION_SYSTEM_EXCEPTION_STRING);
+ exceptions.put(HIVECODE_EXCEPTION_SYSTEM_SYSTEMEXCEPTION, HIVECODE_EXCEPTION_SYSTEM_SYSTEMEXCEPTION_STRING);
+ exceptions.put(HIVECODE_EXCEPTION_SYSTEM_OUTOFMEMORYEXCEPTION, HIVECODE_EXCEPTION_SYSTEM_OUTOFMEMORYEXCEPTION_STRING);
+ exceptions.put(HIVECODE_EXCEPTION_SYSTEM_ARGUMENTEXCEPTION, HIVECODE_EXCEPTION_SYSTEM_ARGUMENTEXCEPTION_STRING);
+ exceptions.put(HIVECODE_EXCEPTION_SYSTEM_ARGUMENTNULLEXCEPTION, HIVECODE_EXCEPTION_SYSTEM_ARGUMENTNULLEXCEPTION_STRING);
+ exceptions.put(HIVECODE_EXCEPTION_SYSTEM_NULLREFERENCEEXCEPTION, HIVECODE_EXCEPTION_SYSTEM_NULLREFERENCEEXCEPTION_STRING);
+ exceptions.put(HIVECODE_EXCEPTION_SYSTEM_ARGUMENTOUTOFRANGEEXCEPTION, HIVECODE_EXCEPTION_SYSTEM_ARGUMENTOUTOFRANGEEXCEPTION_STRING);
+ exceptions.put(HIVECODE_EXCEPTION_SYSTEM_NOTSUPPORTEDEXCEPTION, HIVECODE_EXCEPTION_SYSTEM_NOTSUPPORTEDEXCEPTION_STRING);
+ exceptions.put(HIVECODE_EXCEPTION_SYSTEM_INVALIDCASTEXCEPTION, HIVECODE_EXCEPTION_SYSTEM_INVALIDCASTEXCEPTION_STRING);
+ exceptions.put(HIVECODE_EXCEPTION_SYSTEM_INVALIDOPERATIONEXCEPTION, HIVECODE_EXCEPTION_SYSTEM_INVALIDOPERATIONEXCEPTION_STRING);
+ exceptions.put(HIVECODE_EXCEPTION_SYSTEM_NOTIMPLEMENTEDEXCEPTION, HIVECODE_EXCEPTION_SYSTEM_NOTIMPLEMENTEDEXCEPTION_STRING);
+ exceptions.put(HIVECODE_EXCEPTION_SYSTEM_OBJECTDISPOSEDEXCEPTION, HIVECODE_EXCEPTION_SYSTEM_OBJECTDISPOSEDEXCEPTION_STRING);
+ exceptions.put(HIVECODE_EXCEPTION_SYSTEM_UNAUTHORIZEDACCESSEXCEPTION, HIVECODE_EXCEPTION_SYSTEM_UNAUTHORIZEDACCESSEXCEPTION_STRING);
+ exceptions.put(HIVECODE_EXCEPTION_SYSTEM_INDEXOUTOFRANGEEXCEPTION, HIVECODE_EXCEPTION_SYSTEM_INDEXOUTOFRANGEEXCEPTION_STRING);
+ exceptions.put(HIVECODE_EXCEPTION_SYSTEM_FORMATEXCEPTION, HIVECODE_EXCEPTION_SYSTEM_FORMATEXCEPTION_STRING);
+ exceptions.put(HIVECODE_EXCEPTION_SYSTEM_ARITHMETICEXCEPTION, HIVECODE_EXCEPTION_SYSTEM_ARITHMETICEXCEPTION_STRING);
+ exceptions.put(HIVECODE_EXCEPTION_SYSTEM_OVERFLOWEXCEPTION, HIVECODE_EXCEPTION_SYSTEM_OVERFLOWEXCEPTION_STRING);
+ exceptions.put(HIVECODE_EXCEPTION_SYSTEM_BADIMAGEFORMATEXCEPTION, HIVECODE_EXCEPTION_SYSTEM_BADIMAGEFORMATEXCEPTION_STRING);
+ exceptions.put(HIVECODE_EXCEPTION_SYSTEM_APPLICATIONEXCEPTION, HIVECODE_EXCEPTION_SYSTEM_APPLICATIONEXCEPTION_STRING);
+ exceptions.put(HIVECODE_EXCEPTION_SYSTEM_ARRAYTYPEMISMATCHEXCEPTION, HIVECODE_EXCEPTION_SYSTEM_ARRAYTYPEMISMATCHEXCEPTION_STRING);
+ exceptions.put(HIVECODE_EXCEPTION_SYSTEM_DIVIDEBYZEROEXCEPTION, HIVECODE_EXCEPTION_SYSTEM_DIVIDEBYZEROEXCEPTION_STRING);
+ exceptions.put(HIVECODE_EXCEPTION_SYSTEM_MEMBERACCESSEXCEPTION, HIVECODE_EXCEPTION_SYSTEM_MEMBERACCESSEXCEPTION_STRING);
+ exceptions.put(HIVECODE_EXCEPTION_SYSTEM_MISSINGMEMBEREXCEPTION, HIVECODE_EXCEPTION_SYSTEM_MISSINGMEMBEREXCEPTION_STRING);
+ exceptions.put(HIVECODE_EXCEPTION_SYSTEM_MISSINGFIELDEXCEPTION, HIVECODE_EXCEPTION_SYSTEM_MISSINGFIELDEXCEPTION_STRING);
+ exceptions.put(HIVECODE_EXCEPTION_SYSTEM_MISSINGMEHTODEXCEPTION, HIVECODE_EXCEPTION_SYSTEM_MISSINGMEHTODEXCEPTION_STRING);
+ exceptions.put(HIVECODE_EXCEPTION_SYSTEM_RANKEXCEPTION, HIVECODE_EXCEPTION_SYSTEM_RANKEXCEPTION_STRING);
+ exceptions.put(HIVECODE_EXCEPTION_SYSTEM_STACKOVERFLOWEXCEPTION, HIVECODE_EXCEPTION_SYSTEM_STACKOVERFLOWEXCEPTION_STRING);
+ exceptions.put(HIVECODE_EXCEPTION_SYSTEM_TYPELOADEXCEPTION, HIVECODE_EXCEPTION_SYSTEM_TYPELOADEXCEPTION_STRING);
+ exceptions.put(HIVECODE_EXCEPTION_SYSTEM_IO_IOEXCEPTION, HIVECODE_EXCEPTION_SYSTEM_IO_IOEXCEPTION_STRING);
+ exceptions.put(HIVECODE_EXCEPTION_SYSTEM_IO_DIRECTORYNOTFOUNDEXCEPTION, HIVECODE_EXCEPTION_SYSTEM_IO_DIRECTORYNOTFOUNDEXCEPTION_STRING);
+ exceptions.put(HIVECODE_EXCEPTION_SYSTEM_IO_FILENOTFOUNDEXCEPTION, HIVECODE_EXCEPTION_SYSTEM_IO_FILENOTFOUNDEXCEPTION_STRING);
+ exceptions.put(HIVECODE_EXCEPTION_SYSTEM_RUNTIME_REMOTING_REMOTINGEXCEPTION, HIVECODE_EXCEPTION_SYSTEM_RUNTIME_REMOTING_REMOTINGEXCEPTION_STRING);
+ exceptions.put(HIVECODE_EXCEPTION_SYSTEM_SECURITY_CRYPTOGRAPHY_CRYPTOGRAPHICEXCEPTION, HIVECODE_EXCEPTION_SYSTEM_SECURITY_CRYPTOGRAPHY_CRYPTOGRAPHICEXCEPTION_STRING);
+
+ }
+
+ public static void checkExceptionInResponse(byte[] data, int offset) throws MSCMException {
+ short value;
+ String optional = null;
+ if(data[offset] == (byte)0xFF) {
+ value = MSCMService.bytesToShort(data, offset+5);
+ if(data.length > offset + 7) {
+ try {
+ optional = decodeString(data, offset + 7);
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ }
+ }
+ } else {
+ value = MSCMService.bytesToShort(data, offset+4);
+ if(data.length > offset + 6) {
+ try {
+ optional = decodeString(data, offset + 6);
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ String message = exceptions.get(value);
+ if(message != null) {
+
+ if(optional == null) {
+ throw new MSCMException(value, message);
+ } else {
+ throw new MSCMException(value, message, optional);
+ }
+ }
+
+ }
+
+ public static String namespaceHiveToString(byte[] hive, int offset) {
+ int value = MSCMService.bytesToInt(hive, offset);
+ String str = namespaces.get(value);
+ if(str == null) {
+ str = MSCMService.bytArrayToHex(hive);
+ }
+ return str;
+ }
+
+ public static String typeHiveToString(byte[] hive, int offset) {
+ short value = MSCMService.bytesToShort(hive, offset);
+ String str = types.get(value);
+ if(str == null) {
+ str = MSCMService.bytArrayToHex(hive);
+ }
+ return str;
+ }
+
+ public static boolean decodeBoolean(byte data) {
+ return (data == (byte) 0x01);
+ }
+
+ public static byte[] decodeByteArray(byte[] data, int offset) {
+ int length = MSCMService.bytesToInt(data, offset);
+ if(length > data.length - offset - 4) {
+ // encoding error
+ return null;
+ }
+ byte[] result = new byte[length];
+ for(int i = 0; i < length; i++) {
+ result[i] = data[offset + 4 + i];
+ }
+ return result;
+ }
+
+ public static short[] decodeShortArray(byte[] data, int offset) {
+ int length = MSCMService.bytesToInt(data, offset);
+ if(length * 2 > data.length - offset - 4) {
+ // encoding error
+ return null;
+ }
+ short[] result = new short[length];
+ for(int i = 0; i < length; i++) {
+ result[i] = MSCMService.bytesToShort(data, offset + 4 + i * 2);
+ }
+ return result;
+ }
+
+ public static int[] decodeIntArray(byte[] data, int offset) {
+ int length = MSCMService.bytesToInt(data, offset);
+ if(length * 4 > data.length - offset - 4) {
+ // encoding error
+ return null;
+ }
+ int[] result = new int[length];
+ for(int i = 0; i < length; i++) {
+ result[i] = MSCMService.bytesToInt(data, offset + 4 + i * 4);
+ }
+ return result;
+ }
+
+ public static String[] decodeStringArray(byte[] data, int offset) throws UnsupportedEncodingException {
+ int length = MSCMService.bytesToInt(data, offset);
+ String[] result = new String[length];
+ int curoffset = 4;
+ for(int i = 0; i < length; i++) {
+ short strlength = MSCMService.bytesToShort(data, offset + curoffset);
+ result[i] = decodeString(data, offset + curoffset);
+ curoffset += strlength + 2;
+ }
+ return result;
+ }
+
+
+ public static String decodeString(byte[] data, int offset) throws UnsupportedEncodingException {
+ short length = MSCMService.bytesToShort(data, offset);
+ if(length == 0xFFFF) {
+ return "";
+ }
+
+ byte[] utf8Data = new byte[length*2];
+ for(int i = 0; i < length; i++) {
+ utf8Data[i] = data[offset + 2 + i];
+ }
+
+ String str = new String(utf8Data, "UTF-8");
+ return str;
+ }
+
+
+ public static byte[] encodeString(String str) throws IOException {
+ if(str == null) {
+ return new byte[] { (byte) 0xFF, (byte) 0xFF };
+ }
+ byte[] utf8data = str.getBytes("UTF-8");
+ short strinlen = (short)utf8data.length;
+ byte[] lendata = MSCMService.shortToBytes(strinlen);
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream(strinlen + 2);
+ out.write(lendata);
+ out.write(utf8data);
+ out.close();
+ return out.toByteArray();
+ }
+
+ public static byte[] encodeByteArray(byte[] data) throws IOException {
+ int strinlen = (int)data.length;
+ byte[] lendata = MSCMService.intToBytes(strinlen);
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream(strinlen + 4);
+ out.write(lendata);
+ out.write(data);
+ out.close();
+ return out.toByteArray();
+ }
+
+ public static byte[] concatByteArrays(byte[] a, byte[] b) throws IOException {
+ ByteArrayOutputStream out = new ByteArrayOutputStream(a.length + b.length);
+ out.write(a);
+ out.write(b);
+ out.close();
+ return out.toByteArray();
+ }
+}
+ \ No newline at end of file
diff --git a/smcc/src/main/java/at/gv/egiz/smcc/util/MSCMException.java b/smcc/src/main/java/at/gv/egiz/smcc/util/MSCMException.java
new file mode 100644
index 00000000..0466d30c
--- /dev/null
+++ b/smcc/src/main/java/at/gv/egiz/smcc/util/MSCMException.java
@@ -0,0 +1,23 @@
+package at.gv.egiz.smcc.util;
+
+public class MSCMException extends Exception {
+ private short hive;
+
+ public MSCMException(short hive, String netException, String optional) {
+ super(netException + " [ " + optional + " ]");
+ this.setHive(hive);
+ }
+
+ public MSCMException(short hive, String netException) {
+ super(netException);
+ this.setHive(hive);
+ }
+
+ public short getHive() {
+ return hive;
+ }
+
+ public void setHive(short hive) {
+ this.hive = hive;
+ }
+}
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);
+ }
+}
diff --git a/smcc/src/main/java/at/gv/egiz/smcc/util/MSCMTransfer.java b/smcc/src/main/java/at/gv/egiz/smcc/util/MSCMTransfer.java
new file mode 100644
index 00000000..ea4121a5
--- /dev/null
+++ b/smcc/src/main/java/at/gv/egiz/smcc/util/MSCMTransfer.java
@@ -0,0 +1,146 @@
+package at.gv.egiz.smcc.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import javax.smartcardio.CardChannel;
+import javax.smartcardio.CardException;
+import javax.smartcardio.CommandAPDU;
+import javax.smartcardio.ResponseAPDU;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import at.gv.egiz.smcc.GemaltoNetV2_0Card;
+
+import java.nio.ByteBuffer;
+
+public class MSCMTransfer implements MSCMConstants {
+
+ private final Logger log = LoggerFactory
+ .getLogger(MSCMTransfer.class);
+
+ private CardChannel channel;
+
+ public MSCMTransfer(CardChannel channel) {
+ this.channel = channel;
+ }
+
+ public byte[] transfer(byte[] payload, short expectedType) throws IOException, CardException, MSCMException {
+ byte[] header = new byte[] { (byte) 0x80, (byte) 0xC2, (byte) 0x00,
+ (byte) 0x00 };
+ byte[] cmd = null;
+ byte[] len = new byte[1];
+ byte[] con = new byte[] { (byte) 0xD8, (byte) 0xFF, (byte) 0xFF };
+ ByteArrayOutputStream cmdbuffer = new ByteArrayOutputStream();
+ ResponseAPDU response = null;
+ if(payload.length <= 0xFF) {
+ cmdbuffer.write(header);
+ len[0] = (byte) payload.length;
+ cmdbuffer.write(len);
+ cmdbuffer.write(payload);
+ // Transfer cmdbuffer
+ cmd = cmdbuffer.toByteArray();
+ String str = MSCMService.bytArrayToHex(cmd);
+ log.info("Sending: >>> " + str);
+ //ByteBuffer bb = ByteBuffer.wrap(cmd);
+ //ByteBuffer resp = ByteBuffer.allocate(18000);
+ //response = channel.transmit(bb, resp);
+ //int resps = channel.transmit(bb, resp);
+ //ByteArrayOutputStream out = new ByteArrayOutputStream();
+ //out.write(resp.array(), 0, resps);
+ //out.close();
+ //response = new ResponseAPDU(out.toByteArray());
+ response = channel.transmit(new CommandAPDU(cmd));
+ } else { // (> 0xFF)
+ // divide payload
+ int length = payload.length;
+ int offset = 0;
+ int curlen = 0;
+ boolean first = true;
+ while(length > 0) {
+ curlen = (length > 0xF4) ? 0xF4 : length;
+ ByteArrayOutputStream dpay = new ByteArrayOutputStream();
+ dpay.write(con);
+ if(first) {
+ dpay.write(MSCMService.intToBytes(payload.length-18));
+ dpay.write(MSCMService.intToBytes(curlen-18));
+ } else {
+ dpay.write(MSCMService.intToBytes(offset-18));
+ dpay.write(MSCMService.intToBytes(curlen));
+ }
+ first = false;
+
+ dpay.write(payload, offset, curlen);
+ dpay.close();
+ byte[] ppay = dpay.toByteArray();
+
+ cmdbuffer.write(header);
+ len[0] = (byte)ppay.length;
+ cmdbuffer.write(len);
+ cmdbuffer.write(ppay);
+
+ length -= curlen;
+ offset += curlen;
+
+ cmd = cmdbuffer.toByteArray();
+ String str = MSCMService.bytArrayToHex(cmd);
+ log.info("Sending: >>> " + str);
+ response = channel.transmit(new CommandAPDU(cmd));
+
+
+ //ByteBuffer bb = ByteBuffer.wrap(cmd);
+ //ByteBuffer resp = ByteBuffer.allocate(18000);
+ //response = channel.transmit(bb, resp);
+ //int resps = channel.transmit(bb, resp);
+ //ByteArrayOutputStream out = new ByteArrayOutputStream();
+ //out.write(resp.array(), 0, resps);
+ //out.close();
+ //response = new ResponseAPDU(out.toByteArray());
+ log.info("Resp: <<< " + MSCMService.bytArrayToHex(MSCMService.intToBytes(response.getSW())));
+ cmdbuffer.reset();
+ }
+ }
+
+ log.info(" SW : <<< " + MSCMService.bytArrayToHex(
+ MSCMService.intToBytes(response.getSW())));
+ byte[] data = response.getData();
+ log.info("DATA: <<< " + MSCMService.bytArrayToHex(data));
+
+ if(data.length == 0) {
+ return null;
+ }
+
+ MSCMDecoder.checkExceptionInResponse(data, 0);
+
+ if(expectedType == HIVECODE_TYPE_SYSTEM_VOID) {
+ return data;
+ }
+
+ String namespaceString = MSCMDecoder.namespaceHiveToString(data, 0);
+ String typeString = MSCMDecoder.typeHiveToString(data, 4);
+ short resultType = MSCMService.bytesToShort(data, 4);
+ if(expectedType == resultType) {
+ ByteArrayOutputStream str = new ByteArrayOutputStream();
+ str.write(data, 6, data.length-6);
+ return str.toByteArray();
+ } else {
+ throw new CardException("Wrong result type");
+ }/*
+ if(typeString.equals(HIVECODE_TYPE_SYSTEM_STRING_STRING)) {
+ System.out.println(namespaceString + "." + typeString + ": " +
+ MSCMDecoder.decodeString(data, 6));
+ } else if(typeString.equals(HIVECODE_TYPE_SYSTEM_STRING_ARRAY_STRING)) {
+ String[] results = MSCMDecoder.decodeStringArray(data, 6);
+ System.out.println(typeString + ": ");
+ for(String str : results) {
+ System.out.println(str);
+ }
+ } else {
+ System.out.println(namespaceString + "." + typeString + ": " +
+ MSCMService.bytArrayToHex(MSCMDecoder.decodeByteArray(data, 6)));
+ }
+ return data;*/
+ }
+
+}