From b95a023faa4b6248c9526d1a76ed4e26b1dfc997 Mon Sep 17 00:00:00 2001 From: tkellner Date: Tue, 3 Sep 2013 15:38:58 +0000 Subject: Gemalto .NET V2 Card integration git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@1201 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../java/at/gv/egiz/smcc/GemaltoNetV2_0Card.java | 513 +++++++++++++++++++++ .../java/at/gv/egiz/smcc/SignatureCardFactory.java | 12 + .../main/java/at/gv/egiz/smcc/T0CardChannel.java | 4 +- .../java/at/gv/egiz/smcc/util/MSCMConstants.java | 220 +++++++++ .../java/at/gv/egiz/smcc/util/MSCMDecoder.java | 259 +++++++++++ .../java/at/gv/egiz/smcc/util/MSCMException.java | 23 + .../java/at/gv/egiz/smcc/util/MSCMService.java | 273 +++++++++++ .../java/at/gv/egiz/smcc/util/MSCMTransfer.java | 146 ++++++ 8 files changed, 1448 insertions(+), 2 deletions(-) create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/GemaltoNetV2_0Card.java create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/util/MSCMConstants.java create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/util/MSCMDecoder.java create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/util/MSCMException.java create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/util/MSCMService.java create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/util/MSCMTransfer.java (limited to 'smcc/src') 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 namespaces; + + private static Map types; + + private static Map exceptions; + + static { + namespaces = new HashMap(); + 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(); + + 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(); + 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;*/ + } + +} -- cgit v1.2.3