summaryrefslogtreecommitdiff
path: root/smcc/src/main/java
diff options
context:
space:
mode:
authormcentner <mcentner@8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4>2010-05-05 15:29:01 +0000
committermcentner <mcentner@8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4>2010-05-05 15:29:01 +0000
commitb1c8641a63a67e3c64d948f9e8dce5c01e11e2dd (patch)
tree0883f08a408f89f758e9a1be629232e3dd055c3a /smcc/src/main/java
parent83a9b613836910f7edc370c2fe60fa2268dc4461 (diff)
downloadmocca-b1c8641a63a67e3c64d948f9e8dce5c01e11e2dd.tar.gz
mocca-b1c8641a63a67e3c64d948f9e8dce5c01e11e2dd.tar.bz2
mocca-b1c8641a63a67e3c64d948f9e8dce5c01e11e2dd.zip
Merged feature branch mocca-1.2.13-id@r724 back to trunk.
git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@725 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4
Diffstat (limited to 'smcc/src/main/java')
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java134
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java22
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/BELPICCard.java23
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/EstEIDCard.java280
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/ExclSignatureCardProxy.java11
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/ITCard.java24
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/LogCardChannel.java16
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/PINConfirmationException.java3
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/PINFormatException.java3
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/PINMgmtSignatureCard.java20
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/PinInfo.java (renamed from smcc/src/main/java/at/gv/egiz/smcc/PINSpec.java)123
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/PtEidCard.java310
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java218
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/SWCard.java12
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java61
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/pin/gui/ModifyPINGUI.java10
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/pin/gui/ModifyPINProvider.java6
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/pin/gui/PINGUI.java6
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/pin/gui/PINProvider.java4
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/reader/CardReader.java32
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/reader/DefaultCardReader.java16
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/reader/PinpadCardReader.java167
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/reader/ReaderFactory.java32
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/util/ISO7816Utils.java51
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/util/SMCCHelper.java268
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/util/SmartCardIO.java358
26 files changed, 1449 insertions, 761 deletions
diff --git a/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java b/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java
index 9b3b88ed..e35aa5a4 100644
--- a/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java
+++ b/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java
@@ -26,7 +26,6 @@ import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
-import java.util.List;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
@@ -40,8 +39,8 @@ import javax.smartcardio.CardTerminal;
import javax.smartcardio.CommandAPDU;
import javax.smartcardio.ResponseAPDU;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import at.gv.egiz.smcc.util.ISO7816Utils;
import at.gv.egiz.smcc.util.SMCCHelper;
@@ -49,7 +48,7 @@ import at.gv.egiz.smcc.util.TransparentFileInputStream;
public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureCard {
- private static Log log = LogFactory.getLog(ACOSCard.class);
+ private final Logger log = LoggerFactory.getLogger(ACOSCard.class);
public static final byte[] AID_DEC = new byte[] { (byte) 0xA0, (byte) 0x00,
(byte) 0x00, (byte) 0x01, (byte) 0x18, (byte) 0x45, (byte) 0x4E };
@@ -115,22 +114,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC
(byte) 0x01 // RSA // TODO: Not verified yet
};
- private static final PINSpec DEC_PIN_SPEC = new PINSpec(0, 8, "[0-9]",
- "at/gv/egiz/smcc/ACOSCard", "dec.pin", KID_PIN_DEC, AID_DEC);
-
- private static final PINSpec SIG_PIN_SPEC = new PINSpec(0, 8, "[0-9]",
- "at/gv/egiz/smcc/ACOSCard", "sig.pin", KID_PIN_SIG, AID_SIG);
-
- private static final PINSpec INF_PIN_SPEC = new PINSpec(0, 8, "[0-9]",
- "at/gv/egiz/smcc/ACOSCard", "inf.pin", KID_PIN_INF, AID_DEC);
-
- static {
- if (SignatureCardFactory.ENFORCE_RECOMMENDED_PIN_LENGTH) {
- DEC_PIN_SPEC.setRecLength(4);
- SIG_PIN_SPEC.setRecLength(6);
- INF_PIN_SPEC.setRecLength(4);
- }
- }
+ protected PinInfo decPinInfo, sigPinInfo, infPinInfo;
/**
* The version of the card's digital signature application.
@@ -160,20 +144,29 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC
appVersion = 1;
log.info("a-sign premium application version = " + appVersion);
} catch (SignatureCardException e) {
- log.warn(e);
+ log.warn("Failed to execute command.", e);
appVersion = 0;
} catch (IOException e) {
- log.warn(e);
+ log.warn("Failed to execute command.", e);
appVersion = 0;
} catch (CardException e) {
- log.warn(e);
+ log.warn("Failed to execute command.", e);
appVersion = 0;
- }
-
- pinSpecs.add(DEC_PIN_SPEC);
- pinSpecs.add(SIG_PIN_SPEC);
- if (appVersion < 2) {
- pinSpecs.add(INF_PIN_SPEC);
+ }
+
+ decPinInfo = new PinInfo(0, 8, "[0-9]",
+ "at/gv/egiz/smcc/ACOSCard", "dec.pin", KID_PIN_DEC, AID_DEC, 10);
+
+ sigPinInfo = new PinInfo(0, 8, "[0-9]",
+ "at/gv/egiz/smcc/ACOSCard", "sig.pin", KID_PIN_SIG, AID_SIG, 10);
+
+ infPinInfo= new PinInfo(0, 8, "[0-9]",
+ "at/gv/egiz/smcc/ACOSCard", "inf.pin", KID_PIN_INF, AID_DEC, 10);
+
+ if (SignatureCardFactory.ENFORCE_RECOMMENDED_PIN_LENGTH) {
+ decPinInfo.setRecLength(4);
+ sigPinInfo.setRecLength(6);
+ infPinInfo.setRecLength(4);
}
}
@@ -205,7 +198,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC
int maxSize = -1;
if (getAppVersion() < 2) {
maxSize = ISO7816Utils.getLengthFromFCx(fcx);
- log.debug("Size of selected file = " + maxSize);
+ log.debug("Size of selected file = {}.", maxSize);
}
// READ BINARY
byte[] certificate = ISO7816Utils.readTransparentFileTLV(channel, maxSize, (byte) 0x30);
@@ -251,13 +244,13 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC
// SELECT file
byte[] fcx = execSELECT_FID(channel, EF_INFOBOX);
int maxSize = ISO7816Utils.getLengthFromFCx(fcx);
- log.debug("Size of selected file = " + maxSize);
+ log.debug("Size of selected file = {}.", maxSize);
// READ BINARY
while(true) {
try {
return ISO7816Utils.readTransparentFileTLV(channel, maxSize, (byte) 0x30);
} catch (SecurityStatusNotSatisfiedException e) {
- verifyPINLoop(channel, INF_PIN_SPEC, provider);
+ verifyPINLoop(channel, infPinInfo, provider);
}
}
@@ -295,7 +288,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC
b = is.read();
if (b != 0x01) {
- String msg = "Infobox structure v" + b + " not supported.";
+ String msg = "Infobox structure v{}" + b + " not supported.";
log.info(msg);
throw new SignatureCardException(msg);
}
@@ -348,7 +341,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC
plainKey = execPSO_DECIPHER(channel, key);
break;
} catch(SecurityStatusNotSatisfiedException e) {
- verifyPINLoop(channel, DEC_PIN_SPEC, provider);
+ verifyPINLoop(channel, decPinInfo, provider);
}
}
@@ -444,14 +437,12 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC
if (KeyboxName.SECURE_SIGNATURE_KEYPAIR.equals(keyboxName)) {
- PINSpec spec = SIG_PIN_SPEC;
-
// SELECT application
execSELECT_AID(channel, AID_SIG);
// MANAGE SECURITY ENVIRONMENT : SET DST
execMSE(channel, 0x41, 0xb6, dst.toByteArray());
// VERIFY
- verifyPINLoop(channel, spec, provider);
+ verifyPINLoop(channel, sigPinInfo, provider);
// PERFORM SECURITY OPERATION : HASH
execPSO_HASH(channel, digest);
// PERFORM SECURITY OPERATION : COMPUTE DIGITAL SIGNATRE
@@ -459,8 +450,6 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC
} else if (KeyboxName.CERITIFIED_KEYPAIR.equals(keyboxName)) {
- PINSpec spec = DEC_PIN_SPEC;
-
// SELECT application
execSELECT_AID(channel, AID_DEC);
// MANAGE SECURITY ENVIRONMENT : SET AT
@@ -471,7 +460,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC
// INTERNAL AUTHENTICATE
return execINTERNAL_AUTHENTICATE(channel, digest);
} catch (SecurityStatusNotSatisfiedException e) {
- verifyPINLoop(channel, spec, provider);
+ verifyPINLoop(channel, decPinInfo, provider);
}
}
@@ -481,7 +470,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC
}
} catch (CardException e) {
- log.warn(e);
+ log.warn("Failed to execute command.", e);
throw new SignatureCardException("Failed to access card.", e);
}
@@ -492,10 +481,10 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC
}
/* (non-Javadoc)
- * @see at.gv.egiz.smcc.AbstractSignatureCard#verifyPIN(at.gv.egiz.smcc.PINSpec, at.gv.egiz.smcc.PINProvider)
+ * @see at.gv.egiz.smcc.AbstractSignatureCard#verifyPIN(at.gv.egiz.smcc.pinInfo, at.gv.egiz.smcc.PINProvider)
*/
@Override
- public void verifyPIN(PINSpec pinSpec, PINGUI pinProvider)
+ public void verifyPIN(PinInfo pinInfo, PINGUI pinProvider)
throws LockedException, NotActivatedException, CancelledException,
TimeoutException, SignatureCardException, InterruptedException {
@@ -503,9 +492,9 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC
try {
// SELECT application
- execSELECT_AID(channel, pinSpec.getContextAID());
+ execSELECT_AID(channel, pinInfo.getContextAID());
// VERIFY
- verifyPINLoop(channel, pinSpec, pinProvider);
+ verifyPINLoop(channel, pinInfo, pinProvider);
} catch (CardException e) {
log.info("Failed to verify PIN.", e);
throw new SignatureCardException("Failed to verify PIN.", e);
@@ -514,10 +503,10 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC
}
/* (non-Javadoc)
- * @see at.gv.egiz.smcc.AbstractSignatureCard#changePIN(at.gv.egiz.smcc.PINSpec, at.gv.egiz.smcc.ChangePINProvider)
+ * @see at.gv.egiz.smcc.AbstractSignatureCard#changePIN(at.gv.egiz.smcc.pinInfo, at.gv.egiz.smcc.ChangePINProvider)
*/
@Override
- public void changePIN(PINSpec pinSpec, ModifyPINGUI pinProvider)
+ public void changePIN(PinInfo pinInfo, ModifyPINGUI pinProvider)
throws LockedException, NotActivatedException, CancelledException,
TimeoutException, SignatureCardException, InterruptedException {
@@ -525,9 +514,9 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC
try {
// SELECT application
- execSELECT_AID(channel, pinSpec.getContextAID());
+ execSELECT_AID(channel, pinInfo.getContextAID());
// CHANGE REFERENCE DATA
- changePINLoop(channel, pinSpec, pinProvider);
+ changePINLoop(channel, pinInfo, pinProvider);
} catch (CardException e) {
log.info("Failed to change PIN.", e);
throw new SignatureCardException("Failed to change PIN.", e);
@@ -536,7 +525,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC
}
@Override
- public void activatePIN(PINSpec pinSpec, ModifyPINGUI pinGUI)
+ public void activatePIN(PinInfo pinInfo, ModifyPINGUI pinGUI)
throws CancelledException, SignatureCardException, CancelledException,
TimeoutException, InterruptedException {
log.error("ACTIVATE PIN not supported by ACOS");
@@ -544,29 +533,20 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC
}
@Override
- public void unblockPIN(PINSpec pinSpec, ModifyPINGUI pinGUI)
+ public void unblockPIN(PinInfo pinInfo, ModifyPINGUI pinGUI)
throws CancelledException, SignatureCardException, InterruptedException {
throw new SignatureCardException("Unblock PIN not supported.");
}
/* (non-Javadoc)
- * @see at.gv.egiz.smcc.PINMgmtSignatureCard#getPINSpecs()
+ * @see at.gv.egiz.smcc.PINMgmtSignatureCard#getpinInfos()
*/
@Override
- public List<PINSpec> getPINSpecs() {
- if (getAppVersion() < 2) {
- return Arrays.asList(new PINSpec[] {DEC_PIN_SPEC, SIG_PIN_SPEC, INF_PIN_SPEC});
- } else {
- return Arrays.asList(new PINSpec[] {DEC_PIN_SPEC, SIG_PIN_SPEC});
+ public PinInfo[] getPinInfos() {
+ if (appVersion < 2) {
+ return new PinInfo[] {decPinInfo, sigPinInfo, infPinInfo };
}
- }
-
- /* (non-Javadoc)
- * @see at.gv.egiz.smcc.PINMgmtSignatureCard#getPINStatus(at.gv.egiz.smcc.PINSpec)
- */
- @Override
- public PIN_STATE getPINState(PINSpec pinSpec) throws SignatureCardException {
- return PIN_STATE.UNKNOWN;
+ return new PinInfo[] {decPinInfo, sigPinInfo };
}
@Override
@@ -578,7 +558,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC
// PROTECTED METHODS (assume exclusive card access)
////////////////////////////////////////////////////////////////////////
- protected void verifyPINLoop(CardChannel channel, PINSpec spec, PINGUI provider)
+ protected void verifyPINLoop(CardChannel channel, PinInfo spec, PINGUI provider)
throws InterruptedException, CardException, SignatureCardException {
int retries = -1;
@@ -587,7 +567,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC
} while (retries > 0);
}
- protected void changePINLoop(CardChannel channel, PINSpec spec, ModifyPINGUI provider)
+ protected void changePINLoop(CardChannel channel, PinInfo spec, ModifyPINGUI provider)
throws InterruptedException, CardException, SignatureCardException {
int retries = -1;
@@ -596,44 +576,48 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC
} while (retries > 0);
}
- protected int verifyPIN(CardChannel channel, PINSpec pinSpec,
+ protected int verifyPIN(CardChannel channel, PinInfo pinInfo,
PINGUI provider, int retries) throws InterruptedException, CardException, SignatureCardException {
VerifyAPDUSpec apduSpec = new VerifyAPDUSpec(
new byte[] {
- (byte) 0x00, (byte) 0x20, (byte) 0x00, pinSpec.getKID(), (byte) 0x08,
+ (byte) 0x00, (byte) 0x20, (byte) 0x00, pinInfo.getKID(), (byte) 0x08,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 },
0, VerifyAPDUSpec.PIN_FORMAT_ASCII, 8);
- ResponseAPDU resp = reader.verify(channel, apduSpec, provider, pinSpec, retries);
+ ResponseAPDU resp = reader.verify(channel, apduSpec, provider, pinInfo, retries);
if (resp.getSW() == 0x9000) {
+ pinInfo.setActive(pinInfo.maxRetries);
return -1;
}
if (resp.getSW() >> 4 == 0x63c) {
+ pinInfo.setActive(0x0f & resp.getSW());
return 0x0f & resp.getSW();
}
switch (resp.getSW()) {
case 0x6983:
// authentication method blocked
+ pinInfo.setBlocked();
throw new LockedException();
default:
String msg = "VERIFY failed. SW=" + Integer.toHexString(resp.getSW());
log.info(msg);
+ pinInfo.setUnknown();
throw new SignatureCardException(msg);
}
}
- protected int changePIN(CardChannel channel, PINSpec pinSpec,
+ protected int changePIN(CardChannel channel, PinInfo pinInfo,
ModifyPINGUI pinProvider, int retries) throws CancelledException, InterruptedException, CardException, SignatureCardException {
ChangeReferenceDataAPDUSpec apduSpec = new ChangeReferenceDataAPDUSpec(
new byte[] {
- (byte) 0x00, (byte) 0x24, (byte) 0x00, pinSpec.getKID(), (byte) 0x10,
+ (byte) 0x00, (byte) 0x24, (byte) 0x00, pinInfo.getKID(), (byte) 0x10,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
@@ -643,23 +627,27 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC
- ResponseAPDU resp = reader.modify(channel, apduSpec, pinProvider, pinSpec, retries);
+ ResponseAPDU resp = reader.modify(channel, apduSpec, pinProvider, pinInfo, retries);
if (resp.getSW() == 0x9000) {
+ pinInfo.setActive(pinInfo.maxRetries);
return -1;
}
if (resp.getSW() >> 4 == 0x63c) {
+ pinInfo.setActive(0x0f & resp.getSW());
return 0x0f & resp.getSW();
}
switch (resp.getSW()) {
case 0x6983:
// authentication method blocked
+ pinInfo.setBlocked();
throw new LockedException();
default:
String msg = "CHANGE REFERENCE DATA failed. SW=" + Integer.toHexString(resp.getSW());
log.info(msg);
+ pinInfo.setUnknown();
throw new SignatureCardException(msg);
}
diff --git a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java
index fcb94fc6..73dadceb 100644
--- a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java
+++ b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java
@@ -18,8 +18,6 @@ package at.gv.egiz.smcc;
import at.gv.egiz.smcc.reader.CardReader;
import at.gv.egiz.smcc.reader.ReaderFactory;
-import java.util.ArrayList;
-import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;
@@ -28,14 +26,12 @@ import javax.smartcardio.CardChannel;
import javax.smartcardio.CardException;
import javax.smartcardio.CardTerminal;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public abstract class AbstractSignatureCard implements SignatureCard {
- private static Log log = LogFactory.getLog(AbstractSignatureCard.class);
-
- protected List<PINSpec> pinSpecs = new ArrayList<PINSpec>();
+ private final Logger log = LoggerFactory.getLogger(AbstractSignatureCard.class);
private ResourceBundle i18n;
private String resourceBundleName;
@@ -118,4 +114,16 @@ public abstract class AbstractSignatureCard implements SignatureCard {
}
}
+ public void interfaceMethod(PinInfoTest pinInfo) {
+
+ }
+
+ int testMember = 3;
+
+ public static class PinInfoTest {
+
+ void setStatus(int status) {
+ }
+
+ }
}
diff --git a/smcc/src/main/java/at/gv/egiz/smcc/BELPICCard.java b/smcc/src/main/java/at/gv/egiz/smcc/BELPICCard.java
index 41358bb5..bd42f47c 100644
--- a/smcc/src/main/java/at/gv/egiz/smcc/BELPICCard.java
+++ b/smcc/src/main/java/at/gv/egiz/smcc/BELPICCard.java
@@ -29,8 +29,8 @@ import javax.smartcardio.CardException;
import javax.smartcardio.CommandAPDU;
import javax.smartcardio.ResponseAPDU;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import at.gv.egiz.smcc.util.ISO7816Utils;
import at.gv.egiz.smcc.util.SMCCHelper;
@@ -40,7 +40,7 @@ public class BELPICCard extends AbstractSignatureCard implements SignatureCard {
/**
* Logging facility.
*/
- private static Log log = LogFactory.getLog(BELPICCard.class);
+ private final Logger log = LoggerFactory.getLogger(BELPICCard.class);
public static final byte[] MF = new byte[] { (byte) 0x3F, (byte) 0x00 };
@@ -64,16 +64,15 @@ public class BELPICCard extends AbstractSignatureCard implements SignatureCard {
public static final int PINSPEC_SS = 0;
- private static final PINSpec SS_PIN_SPEC =
- new PINSpec(4, 12, "[0-9]",
- "at/gv/egiz/smcc/BELPICCard", "sig.pin", KID, DF_BELPIC);
+ protected PinInfo ssPinInfo =
+ new PinInfo(4, 12, "[0-9]",
+ "at/gv/egiz/smcc/BELPICCard", "sig.pin", KID, DF_BELPIC, PinInfo.UNKNOWN_RETRIES);
/**
* Creates a new instance.
*/
public BELPICCard() {
super("at/gv/egiz/smcc/BelpicCard");
- pinSpecs.add(SS_PIN_SPEC);
}
@Override
@@ -161,12 +160,12 @@ public class BELPICCard extends AbstractSignatureCard implements SignatureCard {
// VERIFY
execMSE(channel, 0x41, 0xb6, dst);
// PERFORM SECURITY OPERATION : COMPUTE DIGITAL SIGNATURE
- verifyPINLoop(channel, SS_PIN_SPEC, provider);
+ verifyPINLoop(channel, ssPinInfo, provider);
// MANAGE SECURITY ENVIRONMENT : SET DST
return execPSO_COMPUTE_DIGITAL_SIGNATURE(channel, digest);
} catch (CardException e) {
- log.warn(e);
+ log.warn("Failed to execute command.", e);
throw new SignatureCardException("Failed to access card.", e);
}
@@ -176,7 +175,7 @@ public class BELPICCard extends AbstractSignatureCard implements SignatureCard {
return "Belpic Card";
}
- protected void verifyPINLoop(CardChannel channel, PINSpec spec,
+ protected void verifyPINLoop(CardChannel channel, PinInfo spec,
PINGUI provider) throws LockedException, NotActivatedException,
SignatureCardException, InterruptedException, CardException {
@@ -186,7 +185,7 @@ public class BELPICCard extends AbstractSignatureCard implements SignatureCard {
} while (retries > 0);
}
- protected int verifyPIN(CardChannel channel, PINSpec pinSpec,
+ protected int verifyPIN(CardChannel channel, PinInfo pinSpec,
PINGUI provider, int retries) throws SignatureCardException,
LockedException, NotActivatedException, InterruptedException,
CardException {
@@ -281,4 +280,4 @@ public class BELPICCard extends AbstractSignatureCard implements SignatureCard {
-} \ No newline at end of file
+}
diff --git a/smcc/src/main/java/at/gv/egiz/smcc/EstEIDCard.java b/smcc/src/main/java/at/gv/egiz/smcc/EstEIDCard.java
new file mode 100644
index 00000000..93c439a3
--- /dev/null
+++ b/smcc/src/main/java/at/gv/egiz/smcc/EstEIDCard.java
@@ -0,0 +1,280 @@
+/*
+* Copyright 2009 Federal Chancellery Austria and
+* Graz University of Technology
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package at.gv.egiz.smcc;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+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.pin.gui.PINGUI;
+import at.gv.egiz.smcc.util.ISO7816Utils;
+import at.gv.egiz.smcc.util.SMCCHelper;
+
+public class EstEIDCard extends AbstractSignatureCard {
+
+ private final Logger log = LoggerFactory.getLogger(EstEIDCard.class);
+
+ public static final byte KID_PIN_2 = (byte) 0x02;
+
+ public static final byte[] DF = { (byte) 0xEE, (byte) 0xEE };
+
+ public static final byte[] EF_CERT = { (byte) 0xDD, (byte) 0x0CE };
+
+ private static final PinInfo QS_PIN_SPEC = new PinInfo(5, 12, "[0-9]",
+ "at/gv/egiz/smcc/EstEIDCard", "qs.pin", KID_PIN_2, DF, PinInfo.UNKNOWN_RETRIES);
+
+ public EstEIDCard() {
+ super("at/gv/egiz/smcc/EstEIDCard");
+ }
+
+ @Override
+ public byte[] getCertificate(KeyboxName keyboxName)
+ throws SignatureCardException, InterruptedException {
+
+ try {
+ CardChannel channel = getCardChannel();
+ // SELECT MF
+ execSELECT_MF(channel);
+ // SELECT DF
+ execSELECT_DF(channel, DF);
+ // SELECT EF CERT
+ execSELECT_EF(channel, EF_CERT);
+ // READ BINARY
+ byte[] certificate = ISO7816Utils.readTransparentFileTLV(channel, -1, (byte) 0x30);
+ if (certificate == null) {
+ throw new NotActivatedException();
+ }
+ return certificate;
+ } catch(FileNotFoundException e) {
+ throw new NotActivatedException();
+ } catch (CardException e) {
+ log.info("Failed to get certificate.", e);
+ throw new SignatureCardException(e);
+ }
+ }
+
+ @Override
+ public byte[] createSignature(InputStream input, KeyboxName keyboxName,
+ PINGUI pinGUI, String alg) throws SignatureCardException,
+ InterruptedException, IOException {
+
+ if (!"http://www.w3.org/2000/09/xmldsig#rsa-sha1".equals(alg)) {
+ throw new SignatureCardException("Card does not support algorithm " + alg + ".");
+ }
+
+ MessageDigest md;
+ try {
+ md = MessageDigest.getInstance("SHA-1");
+ } catch (NoSuchAlgorithmException e) {
+ log.error("Failed to get MessageDigest.", e);
+ throw new SignatureCardException(e);
+ }
+ // calculate message digest
+ byte[] digest = new byte[md.getDigestLength()];
+ for (int l; (l = input.read(digest)) != -1;) {
+ md.update(digest, 0, l);
+ }
+ digest = md.digest();
+
+ try {
+
+ CardChannel channel = getCardChannel();
+
+ // SELECT MF
+ execSELECT_MF(channel);
+ // SELECT DF
+ execSELECT_DF(channel, DF);
+ // MANAGE SECURITY ENVIRONMENT : RESTORE
+ execMSE(channel, 0xF3, 0x01, null);
+ // VERIFY
+ verifyPINLoop(channel, QS_PIN_SPEC, pinGUI);
+ // PERFORM SECURITY OPERATION : COMPUTE DIGITAL SIGNATURE
+ return execPSO_COMPUTE_DIGITAL_SIGNATURE(channel, digest);
+
+ } catch (CardException e) {
+ log.warn("Failed to execute command.", e);
+ throw new SignatureCardException("Failed to access card.", e);
+ }
+
+ }
+
+ @Override
+ public byte[] getInfobox(String infobox, PINGUI pinGUI, String domainId)
+ throws SignatureCardException, InterruptedException {
+
+ throw new IllegalArgumentException("Infobox '" + infobox
+ + "' not supported.");
+ }
+
+ protected void verifyPINLoop(CardChannel channel, PinInfo spec,
+ PINGUI provider) throws LockedException, NotActivatedException,
+ SignatureCardException, InterruptedException, CardException {
+
+ int retries = -1;
+ do {
+ retries = verifyPIN(channel, spec, provider, retries);
+ } while (retries >= -1);
+ }
+
+ protected int verifyPIN(CardChannel channel, PinInfo pinSpec,
+ PINGUI provider, int retries) throws SignatureCardException,
+ LockedException, NotActivatedException, InterruptedException,
+ CardException {
+
+ VerifyAPDUSpec apduSpec = new VerifyAPDUSpec(
+ new byte[] {
+ (byte) 0x00, (byte) 0x20, (byte) 0x00, pinSpec.getKID()},
+ 0, VerifyAPDUSpec.PIN_FORMAT_ASCII, 0);
+
+ ResponseAPDU resp = reader.verify(channel, apduSpec, provider, pinSpec, retries);
+
+ if (resp.getSW() == 0x9000) {
+ return -2;
+ }
+ if (resp.getSW() >> 4 == 0x63c) {
+ return 0x0f & resp.getSW();
+ }
+
+ switch (resp.getSW()) {
+ case 0x6300:
+ // incorrect PIN, number of retries not provided
+ return -1;
+ case 0x6400:
+ // ?
+ throw new TimeoutException();
+ case 0x6983:
+ // authentication method blocked
+ throw new LockedException();
+ case 0x6984:
+ // reference data not usable
+ throw new NotActivatedException();
+ case 0x6985:
+ // conditions of use not satisfied
+ throw new NotActivatedException();
+
+ default:
+ String msg = "VERIFY failed. SW=" + Integer.toHexString(resp.getSW());
+ log.info(msg);
+ throw new SignatureCardException(msg);
+ }
+
+ }
+
+
+ protected void execSELECT_MF(CardChannel channel)
+ throws SignatureCardException, CardException {
+ execSELECT(channel, 0x00, null);
+ }
+
+ protected void execSELECT_DF(CardChannel channel, byte[] fid)
+ throws SignatureCardException, CardException {
+ execSELECT(channel, 0x01, fid);
+ }
+
+ protected void execSELECT_EF(CardChannel channel, byte[] fid)
+ throws SignatureCardException, CardException {
+ execSELECT(channel, 0x02, fid);
+ }
+
+ protected void execSELECT(CardChannel channel, int p1, byte[] fid)
+ throws SignatureCardException, CardException {
+
+ CommandAPDU command;
+ if (fid != null) {
+ command = new CommandAPDU(0x00, 0xA4, p1, 0x0C, fid, 256);
+ } else {
+ command = new CommandAPDU(0x00, 0xA4, p1, 0x0C, 256);
+ }
+
+ ResponseAPDU resp = channel.transmit(command);
+
+ if (resp.getSW() == 0x6A82) {
+ String msg = "File or application not found FID="
+ + SMCCHelper.toString(fid) + " SW="
+ + Integer.toHexString(resp.getSW()) + ".";
+ log.info(msg);
+ throw new FileNotFoundException(msg);
+ } else if (resp.getSW() != 0x9000) {
+ String msg = "Failed to select application FID="
+ + SMCCHelper.toString(fid) + " SW="
+ + Integer.toHexString(resp.getSW()) + ".";
+ log.error(msg);
+ throw new SignatureCardException(msg);
+ }
+
+ }
+
+ protected void execMSE(CardChannel channel, int p1, int p2, byte[] data)
+ throws CardException, SignatureCardException {
+
+ ResponseAPDU resp;
+ if (data == null) {
+ resp = channel.transmit(new CommandAPDU(0x00, 0x22, p1, p2));
+ } else {
+ resp = channel.transmit(new CommandAPDU(0x00, 0x22, p1, p2, data));
+ }
+
+ if (resp.getSW() != 0x9000) {
+ throw new SignatureCardException("MSE:SET failed: SW="
+ + Integer.toHexString(resp.getSW()));
+ }
+
+ }
+
+ protected byte[] execPSO_COMPUTE_DIGITAL_SIGNATURE(CardChannel channel,
+ byte[] hash) throws CardException, SignatureCardException {
+
+ byte[] oid = new byte[] { (byte) 0x30, (byte) 0x21, (byte) 0x30,
+ (byte) 0x09, (byte) 0x06, (byte) 0x05, (byte) 0x2b,
+ (byte) 0x0e, (byte) 0x03, (byte) 0x02, (byte) 0x1a,
+ (byte) 0x05, (byte) 0x00, (byte) 0x04, (byte) 0x14 };
+
+ ByteArrayOutputStream data = new ByteArrayOutputStream();
+
+ try {
+ // oid
+ data.write(oid);
+ // hash
+ data.write(hash);
+ } catch (IOException e) {
+ throw new SignatureCardException(e);
+ }
+
+ ResponseAPDU resp = channel
+ .transmit(new CommandAPDU(0x00, 0x2A, 0x9E, 0x9A, data.toByteArray(), 0x80));
+
+ if (resp.getSW() != 0x9000) {
+ throw new SignatureCardException(
+ "PSO: COMPUTE DIGITAL SIGNATRE failed: SW="
+ + Integer.toHexString(resp.getSW()));
+ } else {
+ return resp.getData();
+ }
+ }
+
+}
diff --git a/smcc/src/main/java/at/gv/egiz/smcc/ExclSignatureCardProxy.java b/smcc/src/main/java/at/gv/egiz/smcc/ExclSignatureCardProxy.java
index bfbd0063..2562ae56 100644
--- a/smcc/src/main/java/at/gv/egiz/smcc/ExclSignatureCardProxy.java
+++ b/smcc/src/main/java/at/gv/egiz/smcc/ExclSignatureCardProxy.java
@@ -26,12 +26,12 @@ import javax.smartcardio.Card;
import javax.smartcardio.CardException;
import javax.smartcardio.CardTerminal;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class ExclSignatureCardProxy implements InvocationHandler {
- private static Log log = LogFactory.getLog(ExclSignatureCardProxy.class);
+ private final Logger log = LoggerFactory.getLogger(ExclSignatureCardProxy.class);
private static final Method init;
@@ -85,11 +85,10 @@ public class ExclSignatureCardProxy implements InvocationHandler {
if (card != null) {
try {
- log.trace("Invoking method " + method.getName() + "() with exclusive access.");
+ log.trace("Invoking method {}() with exclusive access.", method.getName());
card.beginExclusive();
} catch (CardException e) {
- log.info("Failed to get exclusive access to signature card "
- + signatureCard.toString() + ".");
+ log.info("Failed to get exclusive access to signature card {}.", signatureCard);
throw new SignatureCardException(e);
}
}
diff --git a/smcc/src/main/java/at/gv/egiz/smcc/ITCard.java b/smcc/src/main/java/at/gv/egiz/smcc/ITCard.java
index 64389190..9ed65d53 100644
--- a/smcc/src/main/java/at/gv/egiz/smcc/ITCard.java
+++ b/smcc/src/main/java/at/gv/egiz/smcc/ITCard.java
@@ -29,8 +29,8 @@ import javax.smartcardio.CardException;
import javax.smartcardio.CommandAPDU;
import javax.smartcardio.ResponseAPDU;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import at.gv.egiz.smcc.util.ISO7816Utils;
import at.gv.egiz.smcc.util.SMCCHelper;
@@ -40,7 +40,7 @@ public class ITCard extends AbstractSignatureCard {
/**
* Logging facility.
*/
- private static Log log = LogFactory.getLog(STARCOSCard.class);
+ private final Logger log = LoggerFactory.getLogger(STARCOSCard.class);
public static final byte[] MF = new byte[] { (byte) 0x3F, (byte) 0x00 };
@@ -48,17 +48,15 @@ public class ITCard extends AbstractSignatureCard {
public static final byte[] EF_C_Carta = new byte[] { (byte) 0x11, (byte) 0x01 };
- private static final PINSpec SS_PIN_SPEC =
- new PINSpec(5, 8, "[0-9]",
- "at/gv/egiz/smcc/ITCard", "sig.pin", (byte) 0x10,
- new byte[] { (byte) 0x11, (byte) 0x00 });
-
+ protected PinInfo ssPinInfo = new PinInfo(5, 8, "[0-9]",
+ "at/gv/egiz/smcc/ITCard", "sig.pin", (byte) 0x10,
+ new byte[] { (byte) 0x11, (byte) 0x00 }, PinInfo.UNKNOWN_RETRIES);
+
/**
* Creates a new instance.
*/
public ITCard() {
super("at/gv/egiz/smcc/ITCard");
- pinSpecs.add(SS_PIN_SPEC);
}
@Override
@@ -144,7 +142,7 @@ public class ITCard extends AbstractSignatureCard {
// SELECT MF
execSELECT_FID(channel, MF);
// VERIFY
- verifyPINLoop(channel, SS_PIN_SPEC, provider);
+ verifyPINLoop(channel, ssPinInfo, provider);
// MANAGE SECURITY ENVIRONMENT : RESTORE SE
execMSE(channel, 0xF3, 0x03, null);
// MANAGE SECURITY ENVIRONMENT : SET DST
@@ -153,13 +151,13 @@ public class ITCard extends AbstractSignatureCard {
return execPSO_COMPUTE_DIGITAL_SIGNATURE(channel, digest);
} catch (CardException e) {
- log.warn(e);
+ log.warn("Failed to execute command.", e);
throw new SignatureCardException("Failed to access card.", e);
}
}
- protected void verifyPINLoop(CardChannel channel, PINSpec spec,
+ protected void verifyPINLoop(CardChannel channel, PinInfo spec,
PINGUI provider) throws LockedException, NotActivatedException,
SignatureCardException, InterruptedException, CardException {
@@ -169,7 +167,7 @@ public class ITCard extends AbstractSignatureCard {
} while (retries >= -1);
}
- protected int verifyPIN(CardChannel channel, PINSpec pinSpec,
+ protected int verifyPIN(CardChannel channel, PinInfo pinSpec,
PINGUI provider, int retries) throws SignatureCardException,
LockedException, NotActivatedException, InterruptedException,
CardException {
diff --git a/smcc/src/main/java/at/gv/egiz/smcc/LogCardChannel.java b/smcc/src/main/java/at/gv/egiz/smcc/LogCardChannel.java
index 3fc80fa1..cbccda3d 100644
--- a/smcc/src/main/java/at/gv/egiz/smcc/LogCardChannel.java
+++ b/smcc/src/main/java/at/gv/egiz/smcc/LogCardChannel.java
@@ -24,12 +24,12 @@ import javax.smartcardio.CardException;
import javax.smartcardio.CommandAPDU;
import javax.smartcardio.ResponseAPDU;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class LogCardChannel extends CardChannel {
- protected static Log log = LogFactory.getLog(LogCardChannel.class);
+ private final Logger log = LoggerFactory.getLogger(LogCardChannel.class);
private CardChannel channel;
@@ -61,11 +61,11 @@ public class LogCardChannel extends CardChannel {
switch (command.getINS()) {
case 0x20: // VERIFY
case 0x21: // VERIFY
- case 0x24: { // CHANGE REFERENCE DATA
- // Don't log possibly sensitive command data
+ case 0x24: { // CHANGE REFERENCE DATA
+ // Don't log possibly sensitive command data
StringBuilder sb = new StringBuilder();
sb.append(command);
- sb.append('\n');
+ sb.append("\n-> ");
byte[] c = new byte[4];
c[0] = (byte) command.getCLA();
c[1] = (byte) command.getINS();
@@ -87,12 +87,12 @@ public class LogCardChannel extends CardChannel {
}; break;
default:
- log.trace(command + "\n" + toString(command.getBytes()));
+ log.trace(command + "\n-> " + toString(command.getBytes()));
}
long t0 = System.currentTimeMillis();
ResponseAPDU response = channel.transmit(command);
long t1 = System.currentTimeMillis();
- log.trace(response + " [" + (t1 - t0) + "ms]\n" + toString(response.getBytes()));
+ log.trace(response + " [" + (t1 - t0) + "ms]\n<- " + toString(response.getBytes()));
return response;
} else {
return channel.transmit(command);
diff --git a/smcc/src/main/java/at/gv/egiz/smcc/PINConfirmationException.java b/smcc/src/main/java/at/gv/egiz/smcc/PINConfirmationException.java
index 24dfa53c..4d7d34f5 100644
--- a/smcc/src/main/java/at/gv/egiz/smcc/PINConfirmationException.java
+++ b/smcc/src/main/java/at/gv/egiz/smcc/PINConfirmationException.java
@@ -23,4 +23,7 @@ package at.gv.egiz.smcc;
* @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>
*/
public class PINConfirmationException extends SignatureCardException {
+
+ private static final long serialVersionUID = 1L;
+
}
diff --git a/smcc/src/main/java/at/gv/egiz/smcc/PINFormatException.java b/smcc/src/main/java/at/gv/egiz/smcc/PINFormatException.java
index 721c63e2..08bc0f18 100644
--- a/smcc/src/main/java/at/gv/egiz/smcc/PINFormatException.java
+++ b/smcc/src/main/java/at/gv/egiz/smcc/PINFormatException.java
@@ -23,4 +23,7 @@ package at.gv.egiz.smcc;
* @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>
*/
public class PINFormatException extends SignatureCardException {
+
+ private static final long serialVersionUID = 1L;
+
}
diff --git a/smcc/src/main/java/at/gv/egiz/smcc/PINMgmtSignatureCard.java b/smcc/src/main/java/at/gv/egiz/smcc/PINMgmtSignatureCard.java
index 5091c10f..70b19ff0 100644
--- a/smcc/src/main/java/at/gv/egiz/smcc/PINMgmtSignatureCard.java
+++ b/smcc/src/main/java/at/gv/egiz/smcc/PINMgmtSignatureCard.java
@@ -19,26 +19,26 @@ package at.gv.egiz.smcc;
import at.gv.egiz.smcc.pin.gui.ModifyPINGUI;
import at.gv.egiz.smcc.pin.gui.PINGUI;
-import java.util.List;
public interface PINMgmtSignatureCard extends SignatureCard {
- public enum PIN_STATE {UNKNOWN, ACTIV, NOT_ACTIV, BLOCKED};
-
- public List<PINSpec> getPINSpecs();
+ /**
+ * PinInfo declares protected methods to be used from within card implementations.
+ * DO NOT REFACTOR CARD INTERFACE AND IMPLEMENTATIONS TO SEPARATE PACKAGES
+ * @throws SignatureCardException if the card is STARCOS G3 and not activated (G3 pin activation fails if card not active)
+ */
+ public PinInfo[] getPinInfos() throws SignatureCardException;
- public PIN_STATE getPINState(PINSpec pinSpec) throws SignatureCardException;
-
- public void verifyPIN(PINSpec pinSpec, PINGUI pinGUI)
+ public void verifyPIN(PinInfo pinInfo, PINGUI pinGUI)
throws LockedException, NotActivatedException, CancelledException, SignatureCardException, InterruptedException;
- public void changePIN(PINSpec pinSpec, ModifyPINGUI changePINGUI)
+ public void changePIN(PinInfo pinInfo, ModifyPINGUI changePINGUI)
throws LockedException, NotActivatedException, CancelledException, PINFormatException, SignatureCardException, InterruptedException;
- public void activatePIN(PINSpec pinSpec, ModifyPINGUI activatePINGUI)
+ public void activatePIN(PinInfo pinInfo, ModifyPINGUI activatePINGUI)
throws CancelledException, SignatureCardException, InterruptedException;
- public void unblockPIN(PINSpec pinSpec, ModifyPINGUI pukGUI)
+ public void unblockPIN(PinInfo pinInfo, ModifyPINGUI pukGUI)
throws CancelledException, SignatureCardException, InterruptedException;
}
diff --git a/smcc/src/main/java/at/gv/egiz/smcc/PINSpec.java b/smcc/src/main/java/at/gv/egiz/smcc/PinInfo.java
index f68edbed..d2acf666 100644
--- a/smcc/src/main/java/at/gv/egiz/smcc/PINSpec.java
+++ b/smcc/src/main/java/at/gv/egiz/smcc/PinInfo.java
@@ -24,18 +24,25 @@ import java.util.ResourceBundle;
*
* @author mcentner
*/
-public class PINSpec {
+public class PinInfo {
+ public enum STATE {UNKNOWN, ACTIV, NOT_ACTIV, BLOCKED};
+
+ /**
+ * the number of remaining retries is unknown or irrelevant (blocked, not active states)
+ */
+ public static final int UNKNOWN_RETRIES = -1;
+
/**
* The minimum PIN length.
*/
- protected int minLength = 0;
+ protected final int minLength;
/**
* The maximum PIN length or -1 if not specified.
*/
- protected int maxLength = -1;
-
+ protected final int maxLength;
+
/**
* The recommended PIN length or -1 if not specified.
*/
@@ -44,34 +51,42 @@ public class PINSpec {
/**
* The regular expression pattern of a single PIN digit or character.
*/
- protected String rexepPattern;
+ protected final String rexepPattern;
/**
* The name of the corresponding resource bundle.
*/
- protected String resourceBundleName;
+ protected final String resourceBundleName;
/**
* The key of the PIN name in the resource bundle.
*/
- protected String nameKey;
+ protected final String nameKey;
/**
- * The name of the PIN.
- */
- protected String name;
-
- /**
* The key id to be used in VERIFY or CHANGE REFERENCE DATA APDUs.
*/
- protected byte kid;
+ protected final byte kid;
/**
* The context AID of the key id.
*/
- protected byte[] context_aid;
+ protected final byte[] context_aid;
+
+ protected final int maxRetries;
+
+ /**
+ * The current status of this PIN
+ */
+ protected STATE state = STATE.UNKNOWN;
/**
+ * number of further allowed retries (before the pin is blocked)
+ */
+ protected int retries = UNKNOWN_RETRIES;
+
+
+ /**
* Creates a new instance of this PINSpec with the given lengths, regular
* expression pattern, the ResourceBundle name and key to lookup the PIN name
* and the KID and AID.
@@ -84,8 +99,8 @@ public class PINSpec {
* @param kid the key id of the PIN
* @param contextAID the AID the KID is valid in
*/
- public PINSpec(int minLenght, int maxLength, String rexepPattern,
- String resourceBundleName, String resourceKey, byte kid, byte[] contextAID) {
+ public PinInfo(int minLenght, int maxLength, String rexepPattern,
+ String resourceBundleName, String resourceKey, byte kid, byte[] contextAID, int maxRetries) {
this.minLength = minLenght;
this.maxLength = maxLength;
@@ -94,48 +109,23 @@ public class PINSpec {
this.nameKey = resourceKey + ".name";
this.kid = kid;
this.context_aid = contextAID;
- }
-
- /**
- * Creates a new instance of this PINSpec with the given lengths, regular
- * expression pattern, the name of the PIN and the KID and AID.
- *
- * @param minLenght the minimum length of the PIN
- * @param maxLength the maximum length of the PIN, or -1 if there is no maximum length
- * @param rexepPattern the regular expression pattern of a single PIN digit or character
- * @param name the name of the PIN
- * @param kid the key id of the PIN
- * @param contextAID the AID the KID is valid in
- */
- public PINSpec(int minLenght, int maxLength, String rexepPattern,
- String name, byte kid, byte[] contextAID) {
-
- this.minLength = minLenght;
- this.maxLength = maxLength;
- this.rexepPattern = rexepPattern;
- this.name = name;
- this.kid = kid;
- this.context_aid = contextAID;
+ this.maxRetries = maxRetries;
}
/**
* This method sets the recommended PIN length.
- *
+ *
* @param recLength the recommended PIN length
*/
public void setRecLength(int recLength) {
this.recLength = recLength;
}
-
+
/**
- * @return the localized (using the default locale) name of the PIN, or the
- * name set by
- * {@link #PINSpec(int, int, String, String, byte, byte[])}.
+ * @return the localized (using the default locale) name of the PIN
*/
public String getLocalizedName() {
- if (name != null) {
- return name;
- } else if (resourceBundleName != null){
+ if (resourceBundleName != null){
try {
return ResourceBundle.getBundle(resourceBundleName).getString(nameKey);
} catch (MissingResourceException e) {
@@ -146,13 +136,10 @@ public class PINSpec {
/**
* @param locale the locale for which the name should be returned
- * @return the localized name of the PIN, or the name set by
- * {@link #PINSpec(int, int, String, String, byte, byte[])}
+ * @return the localized name of the PIN,
*/
public String getLocalizedName(Locale locale) {
- if (name != null) {
- return name;
- } else if (resourceBundleName != null) {
+ if (resourceBundleName != null) {
try {
return ResourceBundle.getBundle(resourceBundleName, locale).getString(nameKey);
} catch (MissingResourceException e) {
@@ -235,5 +222,37 @@ public class PINSpec {
public byte[] getContextAID() {
return context_aid;
}
-
+
+ public STATE getState() {
+ return state;
+ }
+
+ public int getRetries() {
+ return retries;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ //* PinInfo declares protected methods to be used from within card implementations.
+ //* DO NOT REFACTOR CARD INTERFACE AND IMPLEMENTATIONS TO SEPARATE PACKAGES
+
+ protected void setNotActive() {
+ this.state = STATE.NOT_ACTIV;
+ this.retries = UNKNOWN_RETRIES;
+ }
+
+ protected void setActive(int retries) {
+ this.state = STATE.ACTIV;
+ this.retries = retries;
+ }
+
+ protected void setBlocked() {
+ this.state = STATE.BLOCKED;
+ this.retries = UNKNOWN_RETRIES;
+ }
+
+ protected void setUnknown() {
+ this.state = STATE.UNKNOWN;
+ this.retries = UNKNOWN_RETRIES;
+ }
+
}
diff --git a/smcc/src/main/java/at/gv/egiz/smcc/PtEidCard.java b/smcc/src/main/java/at/gv/egiz/smcc/PtEidCard.java
new file mode 100644
index 00000000..8bd49e01
--- /dev/null
+++ b/smcc/src/main/java/at/gv/egiz/smcc/PtEidCard.java
@@ -0,0 +1,310 @@
+/*
+ * Copyright 2010 Federal Chancellery Austria and
+ * Graz University of Technology
+ *
+ * based on an implementation
+ *
+ * Copyright 2009 Manuel Preliteiro, MULTICERT S.A.
+ *
+ * Licensed under the EUPL, Version 1.1 or – as soon they
+ * will be approved by the European Commission - subsequent
+ * versions of the EUPL (the "Licence");
+ *
+ * You may not use this work except in compliance with the
+ * Licence.
+ *
+ * You may obtain a copy of the Licence at:
+ *
+ * http://ec.europa.eu/idabc/eupl
+ *
+ * Unless required by applicable law or agreed to in
+ * writing, software distributed under the Licence is
+ * distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ *
+ * See the Licence for the specific language governing
+ * permissions and limitations under the Licence.
+ */
+
+package at.gv.egiz.smcc;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+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.pin.gui.PINGUI;
+import at.gv.egiz.smcc.util.ISO7816Utils;
+import at.gv.egiz.smcc.util.SMCCHelper;
+
+public class PtEidCard extends AbstractSignatureCard {
+
+ private final Logger log = LoggerFactory.getLogger(PtEidCard.class);
+
+ private static final byte[] AID_APPLET = { (byte) 0x60, (byte) 0x46, (byte) 0x32,
+ (byte) 0xff, (byte) 0x00, (byte) 0x00, (byte) 0x02 };
+
+ private static final byte[] DF_ISSUES = {(byte) 0x5F, (byte) 0x00};
+
+ private static final byte[] EF_SIGN_CERT = { (byte) 0xEF, (byte) 0x08 };
+
+ private static final PinInfo QS_PIN_SPEC =
+ new PinInfo(4, 4, "[0-9]",
+ "at/gv/egiz/smcc/PtEidCard", "sig.pin", (byte) 0x82, DF_ISSUES, PinInfo.UNKNOWN_RETRIES);
+
+ protected PtEidCard() {
+ super("at/gv/egiz/smcc/PtEidCard");
+ }
+
+ @Override
+ public byte[] getCertificate(KeyboxName keyboxName)
+ throws SignatureCardException, InterruptedException {
+
+ try {
+ CardChannel channel = getCardChannel();
+ // SELECT applet
+ execSELECT_AID(channel, AID_APPLET);
+ // SELECT DF_ISSUES
+ execSELECT_FID(channel, DF_ISSUES);
+ // SELECT EF_SIGN_CERT
+ byte[] fcx = execSELECT_FID(channel, EF_SIGN_CERT);
+ int maxsize = ISO7816Utils.getLengthFromFCx(fcx);
+ // READ BINARY
+ byte[] certificate = ISO7816Utils.readTransparentFileTLV(channel, maxsize, (byte) 0x30);
+ if (certificate == null) {
+ throw new NotActivatedException();
+ }
+ return certificate;
+ } catch (FileNotFoundException e) {
+ throw new NotActivatedException();
+ } catch (CardException 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 {
+
+ if (!"http://www.w3.org/2000/09/xmldsig#rsa-sha1".equals(alg)) {
+ throw new SignatureCardException("Card does not support algorithm " + alg + ".");
+ }
+
+ final byte[] dst = {
+ (byte) 0x80, // algorithm reference
+ (byte) 0x01, (byte) 0x12, // RSASSA-PKCS1-v1.5 using SHA1
+ (byte) 0x84, // private key reference
+ (byte) 0x01, (byte) 0x01};
+
+ MessageDigest md;
+ try {
+ md = MessageDigest.getInstance("SHA-1");
+ } catch (NoSuchAlgorithmException e) {
+ log.error("Failed to get MessageDigest.", e);
+ throw new SignatureCardException(e);
+ }
+ // calculate message digest
+ byte[] digest = new byte[md.getDigestLength()];
+ for (int l; (l = input.read(digest)) != -1;) {
+ md.update(digest, 0, l);
+ }
+ digest = md.digest();
+
+
+ try {
+
+ CardChannel channel = getCardChannel();
+
+ // SELECT applet
+ execSELECT_AID(channel, AID_APPLET);
+ // SELECT DF_ISSUES
+ execSELECT_FID(channel, DF_ISSUES);
+ // VERIFY
+ verifyPINLoop(channel, QS_PIN_SPEC, pinGUI);
+ // MANAGE SECURITY ENVIRONMENT : RESTORE SE
+ execMSE(channel, 0x73, 0x03, null);
+ // MANAGE SECURITY ENVIRONMENT : SET DST
+ execMSE(channel, 0x41, 0xB6, dst);
+ // PERFORM SECURITY OPERATION : HASH
+ execPSO_HASH(channel, digest);
+ // PERFORM SECURITY OPERATION : COMPUTE DIGITAL SIGNATURE
+ return execPSO_COMPUTE_DIGITAL_SIGNATURE(channel);
+
+ } catch (CardException e) {
+ log.warn("Failed to execute command.", e);
+ throw new SignatureCardException("Failed to access card.", e);
+ }
+
+ }
+
+ protected void verifyPINLoop(CardChannel channel, PinInfo spec,
+ PINGUI provider) throws LockedException, NotActivatedException,
+ SignatureCardException, InterruptedException, CardException {
+
+ int retries = -1;
+ do {
+ retries = verifyPIN(channel, spec, provider, retries);
+ } while (retries >= -1);
+ }
+
+ protected int verifyPIN(CardChannel channel, PinInfo pinSpec,
+ PINGUI provider, int retries) throws SignatureCardException,
+ LockedException, NotActivatedException, InterruptedException,
+ CardException {
+
+ VerifyAPDUSpec apduSpec = new VerifyAPDUSpec(
+ new byte[] { (byte) 0x00, (byte) 0x20, (byte) 0x00, pinSpec.getKID(),
+ (byte) 0x08, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF },
+ 0, VerifyAPDUSpec.PIN_FORMAT_ASCII, 8);
+
+ ResponseAPDU resp = reader.verify(channel, apduSpec, provider, pinSpec, retries);
+
+ if (resp.getSW() == 0x9000) {
+ return -2;
+ }
+ if (resp.getSW() >> 4 == 0x63c) {
+ return 0x0f & resp.getSW();
+ }
+
+ switch (resp.getSW()) {
+ case 0x6300:
+ // incorrect PIN, number of retries not provided
+ return -1;
+ case 0x6983:
+ // authentication method blocked
+ throw new LockedException();
+
+ default:
+ String msg = "VERIFY failed. SW=" + Integer.toHexString(resp.getSW());
+ log.info(msg);
+ throw new SignatureCardException(msg);
+ }
+
+ }
+
+
+
+ protected void execSELECT_AID(CardChannel channel, byte[] aid)
+ throws SignatureCardException, CardException {
+
+ ResponseAPDU resp = channel.transmit(new CommandAPDU(0x00, 0xA4, 0x04,
+ 0x0C, aid, 256));
+
+ if (resp.getSW() == 0x6A82) {
+ String msg = "File or application not found FID="
+ + SMCCHelper.toString(aid) + " SW="
+ + Integer.toHexString(resp.getSW()) + ".";
+ log.info(msg);
+ throw new FileNotFoundException(msg);
+ } else if (resp.getSW() != 0x9000) {
+ String msg = "Failed to select application FID="
+ + SMCCHelper.toString(aid) + " SW="
+ + Integer.toHexString(resp.getSW()) + ".";
+ log.error(msg);
+ throw new SignatureCardException(msg);
+ }
+
+ }
+
+ protected byte[] execSELECT_FID(CardChannel channel, byte[] fid)
+ throws SignatureCardException, CardException {
+
+ ResponseAPDU resp = channel.transmit(new CommandAPDU(0x00, 0xA4, 0x00,
+ 0x00, fid, 256));
+
+ if (resp.getSW() == 0x6A82) {
+ String msg = "File or application not found FID="
+ + SMCCHelper.toString(fid) + " SW="
+ + Integer.toHexString(resp.getSW()) + ".";
+ log.info(msg);
+ throw new FileNotFoundException(msg);
+ } else if (resp.getSW() != 0x9000) {
+ String msg = "Failed to select application FID="
+ + SMCCHelper.toString(fid) + " SW="
+ + Integer.toHexString(resp.getSW()) + ".";
+ log.error(msg);
+ throw new SignatureCardException(msg);
+ } else {
+ return resp.getBytes();
+ }
+
+ }
+
+ protected void execMSE(CardChannel channel, int p1, int p2, byte[] data)
+ throws CardException, SignatureCardException {
+
+ ResponseAPDU resp;
+ if (data == null) {
+ resp = channel.transmit(new CommandAPDU(0x00, 0x22, p1, p2, 256));
+ } else {
+ resp = channel.transmit(new CommandAPDU(0x00, 0x22, p1, p2, data, 256));
+ }
+
+ if (resp.getSW() != 0x9000) {
+ throw new SignatureCardException("MSE:SET failed: SW="
+ + Integer.toHexString(resp.getSW()));
+ }
+ }
+
+ protected void execPSO_HASH(CardChannel channel, byte[] hash) throws CardException, SignatureCardException {
+
+ ByteArrayOutputStream data = new ByteArrayOutputStream(hash.length + 2);
+ try {
+ data.write(0x90);
+ data.write(hash.length);
+ data.write(hash);
+ } catch (IOException e) {
+ throw new SignatureCardException(e);
+ }
+
+ ResponseAPDU resp = channel.transmit(
+ new CommandAPDU(0x00, 0x2A, 0x90, 0xA0, data.toByteArray()));
+ if (resp.getSW() != 0x9000) {
+ throw new SignatureCardException("PSO - HASH failed: SW="
+ + Integer.toHexString(resp.getSW()));
+ }
+
+ }
+
+ protected byte[] execPSO_COMPUTE_DIGITAL_SIGNATURE(CardChannel channel)
+ throws CardException, SignatureCardException {
+
+ ResponseAPDU resp = channel
+ .transmit(new CommandAPDU(0x00, 0x2A, 0x9E, 0x9A, 0x14));
+
+ if (resp.getSW() == 0x6982) {
+ throw new SecurityStatusNotSatisfiedException();
+ } else if (resp.getSW() == 0x6983) {
+ throw new LockedException();
+ } else if (resp.getSW() != 0x9000) {
+ throw new SignatureCardException(
+ "PSO: COMPUTE DIGITAL SIGNATRE failed: SW="
+ + Integer.toHexString(resp.getSW()));
+ } else {
+ return resp.getData();
+ }
+ }
+
+}
diff --git a/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java b/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java
index b876847f..8de4eeb8 100644
--- a/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java
+++ b/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java
@@ -24,8 +24,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
-import java.util.Arrays;
-import java.util.List;
import javax.smartcardio.Card;
import javax.smartcardio.CardChannel;
@@ -34,8 +32,8 @@ import javax.smartcardio.CardTerminal;
import javax.smartcardio.CommandAPDU;
import javax.smartcardio.ResponseAPDU;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import at.gv.egiz.smcc.util.ISO7816Utils;
import at.gv.egiz.smcc.util.SMCCHelper;
@@ -45,7 +43,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu
/**
* Logging facility.
*/
- private static Log log = LogFactory.getLog(STARCOSCard.class);
+ private final Logger log = LoggerFactory.getLogger(STARCOSCard.class);
public static final byte[] MF = new byte[] { (byte) 0x3F, (byte) 0x00 };
@@ -131,30 +129,16 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu
public static final byte KID_PIN_CARD = (byte) 0x01;
- private static final PINSpec CARD_PIN_SPEC =
- new PINSpec(4, 12, "[0-9]",
- "at/gv/egiz/smcc/STARCOSCard", "card.pin", KID_PIN_CARD, null);
-
- private static final PINSpec SS_PIN_SPEC =
- new PINSpec(6, 12, "[0-9]",
- "at/gv/egiz/smcc/STARCOSCard", "sig.pin", KID_PIN_SS, AID_DF_SS);
-
- static {
- if (SignatureCardFactory.ENFORCE_RECOMMENDED_PIN_LENGTH) {
- CARD_PIN_SPEC.setRecLength(4);
- SS_PIN_SPEC.setRecLength(6);
- }
- }
-
protected double version = 1.1;
+ protected PinInfo cardPinInfo;
+ protected PinInfo ssPinInfo;
+
/**
* Creates a new instance.
*/
public STARCOSCard() {
super("at/gv/egiz/smcc/STARCOSCard");
- pinSpecs.add(CARD_PIN_SPEC);
- pinSpecs.add(SS_PIN_SPEC);
}
/* (non-Javadoc)
@@ -163,7 +147,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu
@Override
public void init(Card card, CardTerminal cardTerminal) {
super.init(card, cardTerminal);
-
+
// determine application version
CardChannel channel = getCardChannel();
try {
@@ -179,17 +163,27 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu
log.info("e-card version=" + version + " (" + generation + ")");
}
} catch (CardException e) {
- log.warn(e);
+ log.warn("Failed to execute command.", e);
} catch (SignatureCardException e) {
- log.warn(e);
+ log.warn("Failed to execute command.", e);
+ }
+
+ cardPinInfo = new PinInfo(4, 12, "[0-9]",
+ "at/gv/egiz/smcc/STARCOSCard", "card.pin", KID_PIN_CARD, null, 10);
+ ssPinInfo = new PinInfo(6, 12, "[0-9]",
+ "at/gv/egiz/smcc/STARCOSCard", "sig.pin", KID_PIN_SS, AID_DF_SS,
+ (version < 1.2) ? 3 : 10);
+
+ if (SignatureCardFactory.ENFORCE_RECOMMENDED_PIN_LENGTH) {
+ cardPinInfo.setRecLength(4);
+ ssPinInfo.setRecLength(6);
}
-
}
@Override
@Exclusive
public byte[] getCertificate(KeyboxName keyboxName)
- throws SignatureCardException, InterruptedException {
+ throws SignatureCardException {
byte[] aid;
byte[] fid;
@@ -233,8 +227,6 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu
try {
if ("IdentityLink".equals(infobox)) {
- PINSpec spec = CARD_PIN_SPEC;
-
CardChannel channel = getCardChannel();
// SELECT application
execSELECT_AID(channel, AID_INFOBOX);
@@ -245,7 +237,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu
try {
return ISO7816Utils.readTransparentFileTLV(channel, -1, (byte) 0x30);
} catch (SecurityStatusNotSatisfiedException e) {
- verifyPINLoop(channel, spec, pinGUI);
+ verifyPINLoop(channel, cardPinInfo, pinGUI);
}
}
@@ -295,7 +287,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu
}
} catch (CardException e) {
- log.warn(e);
+ log.warn("Failed to execute command.", e);
throw new SignatureCardException("Failed to access card.", e);
}
}
@@ -368,14 +360,12 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu
if (KeyboxName.SECURE_SIGNATURE_KEYPAIR.equals(keyboxName)) {
- PINSpec spec = SS_PIN_SPEC;
-
// SELECT MF
execSELECT_MF(channel);
// SELECT application
execSELECT_AID(channel, AID_DF_SS);
// VERIFY
- verifyPINLoop(channel, spec, provider);
+ verifyPINLoop(channel, ssPinInfo, provider);
// MANAGE SECURITY ENVIRONMENT : SET DST
execMSE(channel, 0x41, 0xb6, dst.toByteArray());
if (version < 1.2) {
@@ -395,8 +385,6 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu
} else if (KeyboxName.CERITIFIED_KEYPAIR.equals(keyboxName)) {
- PINSpec spec = CARD_PIN_SPEC;
-
// SELECT application
execSELECT_AID(channel, AID_DF_GS);
// MANAGE SECURITY ENVIRONMENT : SET DST
@@ -412,7 +400,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu
// PERFORM SECURITY OPERATION : COMPUTE DIGITAL SIGNATURE
return execPSO_COMPUTE_DIGITAL_SIGNATURE(channel, null);
} catch (SecurityStatusNotSatisfiedException e) {
- verifyPINLoop(channel, spec, provider);
+ verifyPINLoop(channel, cardPinInfo, provider);
}
}
@@ -422,29 +410,29 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu
}
} catch (CardException e) {
- log.warn(e);
+ log.warn("Failed to execute command.", e);
throw new SignatureCardException("Failed to access card.", e);
}
}
/* (non-Javadoc)
- * @see at.gv.egiz.smcc.AbstractSignatureCard#verifyPIN(at.gv.egiz.smcc.PINSpec, at.gv.egiz.smcc.PINProvider)
+ * @see at.gv.egiz.smcc.AbstractSignatureCard#verifyPIN(at.gv.egiz.smcc.PinInfo, at.gv.egiz.smcc.PINProvider)
*/
@Override
@Exclusive
- public void verifyPIN(PINSpec pinSpec, PINGUI pinProvider)
+ public void verifyPIN(PinInfo pinInfo, PINGUI pinProvider)
throws LockedException, NotActivatedException, CancelledException,
TimeoutException, SignatureCardException, InterruptedException {
CardChannel channel = getCardChannel();
try {
- if (pinSpec.getContextAID() != null) {
+ if (pinInfo.getContextAID() != null) {
// SELECT application
- execSELECT_AID(channel, pinSpec.getContextAID());
+ execSELECT_AID(channel, pinInfo.getContextAID());
}
- verifyPINLoop(channel, pinSpec, pinProvider);
+ verifyPINLoop(channel, pinInfo, pinProvider);
} catch (CardException e) {
log.info("Failed to verify PIN.", e);
throw new SignatureCardException("Failed to verify PIN.", e);
@@ -453,22 +441,22 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu
}
/* (non-Javadoc)
- * @see at.gv.egiz.smcc.AbstractSignatureCard#changePIN(at.gv.egiz.smcc.PINSpec, at.gv.egiz.smcc.ChangePINProvider)
+ * @see at.gv.egiz.smcc.AbstractSignatureCard#changePIN(at.gv.egiz.smcc.PinInfo, at.gv.egiz.smcc.ChangePINProvider)
*/
@Override
@Exclusive
- public void changePIN(PINSpec pinSpec, ModifyPINGUI pinGUI)
+ public void changePIN(PinInfo pinInfo, ModifyPINGUI pinGUI)
throws LockedException, NotActivatedException, CancelledException,
TimeoutException, SignatureCardException, InterruptedException {
CardChannel channel = getCardChannel();
try {
- if (pinSpec.getContextAID() != null) {
+ if (pinInfo.getContextAID() != null) {
// SELECT application
- execSELECT_AID(channel, pinSpec.getContextAID());
+ execSELECT_AID(channel, pinInfo.getContextAID());
}
- changePINLoop(channel, pinSpec, pinGUI);
+ changePINLoop(channel, pinInfo, pinGUI);
} catch (CardException e) {
log.info("Failed to change PIN.", e);
throw new SignatureCardException("Failed to change PIN.", e);
@@ -477,22 +465,22 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu
}
/* (non-Javadoc)
- * @see at.gv.egiz.smcc.AbstractSignatureCard#activatePIN(at.gv.egiz.smcc.PINSpec, at.gv.egiz.smcc.PINProvider)
+ * @see at.gv.egiz.smcc.AbstractSignatureCard#activatePIN(at.gv.egiz.smcc.PinInfo, at.gv.egiz.smcc.PINProvider)
*/
@Override
@Exclusive
- public void activatePIN(PINSpec pinSpec, ModifyPINGUI activatePINGUI)
+ public void activatePIN(PinInfo pinInfo, ModifyPINGUI activatePINGUI)
throws CancelledException, SignatureCardException, CancelledException,
TimeoutException, InterruptedException {
CardChannel channel = getCardChannel();
try {
- if (pinSpec.getContextAID() != null) {
+ if (pinInfo.getContextAID() != null) {
// SELECT application
- execSELECT_AID(channel, pinSpec.getContextAID());
+ execSELECT_AID(channel, pinInfo.getContextAID());
}
- activatePIN(channel, pinSpec, activatePINGUI);
+ activatePIN(channel, pinInfo, activatePINGUI);
} catch (CardException e) {
log.info("Failed to activate PIN.", e);
throw new SignatureCardException("Failed to activate PIN.", e);
@@ -501,15 +489,15 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu
}
/* (non-Javadoc)
- * @see at.gv.egiz.smcc.PINMgmtSignatureCard#unblockPIN(at.gv.egiz.smcc.PINSpec, at.gv.egiz.smcc.PINProvider)
+ * @see at.gv.egiz.smcc.PINMgmtSignatureCard#unblockPIN(at.gv.egiz.smcc.PinInfo, at.gv.egiz.smcc.PINProvider)
*/
@Override
- public void unblockPIN(PINSpec pinSpec, ModifyPINGUI pukProvider)
+ public void unblockPIN(PinInfo pinInfo, ModifyPINGUI pukProvider)
throws CancelledException, SignatureCardException, InterruptedException {
CardChannel channel = getCardChannel();
try {
- unblockPINLoop(channel, pinSpec, pukProvider);
+ unblockPINLoop(channel, pinInfo, pukProvider);
} catch (CardException e) {
log.info("Failed to activate PIN.", e);
throw new SignatureCardException("Failed to activate PIN.", e);
@@ -520,7 +508,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu
public void reset() throws SignatureCardException {
try {
super.reset();
- log.debug("select MF (e-card workaround)");
+ log.debug("Select MF (e-card workaround).");
CardChannel channel = getCardChannel();
ResponseAPDU resp = channel.transmit(new CommandAPDU(0x00, 0xA4, 0x00, 0x0C));
if (resp.getSW() != 0x9000) {
@@ -533,41 +521,39 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu
}
/* (non-Javadoc)
- * @see at.gv.egiz.smcc.PINMgmtSignatureCard#getPINSpecs()
+ * @see at.gv.egiz.smcc.PINMgmtSignatureCard#getPinInfos()
*/
@Override
- public List<PINSpec> getPINSpecs() {
- return Arrays.asList(new PINSpec[] {CARD_PIN_SPEC, SS_PIN_SPEC});
- }
+ public PinInfo[] getPinInfos() throws SignatureCardException {
+
+ if (version >= 1.2) {
+ //check if card is activated
+ getCertificate(KeyboxName.SECURE_SIGNATURE_KEYPAIR);
+ }
+
+ PinInfo[] pinInfos = new PinInfo[] {cardPinInfo, ssPinInfo};
- /* (non-Javadoc)
- * @see at.gv.egiz.smcc.PINMgmtSignatureCard#getPINStatus(at.gv.egiz.smcc.PINSpec)
- */
- @Override
- public PIN_STATE getPINState(PINSpec pinSpec) throws SignatureCardException {
-
CardChannel channel = getCardChannel();
-
- try {
- if (pinSpec.getContextAID() != null) {
- // SELECT AID
- execSELECT_AID(channel, pinSpec.getContextAID());
+ for (PinInfo pinInfo : pinInfos) {
+ if (pinInfo.getState() == PinInfo.STATE.UNKNOWN ) {
+ try {
+ log.debug("Query pin status for {}.", pinInfo.getLocalizedName());
+ if (pinInfo.getContextAID() != null) {
+ execSELECT_AID(channel, pinInfo.getContextAID());
+ }
+ verifyPIN(channel, pinInfo, null, 0);
+ } catch (Exception e) {
+ log.trace("Failed to execute command.", e);
+ // status already set by verifyPIN
+ }
+ } else if (log.isTraceEnabled()) {
+ log.trace("assume pin status {} to be up to date", pinInfo.getState());
}
- verifyPIN(channel, pinSpec, null, 0);
- return PIN_STATE.ACTIV;
- } catch (InterruptedException e) {
- return PIN_STATE.UNKNOWN;
- } catch (LockedException e) {
- return PIN_STATE.BLOCKED;
- } catch (NotActivatedException e) {
- return PIN_STATE.NOT_ACTIV;
- } catch (CardException e) {
- log.error("Failed to get PIN status.", e);
- throw new SignatureCardException("Failed to get PIN status.", e);
}
-
+ return pinInfos;
}
+ @Override
public String toString() {
return "e-card";
}
@@ -576,110 +562,121 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu
// PROTECTED METHODS (assume exclusive card access)
////////////////////////////////////////////////////////////////////////
- protected void verifyPINLoop(CardChannel channel, PINSpec spec, PINGUI provider)
+ protected void verifyPINLoop(CardChannel channel, PinInfo pinInfo, PINGUI provider)
throws LockedException, NotActivatedException, SignatureCardException,
InterruptedException, CardException {
- int retries = verifyPIN(channel, spec, null, -1);
+ int retries = verifyPIN(channel, pinInfo, null, -1);
do {
- retries = verifyPIN(channel, spec, provider, retries);
+ retries = verifyPIN(channel, pinInfo, provider, retries);
} while (retries > 0);
}
- protected void changePINLoop(CardChannel channel, PINSpec spec, ModifyPINGUI provider)
+ protected void changePINLoop(CardChannel channel, PinInfo pinInfo, ModifyPINGUI provider)
throws LockedException, NotActivatedException, SignatureCardException,
InterruptedException, CardException {
- int retries = verifyPIN(channel, spec, null, -1);
+ int retries = verifyPIN(channel, pinInfo, null, -1);
do {
- retries = changePIN(channel, spec, provider, retries);
+ retries = changePIN(channel, pinInfo, provider, retries);
} while (retries > 0);
}
- protected void unblockPINLoop(CardChannel channel, PINSpec spec, ModifyPINGUI provider)
+ protected void unblockPINLoop(CardChannel channel, PinInfo pinInfo, ModifyPINGUI provider)
throws LockedException, NotActivatedException, SignatureCardException,
InterruptedException, CardException {
//TODO get PUK retry counter from EF FID 0036 in MF
int retries = -1;
do {
- retries = unblockPIN(channel, spec, provider, retries);
+ retries = unblockPIN(channel, pinInfo, provider, retries);
} while (retries > 0);
}
- protected int verifyPIN(CardChannel channel, PINSpec pinSpec,
+ protected int verifyPIN(CardChannel channel, PinInfo pinInfo,
PINGUI provider, int retries) throws SignatureCardException,
LockedException, NotActivatedException, InterruptedException,
CardException {
VerifyAPDUSpec apduSpec = new VerifyAPDUSpec(
new byte[] {
- (byte) 0x00, (byte) 0x20, (byte) 0x00, pinSpec.getKID(), (byte) 0x08,
+ (byte) 0x00, (byte) 0x20, (byte) 0x00, pinInfo.getKID(), (byte) 0x08,
(byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
(byte) 0xff, (byte) 0xff, (byte) 0xff },
1, VerifyAPDUSpec.PIN_FORMAT_BCD, 7, 4, 4);
ResponseAPDU resp;
if (provider != null) {
- resp = reader.verify(channel, apduSpec, provider, pinSpec, retries);
+ resp = reader.verify(channel, apduSpec, provider, pinInfo, retries);
} else {
- resp = channel.transmit(new CommandAPDU(0x00, 0x20, 0x00, pinSpec.getKID()));
+ resp = channel.transmit(new CommandAPDU(0x00, 0x20, 0x00, pinInfo.getKID()));
}
if (resp.getSW() == 0x9000) {
+ pinInfo.setActive(pinInfo.maxRetries);
return -1;
} else if (resp.getSW() == 0x6983 || resp.getSW() == 0x63c0) {
// authentication method blocked (0x63c0 returned by 'short' VERIFY)
+ pinInfo.setBlocked();
throw new LockedException();
} else if (resp.getSW() == 0x6984 || resp.getSW() == 0x6985) {
// reference data not usable; conditions of use not satisfied
+ pinInfo.setNotActive();
throw new NotActivatedException();
} else if (resp.getSW() >> 4 == 0x63c) {
+ pinInfo.setActive(0x0f & resp.getSW());
return 0x0f & resp.getSW();
} else if (version >= 1.2 && resp.getSW() == 0x6400) {
String msg = "VERIFY failed, card not activated. SW=0x6400";
log.error(msg);
+ pinInfo.setNotActive();
throw new SignatureCardException(msg);
} else {
String msg = "VERIFY failed. SW=" + Integer.toHexString(resp.getSW());
log.error(msg);
+ pinInfo.setUnknown();
throw new SignatureCardException(msg);
}
}
- protected int changePIN(CardChannel channel, PINSpec pinSpec,
+ protected int changePIN(CardChannel channel, PinInfo pinInfo,
ModifyPINGUI pinProvider, int retries) throws CancelledException,
InterruptedException, CardException, SignatureCardException {
ChangeReferenceDataAPDUSpec apduSpec = new ChangeReferenceDataAPDUSpec(
new byte[] {
- (byte) 0x00, (byte) 0x24, (byte) 0x00, pinSpec.getKID(), (byte) 0x10,
+ (byte) 0x00, (byte) 0x24, (byte) 0x00, pinInfo.getKID(), (byte) 0x10,
(byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
(byte) 0xff, (byte) 0xff, (byte) 0xff,
(byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
(byte) 0xff, (byte) 0xff, (byte) 0xff },
1, VerifyAPDUSpec.PIN_FORMAT_BCD, 7, 4, 4, 8);
- ResponseAPDU resp = reader.modify(channel, apduSpec, pinProvider, pinSpec, retries);
+ ResponseAPDU resp = reader.modify(channel, apduSpec, pinProvider, pinInfo, retries);
if (resp.getSW() == 0x9000) {
+ pinInfo.setActive(pinInfo.maxRetries);
return -1;
} else if (resp.getSW() == 0x6983) {
// authentication method blocked
+ pinInfo.setBlocked();
throw new LockedException();
} else if (resp.getSW() == 0x6984) {
+ pinInfo.setNotActive();
throw new NotActivatedException();
} else if (resp.getSW() >> 4 == 0x63c) {
+ pinInfo.setActive(0x0f & resp.getSW());
return 0x0f & resp.getSW();
} else {
String msg = "CHANGE REFERENCE DATA failed. SW=" + Integer.toHexString(resp.getSW());
log.error(msg);
+ pinInfo.setUnknown();
throw new SignatureCardException(msg);
}
}
- protected int activatePIN(CardChannel channel, PINSpec pinSpec,
+ protected int activatePIN(CardChannel channel, PinInfo pinInfo,
ModifyPINGUI provider) throws SignatureCardException,
InterruptedException, CardException {
@@ -687,35 +684,37 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu
if (version < 1.2) {
NewReferenceDataAPDUSpec apduSpec = new NewReferenceDataAPDUSpec(
new byte[] {
- (byte) 0x00, (byte) 0x24, (byte) 0x01, pinSpec.getKID(), (byte) 0x08,
+ (byte) 0x00, (byte) 0x24, (byte) 0x01, pinInfo.getKID(), (byte) 0x08,
(byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
(byte) 0xff, (byte) 0xff, (byte) 0xff },
1, VerifyAPDUSpec.PIN_FORMAT_BCD, 7, 4, 4);
- resp = reader.modify(channel, apduSpec, provider, pinSpec);
+ resp = reader.modify(channel, apduSpec, provider, pinInfo);
} else {
NewReferenceDataAPDUSpec apduSpec = new NewReferenceDataAPDUSpec(
new byte[] {
- (byte) 0x00, (byte) 0x24, (byte) 0x00, pinSpec.getKID(), (byte) 0x10,
+ (byte) 0x00, (byte) 0x24, (byte) 0x00, pinInfo.getKID(), (byte) 0x10,
(byte) 0x26, (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0xff,
(byte) 0xff, (byte) 0xff, (byte) 0xff,
(byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
(byte) 0xff, (byte) 0xff, (byte) 0xff },
1, VerifyAPDUSpec.PIN_FORMAT_BCD, 7, 4, 4);
apduSpec.setPinInsertionOffsetNew(8);
- resp = reader.modify(channel, apduSpec, provider, pinSpec);
+ resp = reader.modify(channel, apduSpec, provider, pinInfo);
}
if (resp.getSW() == 0x9000) {
+ pinInfo.setActive(pinInfo.maxRetries);
return -1;
} else {
String msg = "CHANGE REFERENCE DATA failed. SW=" + Integer.toHexString(resp.getSW());
log.error(msg);
+ pinInfo.setUnknown();
throw new SignatureCardException(msg);
}
}
- protected int unblockPIN(CardChannel channel, PINSpec pinSpec,
+ protected int unblockPIN(CardChannel channel, PinInfo pinInfo,
ModifyPINGUI provider, int retries) throws SignatureCardException,
InterruptedException, CardException {
@@ -726,27 +725,32 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu
ResetRetryCounterAPDUSpec apduSpec = new ResetRetryCounterAPDUSpec(
new byte[] {
- (byte) 0x00, (byte) 0x2c, (byte) 0x00, pinSpec.getKID(), (byte) 0x10,
+ (byte) 0x00, (byte) 0x2c, (byte) 0x00, pinInfo.getKID(), (byte) 0x10,
(byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
(byte) 0xff, (byte) 0xff, (byte) 0xff,
(byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
(byte) 0xff, (byte) 0xff, (byte) 0xff },
1, VerifyAPDUSpec.PIN_FORMAT_BCD, 7, 4, 4, 8);
- ResponseAPDU resp = reader.modify(channel, apduSpec, provider, pinSpec, retries);
+ ResponseAPDU resp = reader.modify(channel, apduSpec, provider, pinInfo, retries);
if (resp.getSW() == 0x9000) {
+ pinInfo.setActive(pinInfo.maxRetries);
return -1;
} else if (resp.getSW() == 0x6983) {
// PUK blocked
throw new LockedException();
} else if (resp.getSW() == 0x6984) {
+ // PIN not active
+ pinInfo.setNotActive();
throw new NotActivatedException();
} else if (resp.getSW() >> 4 == 0x63c) {
+ // wrong PUK, return PUK retries
return 0x0f & resp.getSW();
} else {
String msg = "RESET RETRY COUNTER failed. SW=" + Integer.toHexString(resp.getSW());
log.error(msg);
+ pinInfo.setUnknown();
throw new SignatureCardException(msg);
}
}
diff --git a/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java b/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java
index 73c7faa8..3318ab0f 100644
--- a/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java
+++ b/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java
@@ -42,8 +42,8 @@ import java.util.Locale;
import javax.smartcardio.Card;
import javax.smartcardio.CardTerminal;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import at.gv.egiz.smcc.pin.gui.PINGUI;
@@ -71,7 +71,7 @@ public class SWCard implements SignatureCard {
private static String swCardDir;
- private static Log log = LogFactory.getLog(SWCard.class);
+ private final Logger log = LoggerFactory.getLogger(SWCard.class);
private KeyStore certifiedKeyStore;
@@ -170,7 +170,7 @@ public class SWCard implements SignatureCard {
// try to load KeyStore file
String fileName = getFileName(keyStoreFileName);
- log.info("Trying to load KeyStore from file '" + fileName + "'.");
+ log.info("Trying to load KeyStore from file '{}'.", fileName);
FileInputStream keyStoreFile;
try {
@@ -313,7 +313,7 @@ public class SWCard implements SignatureCard {
if (password == null) {
- PINSpec pinSpec = new PINSpec(0, -1, ".", "KeyStore-Password", (byte) 0x01, null);
+ PinInfo pinSpec = new PinInfo(0, -1, ".", "at/gv/egiz/smcc/SWCard", "sw.pin", (byte) 0x01, null, PinInfo.UNKNOWN_RETRIES);
password = provider.providePIN(pinSpec, -1);
@@ -331,7 +331,7 @@ public class SWCard implements SignatureCard {
for (Enumeration<String> aliases = keyStore.aliases(); aliases
.hasMoreElements() && privateKey == null;) {
String alias = aliases.nextElement();
- log.debug("Found alias '" + alias + "' in keystore");
+ log.debug("Found alias '{}' in keystore.", alias);
if (keyStore.isKeyEntry(alias)) {
Key key = null;
while (key == null) {
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 9165a7d8..2cd0cc8a 100644
--- a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java
+++ b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java
@@ -25,8 +25,8 @@ import javax.smartcardio.ATR;
import javax.smartcardio.Card;
import javax.smartcardio.CardTerminal;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* A factory for creating {@link SignatureCard}s from {@link Card}s.
@@ -127,7 +127,7 @@ public class SignatureCardFactory {
/**
* Logging facility.
*/
- private static Log log = LogFactory.getLog(SignatureCardFactory.class);
+ private final Logger log = LoggerFactory.getLogger(SignatureCardFactory.class);
/**
* The instance to be returned by {@link #getInstance()}.
@@ -320,7 +320,62 @@ public class SignatureCardFactory {
(byte) 0xff, (byte) 0xff, (byte) 0xff },
"at.gv.egiz.smcc.ITCard"));
+ // EstEID cards return different ATRs depending on the reader device
+ supportedCards.add(new SupportedCard(
+ // ATR
+ // (3B:5E:11:FF:45:73:74:45:49:44:20:76:65:72:20:31:2E:30)
+ new byte[] { (byte) 0x3b, (byte) 0x5e, (byte) 0x11,
+ (byte) 0xff, (byte) 0x45, (byte) 0x73, (byte) 0x74,
+ (byte) 0x45, (byte) 0x49, (byte) 0x44, (byte) 0x20,
+ (byte) 0x76, (byte) 0x65, (byte) 0x72, (byte) 0x20,
+ (byte) 0x31, (byte) 0x2e, (byte) 0x30 },
+ // mask
+ // (ff:ff:ff:00:00:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:00:00:00:00)
+ new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff },
+ "at.gv.egiz.smcc.EstEIDCard"));
+
+ // EstEID cards return different ATRs depending on the reader device
+ supportedCards.add(new SupportedCard(
+ // ATR
+ // (3B:DE:18:FF:C0:80:B1:FE:45:1F:03:45:73:74:45:49:44:20:76:65:72:20:31:2E:30:2B)
+ new byte[] { (byte) 0x3b, (byte) 0xde, (byte) 0x18,
+ (byte) 0xff, (byte) 0xc0, (byte) 0x80, (byte) 0xb1,
+ (byte) 0xfe, (byte) 0x45, (byte) 0x1f, (byte) 0x03,
+ (byte) 0x45, (byte) 0x73, (byte) 0x74, (byte) 0x45,
+ (byte) 0x49, (byte) 0x44, (byte) 0x20, (byte) 0x76,
+ (byte) 0x65, (byte) 0x72, (byte) 0x20, (byte) 0x31,
+ (byte) 0x2e, (byte) 0x30, (byte) 0x2b },
+ // mask
+ // (ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:00:00:00:00)
+ new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff },
+ "at.gv.egiz.smcc.EstEIDCard"));
+ supportedCards.add(new SupportedCard(
+ // ATR (3B:7D:95:00:00:80:31:80:65:B0:83:11:C0:A9:83:00:90:00 -
+ // 00:00:00:00)
+ new byte[] { (byte) 0x3b, (byte) 0x7d, (byte) 0x95,
+ (byte) 0x00, (byte) 0x00, (byte) 0x80, (byte) 0x31,
+ (byte) 0x80, (byte) 0x65, (byte) 0xb0, (byte) 0x83,
+ (byte) 0x11, (byte) 0xc0, (byte) 0xa9, (byte) 0x83,
+ (byte) 0x00, (byte) 0x90, (byte) 0x00 },
+ // mask
+ // (ff:ff:ff:00:00:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:00:00:00:00)
+ new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0x00, (byte) 0x00, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0x00, (byte) 0xff, (byte) 0x00 },
+ "at.gv.egiz.smcc.PtEidCard"));
}
diff --git a/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/ModifyPINGUI.java b/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/ModifyPINGUI.java
index 00dc2d0e..2e0de76b 100644
--- a/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/ModifyPINGUI.java
+++ b/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/ModifyPINGUI.java
@@ -17,17 +17,17 @@
package at.gv.egiz.smcc.pin.gui;
import at.gv.egiz.smcc.CancelledException;
-import at.gv.egiz.smcc.PINSpec;
+import at.gv.egiz.smcc.PinInfo;
public interface ModifyPINGUI extends ModifyPINProvider {
- void modifyPINDirect(PINSpec spec, int retries) throws CancelledException, InterruptedException;
+ void modifyPINDirect(PinInfo pinInfo, int retries) throws CancelledException, InterruptedException;
void finishDirect();
- void enterCurrentPIN(PINSpec spec, int retries);
- void enterNewPIN(PINSpec spec);
- void confirmNewPIN(PINSpec spec);
+ void enterCurrentPIN(PinInfo pinInfo, int retries);
+ void enterNewPIN(PinInfo pinInfo);
+ void confirmNewPIN(PinInfo pinInfo);
void validKeyPressed();
void correctionButtonPressed();
void allKeysCleared();
diff --git a/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/ModifyPINProvider.java b/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/ModifyPINProvider.java
index 36f0097d..7933214b 100644
--- a/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/ModifyPINProvider.java
+++ b/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/ModifyPINProvider.java
@@ -17,7 +17,7 @@
package at.gv.egiz.smcc.pin.gui;
import at.gv.egiz.smcc.CancelledException;
-import at.gv.egiz.smcc.PINSpec;
+import at.gv.egiz.smcc.PinInfo;
/**
@@ -39,10 +39,10 @@ public interface ModifyPINProvider {
* @throws at.gv.egiz.smcc.CancelledException if cancelled by user
* @throws java.lang.InterruptedException
*/
- public char[] provideCurrentPIN(PINSpec spec, int retries)
+ public char[] provideCurrentPIN(PinInfo pinInfo, int retries)
throws CancelledException, InterruptedException;
- public char[] provideNewPIN(PINSpec spec)
+ public char[] provideNewPIN(PinInfo pinInfo)
throws CancelledException, InterruptedException;
}
diff --git a/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/PINGUI.java b/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/PINGUI.java
index 5199977b..92b9f14d 100644
--- a/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/PINGUI.java
+++ b/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/PINGUI.java
@@ -17,7 +17,7 @@
package at.gv.egiz.smcc.pin.gui;
import at.gv.egiz.smcc.CancelledException;
-import at.gv.egiz.smcc.PINSpec;
+import at.gv.egiz.smcc.PinInfo;
/**
@@ -27,13 +27,13 @@ import at.gv.egiz.smcc.PINSpec;
*/
public interface PINGUI extends PINProvider {
- void enterPINDirect(PINSpec spec, int retries)
+ void enterPINDirect(PinInfo pinInfo, int retries)
throws CancelledException, InterruptedException;
/**
* @throws CancelledException, InterruptedException if signature-data dialog is interrupted or cancelled
*/
- void enterPIN(PINSpec spec, int retries)
+ void enterPIN(PinInfo pinInfo, int retries)
throws CancelledException, InterruptedException;
void validKeyPressed();
void correctionButtonPressed();
diff --git a/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/PINProvider.java b/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/PINProvider.java
index 7443ee30..e8641797 100644
--- a/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/PINProvider.java
+++ b/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/PINProvider.java
@@ -17,7 +17,7 @@
package at.gv.egiz.smcc.pin.gui;
import at.gv.egiz.smcc.CancelledException;
-import at.gv.egiz.smcc.PINSpec;
+import at.gv.egiz.smcc.PinInfo;
/**
@@ -45,7 +45,7 @@ public interface PINProvider {
* @throws at.gv.egiz.smcc.CancelledException
* @throws java.lang.InterruptedException
*/
- char[] providePIN(PINSpec pinSpec, int retries)
+ char[] providePIN(PinInfo pinSpec, int retries)
throws CancelledException, InterruptedException;
}
diff --git a/smcc/src/main/java/at/gv/egiz/smcc/reader/CardReader.java b/smcc/src/main/java/at/gv/egiz/smcc/reader/CardReader.java
index a1246dd6..6c5e939b 100644
--- a/smcc/src/main/java/at/gv/egiz/smcc/reader/CardReader.java
+++ b/smcc/src/main/java/at/gv/egiz/smcc/reader/CardReader.java
@@ -23,7 +23,7 @@ import javax.smartcardio.ResponseAPDU;
import at.gv.egiz.smcc.CancelledException;
import at.gv.egiz.smcc.ChangeReferenceDataAPDUSpec;
import at.gv.egiz.smcc.NewReferenceDataAPDUSpec;
-import at.gv.egiz.smcc.PINSpec;
+import at.gv.egiz.smcc.PinInfo;
import at.gv.egiz.smcc.ResetRetryCounterAPDUSpec;
import at.gv.egiz.smcc.SignatureCardException;
import at.gv.egiz.smcc.VerifyAPDUSpec;
@@ -38,7 +38,7 @@ import javax.smartcardio.Card;
public interface CardReader {
- String[] FEATURES = new String[]{"NO_FEATURE",
+ static final String[] FEATURES = new String[]{"NO_FEATURE",
"FEATURE_VERIFY_PIN_START",
"FEATURE_VERIFY_PIN_FINISH",
"FEATURE_MODIFY_PIN_START",
@@ -57,16 +57,16 @@ public interface CardReader {
"FEATURE_GET_KEY",
"FEATURE_IFD_DISPLAY_PROPERTIES"};
- Byte FEATURE_VERIFY_PIN_START = new Byte((byte) 0x01);
- Byte FEATURE_VERIFY_PIN_FINISH = new Byte((byte) 0x02);
- Byte FEATURE_MODIFY_PIN_START = new Byte((byte) 0x03);
- Byte FEATURE_MODIFY_PIN_FINISH = new Byte((byte) 0x04);
- Byte FEATURE_GET_KEY_PRESSED = new Byte((byte) 0x05);
- Byte FEATURE_VERIFY_PIN_DIRECT = new Byte((byte) 0x06);
- Byte FEATURE_MODIFY_PIN_DIRECT = new Byte((byte) 0x07);
- Byte FEATURE_MCT_READER_DIRECT = new Byte((byte) 0x08);
- Byte FEATURE_MCT_UNIVERSAL = new Byte((byte) 0x09);
- Byte FEATURE_IFD_PIN_PROPERTIES = new Byte((byte) 0x0a);
+ static final Byte FEATURE_VERIFY_PIN_START = new Byte((byte) 0x01);
+ static final Byte FEATURE_VERIFY_PIN_FINISH = new Byte((byte) 0x02);
+ static final Byte FEATURE_MODIFY_PIN_START = new Byte((byte) 0x03);
+ static final Byte FEATURE_MODIFY_PIN_FINISH = new Byte((byte) 0x04);
+ static final Byte FEATURE_GET_KEY_PRESSED = new Byte((byte) 0x05);
+ static final Byte FEATURE_VERIFY_PIN_DIRECT = new Byte((byte) 0x06);
+ static final Byte FEATURE_MODIFY_PIN_DIRECT = new Byte((byte) 0x07);
+ static final Byte FEATURE_MCT_READER_DIRECT = new Byte((byte) 0x08);
+ static final Byte FEATURE_MCT_UNIVERSAL = new Byte((byte) 0x09);
+ static final Byte FEATURE_IFD_PIN_PROPERTIES = new Byte((byte) 0x0a);
//TODO continue list
@@ -75,18 +75,18 @@ public interface CardReader {
boolean hasFeature(Byte feature);
ResponseAPDU verify(CardChannel channel, VerifyAPDUSpec apduSpec,
- PINGUI pinGUI, PINSpec pinSpec, int retries)
+ PINGUI pinGUI, PinInfo pinInfo, int retries)
throws CancelledException, InterruptedException, CardException, SignatureCardException;
ResponseAPDU modify(CardChannel channel, ChangeReferenceDataAPDUSpec apduSpec,
- ModifyPINGUI pinGUI, PINSpec pinSpec, int retries)
+ ModifyPINGUI pinGUI, PinInfo pinInfo, int retries)
throws CancelledException, InterruptedException, CardException, SignatureCardException;
ResponseAPDU modify(CardChannel channel, NewReferenceDataAPDUSpec apduSpec,
- ModifyPINGUI pinGUI, PINSpec pinSpec)
+ ModifyPINGUI pinGUI, PinInfo pinInfo)
throws CancelledException, InterruptedException, CardException, SignatureCardException;
ResponseAPDU modify(CardChannel channel, ResetRetryCounterAPDUSpec apduSpec,
- ModifyPINGUI pinGUI, PINSpec pinSpec, int retries)
+ ModifyPINGUI pinGUI, PinInfo pinInfo, int retries)
throws CancelledException, InterruptedException, CardException, SignatureCardException;
}
diff --git a/smcc/src/main/java/at/gv/egiz/smcc/reader/DefaultCardReader.java b/smcc/src/main/java/at/gv/egiz/smcc/reader/DefaultCardReader.java
index 03a794fe..cc25a63c 100644
--- a/smcc/src/main/java/at/gv/egiz/smcc/reader/DefaultCardReader.java
+++ b/smcc/src/main/java/at/gv/egiz/smcc/reader/DefaultCardReader.java
@@ -23,12 +23,12 @@ import javax.smartcardio.CardException;
import javax.smartcardio.CardTerminal;
import javax.smartcardio.ResponseAPDU;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import at.gv.egiz.smcc.ChangeReferenceDataAPDUSpec;
import at.gv.egiz.smcc.NewReferenceDataAPDUSpec;
-import at.gv.egiz.smcc.PINSpec;
+import at.gv.egiz.smcc.PinInfo;
import at.gv.egiz.smcc.ResetRetryCounterAPDUSpec;
import at.gv.egiz.smcc.SignatureCardException;
import at.gv.egiz.smcc.VerifyAPDUSpec;
@@ -42,7 +42,7 @@ import at.gv.egiz.smcc.util.ISO7816Utils;
*/
public class DefaultCardReader implements CardReader {
- protected final static Log log = LogFactory.getLog(DefaultCardReader.class);
+ private final Logger log = LoggerFactory.getLogger(DefaultCardReader.class);
protected CardTerminal ct;
protected String name;
@@ -57,7 +57,7 @@ public class DefaultCardReader implements CardReader {
@Override
public ResponseAPDU verify(CardChannel channel, VerifyAPDUSpec apduSpec,
- PINGUI pinGUI, PINSpec pinSpec, int retries)
+ PINGUI pinGUI, PinInfo pinSpec, int retries)
throws SignatureCardException, CardException, InterruptedException {
log.debug("VERIFY");
@@ -66,7 +66,7 @@ public class DefaultCardReader implements CardReader {
@Override
public ResponseAPDU modify(CardChannel channel, ChangeReferenceDataAPDUSpec apduSpec,
- ModifyPINGUI pinGUI, PINSpec pinSpec, int retries)
+ ModifyPINGUI pinGUI, PinInfo pinSpec, int retries)
throws SignatureCardException, CardException, InterruptedException {
log.debug("MODIFY (CHANGE_REFERENCE_DATA)");
char[] oldPIN = pinGUI.provideCurrentPIN(pinSpec, retries);
@@ -76,7 +76,7 @@ public class DefaultCardReader implements CardReader {
@Override
public ResponseAPDU modify(CardChannel channel, NewReferenceDataAPDUSpec apduSpec,
- ModifyPINGUI pinGUI, PINSpec pinSpec)
+ ModifyPINGUI pinGUI, PinInfo pinSpec)
throws SignatureCardException, CardException, InterruptedException {
log.debug("MODIFY (NEW_REFERENCE_DATA)");
char[] newPIN = pinGUI.provideNewPIN(pinSpec);
@@ -85,7 +85,7 @@ public class DefaultCardReader implements CardReader {
@Override
public ResponseAPDU modify(CardChannel channel, ResetRetryCounterAPDUSpec apduSpec,
- ModifyPINGUI pinGUI, PINSpec pinSpec, int retries)
+ ModifyPINGUI pinGUI, PinInfo pinSpec, int retries)
throws InterruptedException, CardException, SignatureCardException {
log.debug("MODIFY (RESET_RETRY_COUNTER)");
//TODO
diff --git a/smcc/src/main/java/at/gv/egiz/smcc/reader/PinpadCardReader.java b/smcc/src/main/java/at/gv/egiz/smcc/reader/PinpadCardReader.java
index c2537af8..3584af53 100644
--- a/smcc/src/main/java/at/gv/egiz/smcc/reader/PinpadCardReader.java
+++ b/smcc/src/main/java/at/gv/egiz/smcc/reader/PinpadCardReader.java
@@ -26,8 +26,8 @@ import javax.smartcardio.CardException;
import javax.smartcardio.CardTerminal;
import javax.smartcardio.ResponseAPDU;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import at.gv.egiz.smcc.CancelledException;
import at.gv.egiz.smcc.ChangeReferenceDataAPDUSpec;
@@ -35,7 +35,7 @@ import at.gv.egiz.smcc.NewReferenceDataAPDUSpec;
import at.gv.egiz.smcc.PINConfirmationException;
import at.gv.egiz.smcc.PINFormatException;
import at.gv.egiz.smcc.PINOperationAbortedException;
-import at.gv.egiz.smcc.PINSpec;
+import at.gv.egiz.smcc.PinInfo;
import at.gv.egiz.smcc.ResetRetryCounterAPDUSpec;
import at.gv.egiz.smcc.SignatureCardException;
import at.gv.egiz.smcc.TimeoutException;
@@ -52,13 +52,13 @@ public class PinpadCardReader extends DefaultCardReader {
public static final int PIN_ENTRY_POLLING_INTERVAL = 10;
- protected final static Log log = LogFactory.getLog(PinpadCardReader.class);
+ private final Logger log = LoggerFactory.getLogger(PinpadCardReader.class);
protected byte bEntryValidationCondition = 0x02; // validation key pressed
protected byte bTimeOut = 0x3c; // 60sec (= max on ReinerSCT)
protected byte bTimeOut2 = 0x00; // default (attention with SCM)
- protected byte wPINMaxExtraDigitH = 0x00; // min pin length zero digits
- protected byte wPINMaxExtraDigitL = 0x0c; // max pin length 12 digits
+ protected byte wPINMaxExtraDigitMin = 0x00; // min pin length zero digits
+ protected byte wPINMaxExtraDigitMax = 0x0c; // max pin length 12 digits
/**
* supported features and respective control codes
@@ -99,21 +99,21 @@ public class PinpadCardReader extends DefaultCardReader {
//Snow Leopard: Reiner-SCT cyberJack pinpad(a) 00 00
//display: REINER SCT CyberJack 00 00
if(name.startsWith("gemplus gempc pinpad") || name.startsWith("gemalto gempc pinpad")) {
- log.debug("setting custom wPINMaxExtraDigitH (0x04) for " + name);
- wPINMaxExtraDigitH = 0x04;
- log.debug("setting custom wPINMaxExtraDigitL (0x08) for " + name);
- wPINMaxExtraDigitL = 0x08;
+ log.trace("Setting custom wPINMaxExtraDigitH (0x04) for {}.", name);
+ wPINMaxExtraDigitMin = 0x04;
+ log.trace("Setting custom wPINMaxExtraDigitL (0x08) for {}.", name);
+ wPINMaxExtraDigitMax = 0x08;
} else if (name.startsWith("omnikey cardman 3621")) {
- log.debug("setting custom wPINMaxExtraDigitH (0x01) for " + name);
- wPINMaxExtraDigitH = 0x01;
+ log.trace("Setting custom wPINMaxExtraDigitH (0x01) for {}.", name);
+ wPINMaxExtraDigitMin = 0x01;
} else if (name.startsWith("scm spr 532") || name.startsWith("scm microsystems inc. sprx32 usb smart card reader")) {
- log.debug("setting custom bTimeOut (0x3c) for " + name);
+ log.trace("Setting custom bTimeOut (0x3c) for {}.", name);
bTimeOut = 0x3c;
- log.debug("setting custom bTimeOut2 (0x0f) for " + name);
+ log.trace("Setting custom bTimeOut2 (0x0f) for {}.", name);
bTimeOut2 = 0x0f;
} else if (name.startsWith("cherry smartboard xx44")) {
- log.debug("setting custom wPINMaxExtraDigitH (0x01) for " + name);
- wPINMaxExtraDigitH = 0x01;
+ log.trace("Setting custom wPINMaxExtraDigitH (0x01) for {}.", name);
+ wPINMaxExtraDigitMin = 0x01;
}
}
@@ -127,17 +127,17 @@ public class PinpadCardReader extends DefaultCardReader {
private void VERIFY_PIN_START(Card icc, byte[] PIN_VERIFY) throws CardException {
int ioctl = features.get(FEATURE_VERIFY_PIN_START);
if (log.isTraceEnabled()) {
- log.trace("VERIFY_PIN_START (" + Integer.toHexString(ioctl) +
- ") " + SMCCHelper.toString(PIN_VERIFY));
+ log.trace("VERIFY_PIN_START ({}) {}", Integer.toHexString(ioctl),
+ SMCCHelper.toString(PIN_VERIFY));
}
byte[] resp = icc.transmitControlCommand(ioctl, PIN_VERIFY);
if (resp != null && resp.length > 0) {
if (resp[0] == (byte) 0x57) {
- log.error("Invalid parameter in PIN_VERIFY structure");
+ log.error("Invalid parameter in PIN_VERIFY structure.");
throw new CardException("ERROR_INVALID_PARAMETER");
} else {
- log.error("unexpected response to VERIFY_PIN_START: " +
- SMCCHelper.toString(resp));
+ log.error("Unexpected response to VERIFY_PIN_START: {}.", SMCCHelper
+ .toString(resp));
throw new CardException("unexpected response to VERIFY_PIN_START: " +
SMCCHelper.toString(resp));
}
@@ -153,7 +153,7 @@ public class PinpadCardReader extends DefaultCardReader {
// }
return resp[0];
}
- log.error("unexpected response to GET_KEY_PRESSED: " +
+ log.error("Unexpected response to GET_KEY_PRESSED: {}.",
SMCCHelper.toString(resp));
throw new CardException("unexpected response to GET_KEY_PRESSED: " +
SMCCHelper.toString(resp));
@@ -162,16 +162,16 @@ public class PinpadCardReader extends DefaultCardReader {
private byte[] VERIFY_PIN_FINISH(Card icc) throws CardException {
int ioctl = features.get(FEATURE_VERIFY_PIN_FINISH);
if (log.isTraceEnabled()) {
- log.trace("VERIFY_PIN_FINISH (" + Integer.toHexString(ioctl) + ")");
+ log.trace("VERIFY_PIN_FINISH ({})", Integer.toHexString(ioctl));
}
byte[] resp = icc.transmitControlCommand(ioctl, new byte[0]);
if (resp != null && resp.length == 2) {
if (log.isTraceEnabled()) {
- log.trace("response " + SMCCHelper.toString(resp));
+ log.trace("response {}", SMCCHelper.toString(resp));
}
return resp;
}
- log.error("unexpected response to VERIFY_PIN_FINISH: " +
+ log.error("Unexpected response to VERIFY_PIN_FINISH: {}.",
SMCCHelper.toString(resp));
throw new CardException("unexpected response to VERIFY_PIN_FINISH: " +
SMCCHelper.toString(resp));
@@ -186,10 +186,10 @@ public class PinpadCardReader extends DefaultCardReader {
byte[] resp = icc.transmitControlCommand(ioctl, PIN_MODIFY);
if (resp != null && resp.length > 0) {
if (resp[0] == (byte) 0x57) {
- log.error("Invalid parameter in PIN_MODIFY structure");
+ log.error("Invalid parameter in PIN_MODIFY structure.");
throw new CardException("ERROR_INVALID_PARAMETER");
} else {
- log.error("unexpected response to MODIFY_PIN_START: " +
+ log.error("Unexpected response to MODIFY_PIN_START: {}.",
SMCCHelper.toString(resp));
throw new CardException("unexpected response to MODIFY_PIN_START: " +
SMCCHelper.toString(resp));
@@ -200,16 +200,16 @@ public class PinpadCardReader extends DefaultCardReader {
private byte[] MODIFY_PIN_FINISH(Card icc) throws CardException {
int ioctl = features.get(FEATURE_MODIFY_PIN_FINISH);
if (log.isTraceEnabled()) {
- log.trace("MODIFY_PIN_FINISH (" + Integer.toHexString(ioctl) + ")");
+ log.trace("MODIFY_PIN_FINISH ({})", Integer.toHexString(ioctl));
}
byte[] resp = icc.transmitControlCommand(ioctl, new byte[0]);
if (resp != null && resp.length == 2) {
if (log.isTraceEnabled()) {
- log.trace("response " + SMCCHelper.toString(resp));
+ log.trace("response {}", SMCCHelper.toString(resp));
}
return resp;
}
- log.error("unexpected response to MODIFY_PIN_FINISH: " +
+ log.error("Unexpected response to MODIFY_PIN_FINISH: {}",
SMCCHelper.toString(resp));
throw new CardException("unexpected response to MODIFY_PIN_FINISH: " +
SMCCHelper.toString(resp));
@@ -218,12 +218,12 @@ public class PinpadCardReader extends DefaultCardReader {
private byte[] VERIFY_PIN_DIRECT(Card icc, byte[] PIN_VERIFY) throws CardException {
int ioctl = features.get(FEATURE_VERIFY_PIN_DIRECT);
if (log.isTraceEnabled()) {
- log.trace("VERIFY_PIN_DIRECT (" + Integer.toHexString(ioctl) +
- ") " + SMCCHelper.toString(PIN_VERIFY));
+ log.trace("VERIFY_PIN_DIRECT ({}) {}", Integer.toHexString(ioctl),
+ SMCCHelper.toString(PIN_VERIFY));
}
byte[] resp = icc.transmitControlCommand(ioctl, PIN_VERIFY);
if (log.isTraceEnabled()) {
- log.trace("response " + SMCCHelper.toString(resp));
+ log.trace("response {}", SMCCHelper.toString(resp));
}
return resp;
}
@@ -233,7 +233,7 @@ public class PinpadCardReader extends DefaultCardReader {
// pinGUI.enterPIN(pinSpec, retries);
- log.debug("VERIFY_PIN_START [" + FEATURES[FEATURE_VERIFY_PIN_START] + "]");
+ log.debug("VERIFY_PIN_START [{}]", FEATURES[FEATURE_VERIFY_PIN_START]);
VERIFY_PIN_START(icc, PIN_VERIFY);
byte resp;
@@ -248,29 +248,29 @@ public class PinpadCardReader extends DefaultCardReader {
}
}
} else if (resp == (byte) 0x0d) {
- log.debug("GET_KEY_PRESSED: 0x0d (user confirmed)");
+ log.trace("GET_KEY_PRESSED: 0x0d (user confirmed)");
break;
} else if (resp == (byte) 0x2b) {
log.trace("GET_KEY_PRESSED: 0x2b (user entered valid key 0-9)");
pinGUI.validKeyPressed();
} else if (resp == (byte) 0x1b) {
- log.debug("GET_KEY_PRESSED: 0x1b (user cancelled VERIFY_PIN via cancel button)");
+ log.trace("GET_KEY_PRESSED: 0x1b (user cancelled VERIFY_PIN via cancel button)");
break; // returns 0x6401
} else if (resp == (byte) 0x08) {
- log.debug("GET_KEY_PRESSED: 0x08 (user pressed correction/backspace button)");
+ log.trace("GET_KEY_PRESSED: 0x08 (user pressed correction/backspace button)");
pinGUI.correctionButtonPressed();
} else if (resp == (byte) 0x0e) {
- log.debug("GET_KEY_PRESSED: 0x0e (timeout occured)");
+ log.trace("GET_KEY_PRESSED: 0x0e (timeout occured)");
break; // return 0x6400
} else if (resp == (byte) 0x40) {
- log.debug("GET_KEY_PRESSED: 0x40 (PIN_Operation_Aborted)");
+ log.trace("GET_KEY_PRESSED: 0x40 (PIN_Operation_Aborted)");
throw new PINOperationAbortedException("PIN_Operation_Aborted (0x40)");
} else if (resp == (byte) 0x0a) {
- log.debug("GET_KEY_PRESSED: 0x0a (all keys cleared");
+ log.trace("GET_KEY_PRESSED: 0x0a (all keys cleared");
pinGUI.allKeysCleared();
} else {
- log.error("unexpected response to GET_KEY_PRESSED: " +
- Integer.toHexString(resp));
+ log.error("Unexpected response to GET_KEY_PRESSED: {}.", Integer
+ .toHexString(resp));
throw new CardException("unexpected response to GET_KEY_PRESSED: " +
Integer.toHexString(resp));
}
@@ -283,7 +283,7 @@ public class PinpadCardReader extends DefaultCardReader {
* does not display the first pin dialog (enterCurrentPIN or enterNewPIN, depends on bConfirmPIN),
* since this is easier to do in calling modify()
*/
- private byte[] modifyPin(Card icc, byte[] PIN_MODIFY, ModifyPINGUI pinGUI, PINSpec pINSpec)
+ private byte[] modifyPin(Card icc, byte[] PIN_MODIFY, ModifyPINGUI pinGUI, PinInfo pINSpec)
throws PINOperationAbortedException, CardException {
byte pinConfirmations = (byte) 0x00; //b0: new pin not entered (0) / entered (1)
@@ -298,7 +298,7 @@ public class PinpadCardReader extends DefaultCardReader {
// pinGUI.enterCurrentPIN(pINSpec, retries);
// }
- log.debug("MODIFY_PIN_START [" + FEATURES[FEATURE_MODIFY_PIN_START] + "]");
+ log.debug("MODIFY_PIN_START [{}]", FEATURES[FEATURE_MODIFY_PIN_START]);
MODIFY_PIN_START(icc, PIN_MODIFY);
byte resp;
@@ -309,13 +309,13 @@ public class PinpadCardReader extends DefaultCardReader {
try {
wait(PIN_ENTRY_POLLING_INTERVAL);
} catch (InterruptedException ex) {
- log.error("interrupted in MODIFY_PIN");
+ log.error("Interrupted in MODIFY_PIN");
}
}
} else if (resp == (byte) 0x0d) {
if (log.isTraceEnabled()) {
- log.trace("requested pin confirmations: 0b" + Integer.toBinaryString(bConfirmPIN & 0xff));
- log.trace("performed pin confirmations: 0b" + Integer.toBinaryString(pinConfirmations & 0xff));
+ log.trace("requested pin confirmations: 0b{}", Integer.toBinaryString(bConfirmPIN & 0xff));
+ log.trace("performed pin confirmations: 0b{}", Integer.toBinaryString(pinConfirmations & 0xff));
}
log.debug("GET_KEY_PRESSED: 0x0d (user confirmed)");
if (pinConfirmations == bConfirmPIN) {
@@ -337,23 +337,23 @@ public class PinpadCardReader extends DefaultCardReader {
log.trace("GET_KEY_PRESSED: 0x2b (user entered valid key 0-9)");
pinGUI.validKeyPressed();
} else if (resp == (byte) 0x1b) {
- log.debug("GET_KEY_PRESSED: 0x1b (user cancelled VERIFY_PIN via cancel button)");
+ log.trace("GET_KEY_PRESSED: 0x1b (user cancelled VERIFY_PIN via cancel button)");
break; // returns 0x6401
} else if (resp == (byte) 0x08) {
- log.debug("GET_KEY_PRESSED: 0x08 (user pressed correction/backspace button)");
+ log.trace("GET_KEY_PRESSED: 0x08 (user pressed correction/backspace button)");
pinGUI.correctionButtonPressed();
} else if (resp == (byte) 0x0e) {
- log.debug("GET_KEY_PRESSED: 0x0e (timeout occured)");
+ log.trace("GET_KEY_PRESSED: 0x0e (timeout occured)");
break; // return 0x6400
} else if (resp == (byte) 0x40) {
- log.debug("GET_KEY_PRESSED: 0x40 (PIN_Operation_Aborted)");
+ log.trace("GET_KEY_PRESSED: 0x40 (PIN_Operation_Aborted)");
throw new PINOperationAbortedException("PIN_Operation_Aborted (0x40)");
} else if (resp == (byte) 0x0a) {
- log.debug("GET_KEY_PRESSED: 0x0a (all keys cleared");
+ log.trace("GET_KEY_PRESSED: 0x0a (all keys cleared");
pinGUI.allKeysCleared();
} else {
- log.error("unexpected response to GET_KEY_PRESSED: " +
- Integer.toHexString(resp));
+ log.error("Unexpected response to GET_KEY_PRESSED: {}.", Integer
+ .toHexString(resp));
throw new CardException("unexpected response to GET_KEY_PRESSED: " +
Integer.toHexString(resp));
}
@@ -367,17 +367,17 @@ public class PinpadCardReader extends DefaultCardReader {
private byte[] MODIFY_PIN_DIRECT(Card icc, byte[] PIN_MODIFY) throws CardException {
int ioctl = features.get(FEATURE_MODIFY_PIN_DIRECT);
if (log.isTraceEnabled()) {
- log.trace("MODIFY_PIN_DIRECT (" + Integer.toHexString(ioctl) +
- ") " + SMCCHelper.toString(PIN_MODIFY));
+ log.trace("MODIFY_PIN_DIRECT ({}) {}", Integer.toHexString(ioctl),
+ SMCCHelper.toString(PIN_MODIFY));
}
byte[] resp = icc.transmitControlCommand(ioctl, PIN_MODIFY);
if (log.isTraceEnabled()) {
- log.trace("response " + SMCCHelper.toString(resp));
+ log.trace("response {}", SMCCHelper.toString(resp));
}
return resp;
}
- protected byte[] createPINModifyStructure(NewReferenceDataAPDUSpec apduSpec, PINSpec pinSpec) {
+ protected byte[] createPINModifyStructure(NewReferenceDataAPDUSpec apduSpec, PinInfo pinSpec) {
ByteArrayOutputStream s = new ByteArrayOutputStream();
// bTimeOut
@@ -399,16 +399,17 @@ public class PinpadCardReader extends DefaultCardReader {
s.write(0x00);
// bInsertionOffsetNew
s.write(apduSpec.getPinInsertionOffsetNew());
- // wPINMaxExtraDigit
- s.write(Math.min(pinSpec.getMaxLength(), wPINMaxExtraDigitL));
- s.write(Math.max(pinSpec.getMinLength(), wPINMaxExtraDigitH));
+ // wPINMaxExtraDigit (little endian)
+ s.write(Math.min(pinSpec.getMaxLength(), wPINMaxExtraDigitMax));
+ s.write(Math.max(pinSpec.getMinLength(), wPINMaxExtraDigitMin));
// bConfirmPIN
s.write(0x01);
// bEntryValidationCondition
s.write(bEntryValidationCondition);
// bNumberMessage
s.write(0x02);
- // wLangId English (United States), see http://www.usb.org/developers/docs/USB_LANGIDs.pdf
+ // wLangId (little endian)
+ // English (United States), see http://www.usb.org/developers/docs/USB_LANGIDs.pdf
s.write(0x09);
s.write(0x04);
// bMsgIndex1
@@ -440,7 +441,7 @@ public class PinpadCardReader extends DefaultCardReader {
}
- protected byte[] createPINModifyStructure(ChangeReferenceDataAPDUSpec apduSpec, PINSpec pinSpec) {
+ protected byte[] createPINModifyStructure(ChangeReferenceDataAPDUSpec apduSpec, PinInfo pinSpec) {
//TODO bInsertionOffsetOld (0x00), bConfirmPIN (0x01), bNumberMessage (0x02), bMsgIndex1/2/3
ByteArrayOutputStream s = new ByteArrayOutputStream();
@@ -464,8 +465,8 @@ public class PinpadCardReader extends DefaultCardReader {
// bInsertionOffsetNew
s.write(apduSpec.getPinInsertionOffsetNew());
// wPINMaxExtraDigit
- s.write(Math.min(pinSpec.getMaxLength(), wPINMaxExtraDigitL));
- s.write(Math.max(pinSpec.getMinLength(), wPINMaxExtraDigitH));
+ s.write(Math.min(pinSpec.getMaxLength(), wPINMaxExtraDigitMax));
+ s.write(Math.max(pinSpec.getMinLength(), wPINMaxExtraDigitMin));
// bConfirmPIN
s.write(0x03);
// bEntryValidationCondition
@@ -504,7 +505,7 @@ public class PinpadCardReader extends DefaultCardReader {
}
- protected byte[] createPINVerifyStructure(VerifyAPDUSpec apduSpec, PINSpec pinSpec) {
+ protected byte[] createPINVerifyStructure(VerifyAPDUSpec apduSpec, PinInfo pinSpec) {
ByteArrayOutputStream s = new ByteArrayOutputStream();
// bTimeOut
@@ -522,14 +523,14 @@ public class PinpadCardReader extends DefaultCardReader {
// bmPINLengthFormat
s.write(// system unit = bit
(0xF & apduSpec.getPinLengthPos()));
- // wPINMaxExtraDigit
- s.write(Math.min(pinSpec.getMaxLength(), wPINMaxExtraDigitL)); // max PIN length
- s.write(Math.max(pinSpec.getMinLength(), wPINMaxExtraDigitH)); // min PIN length
+ // wPINMaxExtraDigit (little endian)
+ s.write(Math.min(pinSpec.getMaxLength(), wPINMaxExtraDigitMax)); // max PIN length
+ s.write(Math.max(pinSpec.getMinLength(), wPINMaxExtraDigitMin)); // min PIN length
// bEntryValidationCondition
s.write(bEntryValidationCondition);
// bNumberMessage
s.write(0x01);
- // wLangId
+ // wLangId (little endian)
s.write(0x09);
s.write(0x04);
// bMsgIndex
@@ -558,7 +559,7 @@ public class PinpadCardReader extends DefaultCardReader {
@Override
public ResponseAPDU verify(CardChannel channel, VerifyAPDUSpec apduSpec,
- PINGUI pinGUI, PINSpec pinSpec, int retries)
+ PINGUI pinGUI, PinInfo pinSpec, int retries)
throws SignatureCardException, CardException, InterruptedException {
ResponseAPDU resp = null;
@@ -571,10 +572,10 @@ public class PinpadCardReader extends DefaultCardReader {
resp = new ResponseAPDU(verifyPin(icc, s, pinGUI));
} else if (VERIFY_DIRECT) {
pinGUI.enterPINDirect(pinSpec, retries);
- log.debug("VERIFY_PIN_DIRECT [" + FEATURES[FEATURE_VERIFY_PIN_DIRECT] + "]");
+ log.debug("VERIFY_PIN_DIRECT [{}]", FEATURES[FEATURE_VERIFY_PIN_DIRECT]);
resp = new ResponseAPDU(VERIFY_PIN_DIRECT(icc, s));
} else {
- log.warn("falling back to default pin-entry");
+ log.warn("Falling back to default pin-entry.");
return super.verify(channel, apduSpec, pinGUI, pinSpec, retries);
}
@@ -586,9 +587,9 @@ public class PinpadCardReader extends DefaultCardReader {
log.debug("SPE operation was cancelled by the 'Cancel' button.");
throw new CancelledException();
case 0x6403:
- log.debug("User entered too short or too long PIN "
- + "regarding MIN/MAX PIN length.");
- throw new PINFormatException();
+ log.debug("User entered too short or too long PIN "
+ + "regarding MIN/MAX PIN length.");
+ throw new PINFormatException();
case 0x6480:
log.debug("SPE operation was aborted by the 'Cancel' operation "
+ "at the host system.");
@@ -601,7 +602,7 @@ public class PinpadCardReader extends DefaultCardReader {
@Override
public ResponseAPDU modify(CardChannel channel, ChangeReferenceDataAPDUSpec apduSpec,
- ModifyPINGUI pinGUI, PINSpec pinSpec, int retries)
+ ModifyPINGUI pinGUI, PinInfo pinSpec, int retries)
throws SignatureCardException, CardException, InterruptedException {
ResponseAPDU resp = null;
@@ -614,10 +615,10 @@ public class PinpadCardReader extends DefaultCardReader {
resp = new ResponseAPDU(modifyPin(icc, s, pinGUI, pinSpec));
} else if (MODIFY_DIRECT) {
pinGUI.modifyPINDirect(pinSpec, retries);
- log.debug("MODIFY_PIN_DIRECT [" + FEATURES[FEATURE_MODIFY_PIN_DIRECT] + "]");
+ log.debug("MODIFY_PIN_DIRECT [{}]", FEATURES[FEATURE_MODIFY_PIN_DIRECT]);
resp = new ResponseAPDU(MODIFY_PIN_DIRECT(icc, s));
} else {
- log.warn("falling back to default pin-entry");
+ log.warn("Falling back to default pin-entry.");
return super.modify(channel, apduSpec, pinGUI, pinSpec, retries);
}
@@ -648,7 +649,7 @@ public class PinpadCardReader extends DefaultCardReader {
@Override
public ResponseAPDU modify(CardChannel channel, NewReferenceDataAPDUSpec apduSpec,
- ModifyPINGUI pinGUI, PINSpec pinSpec)
+ ModifyPINGUI pinGUI, PinInfo pinSpec)
throws SignatureCardException, CardException, InterruptedException {
ResponseAPDU resp = null;
@@ -661,10 +662,10 @@ public class PinpadCardReader extends DefaultCardReader {
resp = new ResponseAPDU(modifyPin(icc, s, pinGUI, pinSpec));
} else if (MODIFY_DIRECT) {
pinGUI.modifyPINDirect(pinSpec, -1);
- log.debug("MODIFY_PIN_DIRECT [" + FEATURES[FEATURE_MODIFY_PIN_DIRECT] + "]");
+ log.debug("MODIFY_PIN_DIRECT [{}]", FEATURES[FEATURE_MODIFY_PIN_DIRECT]);
resp = new ResponseAPDU(MODIFY_PIN_DIRECT(icc, s));
} else {
- log.warn("falling back to default pin-entry");
+ log.warn("Falling back to default pin-entry.");
return super.modify(channel, apduSpec, pinGUI, pinSpec);
}
@@ -695,7 +696,7 @@ public class PinpadCardReader extends DefaultCardReader {
@Override
public ResponseAPDU modify(CardChannel channel, ResetRetryCounterAPDUSpec apduSpec,
- ModifyPINGUI pinGUI, PINSpec pinSpec, int retries)
+ ModifyPINGUI pinGUI, PinInfo pinSpec, int retries)
throws InterruptedException, CardException, SignatureCardException {
//TODO
return modify(channel, (ChangeReferenceDataAPDUSpec) apduSpec, pinGUI, pinSpec, retries);
diff --git a/smcc/src/main/java/at/gv/egiz/smcc/reader/ReaderFactory.java b/smcc/src/main/java/at/gv/egiz/smcc/reader/ReaderFactory.java
index bf1730e9..0d0a8d8a 100644
--- a/smcc/src/main/java/at/gv/egiz/smcc/reader/ReaderFactory.java
+++ b/smcc/src/main/java/at/gv/egiz/smcc/reader/ReaderFactory.java
@@ -25,8 +25,8 @@ import java.util.Map;
import javax.smartcardio.Card;
import javax.smartcardio.CardException;
import javax.smartcardio.CardTerminal;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
*
@@ -34,7 +34,7 @@ import org.apache.commons.logging.LogFactory;
*/
public class ReaderFactory {
- protected final static Log log = LogFactory.getLog(ReaderFactory.class);
+ private final Logger log = LoggerFactory.getLogger(ReaderFactory.class);
protected static SMCCConfiguration configuration;
@@ -50,8 +50,9 @@ public class ReaderFactory {
public static CardReader getReader(Card icc, CardTerminal ct) {
+ Logger log = LoggerFactory.getLogger(ReaderFactory.class);
String name = ct.getName();
- log.info("creating reader " + name);
+ log.info("Creating reader : {}.", name);
Map<Byte, Integer> features;
if (configuration != null && configuration.isDisablePinpad()) {
@@ -70,33 +71,31 @@ public class ReaderFactory {
return reader;
}
- private static int CTL_CODE(int code) {
+ private static int SCARD_CTL_CODE(int code) {
String os_name = System.getProperty("os.name").toLowerCase();
if (os_name.indexOf("windows") > -1) {
- // cf. WinIOCTL.h
return (0x31 << 16 | (code) << 2);
}
- // cf. reader.h
return 0x42000000 + (code);
}
- static int IOCTL_GET_FEATURE_REQUEST = CTL_CODE(3400);
+ static int IOCTL_GET_FEATURE_REQUEST = SCARD_CTL_CODE(3400);
private static Map<Byte, Integer> queryFeatures(Card icc) {
+ Logger log = LoggerFactory.getLogger(ReaderFactory.class);
Map<Byte, Integer> features = new HashMap<Byte, Integer>();
-
if (icc == null) {
- log.warn("invalid card handle, cannot query ifd features");
+ log.warn("Invalid card handle, cannot query ifd features.");
} else {
try {
if (log.isTraceEnabled()) {
- log.trace("GET_FEATURE_REQUEST " + Integer.toHexString(IOCTL_GET_FEATURE_REQUEST));
+ log.trace("GET_FEATURE_REQUEST {}", Integer.toHexString(IOCTL_GET_FEATURE_REQUEST));
}
byte[] resp = icc.transmitControlCommand(IOCTL_GET_FEATURE_REQUEST,
new byte[0]);
if (log.isTraceEnabled()) {
- log.trace("Response TLV " + SMCCHelper.toString(resp));
+ log.trace("Response TLV {}", SMCCHelper.toString(resp));
}
// tag
// length in bytes (always 4)
@@ -108,15 +107,14 @@ public class ReaderFactory {
((0xff & resp[i + 4]) << 8) |
(0xff & resp[i + 5]);
if (log.isInfoEnabled()) {
- log.info("IFD supports " + CardReader.FEATURES[feature.intValue()] +
- ": " + Integer.toHexString(ioctl.intValue()));
+ log.info("IFD supports {}: {}", CardReader.FEATURES[feature
+ .intValue()], Integer.toHexString(ioctl.intValue()));
}
features.put(feature, ioctl);
}
} catch (CardException ex) {
- log.debug("Failed to query IFD features: " + ex.getMessage());
- log.trace(ex);
- log.info("IFD does not support secure pin entry");
+ log.debug("Failed to query IFD features: {}", ex.getMessage(), ex);
+ log.info("IFD does not support secure pin entry.");
}
}
return features;
diff --git a/smcc/src/main/java/at/gv/egiz/smcc/util/ISO7816Utils.java b/smcc/src/main/java/at/gv/egiz/smcc/util/ISO7816Utils.java
index fcd0b876..05249a5e 100644
--- a/smcc/src/main/java/at/gv/egiz/smcc/util/ISO7816Utils.java
+++ b/smcc/src/main/java/at/gv/egiz/smcc/util/ISO7816Utils.java
@@ -286,12 +286,18 @@ public class ISO7816Utils {
public static CommandAPDU createVerifyAPDU(VerifyAPDUSpec apduSpec, char[] pin) {
// format pin
- byte[] fpin = new byte[apduSpec.getPinLength()];
- byte[] mask = new byte[apduSpec.getPinLength()];
+ int l = (apduSpec.getPinLength() > 0) ? apduSpec.getPinLength() : pin.length;
+ byte[] fpin = new byte[l];
+ byte[] mask = new byte[l];
formatPIN(apduSpec.getPinFormat(), apduSpec.getPinJustification(), fpin, mask, pin);
- byte[] apdu = apduSpec.getApdu();
-
+ byte[] template = apduSpec.getApdu();
+ byte[] apdu = new byte[Math.max(template.length, 5 + apduSpec.getPinPosition() + l)];
+ System.arraycopy(template, 0, apdu, 0, template.length);
+ if (template.length < 5) {
+ apdu[4] = (byte) (apdu.length - 5);
+ }
+
// insert formated pin
insertPIN(apdu, apduSpec.getPinPosition() + 5, fpin, mask);
@@ -307,13 +313,24 @@ public class ISO7816Utils {
public static CommandAPDU createChangeReferenceDataAPDU(
ChangeReferenceDataAPDUSpec apduSpec, char[] oldPin, char[] newPin) {
+ int lo = (apduSpec.getPinLength() > 0) ? apduSpec.getPinLength() : oldPin.length;
+ int ln = (apduSpec.getPinLength() > 0) ? apduSpec.getPinLength() : newPin.length;
+
// format old pin
- byte[] fpin = new byte[apduSpec.getPinLength()];
- byte[] mask = new byte[apduSpec.getPinLength()];
+ byte[] fpin = new byte[lo];
+ byte[] mask = new byte[lo];
formatPIN(apduSpec.getPinFormat(), apduSpec.getPinJustification(), fpin, mask, oldPin);
- byte[] apdu = apduSpec.getApdu();
-
+ byte[] template = apduSpec.getApdu();
+ byte[] apdu = new byte[Math.max(template.length,
+ 5 + apduSpec.getPinPosition()
+ + Math.max(apduSpec.getPinInsertionOffsetOld() + lo,
+ apduSpec.getPinInsertionOffsetNew() + ln))];
+ System.arraycopy(template, 0, apdu, 0, template.length);
+ if (template.length < 5) {
+ apdu[4] = (byte) (apdu.length - 5);
+ }
+
// insert formated old pin
insertPIN(apdu, apduSpec.getPinPosition() + apduSpec.getPinInsertionOffsetOld() + 5, fpin, mask);
@@ -324,8 +341,8 @@ public class ISO7816Utils {
}
// format new pin
- fpin = new byte[apduSpec.getPinLength()];
- mask = new byte[apduSpec.getPinLength()];
+ fpin = new byte[ln];
+ mask = new byte[ln];
formatPIN(apduSpec.getPinFormat(), apduSpec.getPinJustification(), fpin, mask, newPin);
// insert formated new pin
@@ -345,12 +362,18 @@ public class ISO7816Utils {
NewReferenceDataAPDUSpec apduSpec, char[] newPin) {
// format old pin
- byte[] fpin = new byte[apduSpec.getPinLength()];
- byte[] mask = new byte[apduSpec.getPinLength()];
+ int l = (apduSpec.getPinLength() > 0) ? apduSpec.getPinLength() : newPin.length;
+ byte[] fpin = new byte[l];
+ byte[] mask = new byte[l];
formatPIN(apduSpec.getPinFormat(), apduSpec.getPinJustification(), fpin, mask, newPin);
- byte[] apdu = apduSpec.getApdu();
-
+ byte[] template = apduSpec.getApdu();
+ byte[] apdu = new byte[Math.max(template.length, 5 + apduSpec.getPinPosition() + l)];
+ System.arraycopy(template, 0, apdu, 0, template.length);
+ if (template.length < 5) {
+ apdu[4] = (byte) (apdu.length - 5);
+ }
+
// insert formated new pin
insertPIN(apdu, apduSpec.getPinPosition() + apduSpec.getPinInsertionOffsetNew() + 5, fpin, mask);
diff --git a/smcc/src/main/java/at/gv/egiz/smcc/util/SMCCHelper.java b/smcc/src/main/java/at/gv/egiz/smcc/util/SMCCHelper.java
index f7d3bab7..a06fb624 100644
--- a/smcc/src/main/java/at/gv/egiz/smcc/util/SMCCHelper.java
+++ b/smcc/src/main/java/at/gv/egiz/smcc/util/SMCCHelper.java
@@ -14,137 +14,137 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package at.gv.egiz.smcc.util;
-
-import java.util.Locale;
-import java.util.Map;
-
-import javax.smartcardio.ATR;
-import javax.smartcardio.Card;
-import javax.smartcardio.CardTerminal;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import at.gv.egiz.smcc.CardNotSupportedException;
-import at.gv.egiz.smcc.SignatureCard;
-import at.gv.egiz.smcc.SignatureCardFactory;
-
-public class SMCCHelper {
-
- public final static int NO_CARD = 0;
- public final static int PC_SC_NOT_SUPPORTED = 1;
- public final static int TERMINAL_NOT_PRESENT = 2;
- public final static int CARD_NOT_SUPPORTED = 3;
- public final static int CARD_FOUND = 4;
-
- private final static Log log = LogFactory.getLog(SMCCHelper.class);
-
- protected SmartCardIO smartCardIO = new SmartCardIO();
- protected int resultCode = NO_CARD;
- protected SignatureCard signatureCard = null;
- protected static boolean useSWCard = false;
-
- public SMCCHelper() {
- update();
- }
-
- public synchronized void update() {
- update(-1);
- }
-
- public synchronized void update(int sleep) {
- SignatureCardFactory factory = SignatureCardFactory.getInstance();
- if (useSWCard) {
- try {
- signatureCard = factory.createSignatureCard(null, null);
- resultCode = CARD_FOUND;
- } catch (CardNotSupportedException e) {
- resultCode = CARD_NOT_SUPPORTED;
- signatureCard = null;
- }
- return;
- }
- signatureCard = null;
- resultCode = NO_CARD;
- // find pcsc support
- if (smartCardIO.isPCSCSupported()) {
- // find supported card
- if (smartCardIO.isTerminalPresent()) {
- Map<CardTerminal, Card> newCards = null;
- if (sleep > 0) {
- smartCardIO.waitForInserted(sleep);
-
- }
- newCards = smartCardIO.getCards();
- for (CardTerminal cardTerminal : newCards.keySet()) {
- try {
- Card c = newCards.get(cardTerminal);
- if (c == null) {
- throw new CardNotSupportedException();
- }
- signatureCard = factory.createSignatureCard(c, cardTerminal);
- ATR atr = newCards.get(cardTerminal).getATR();
- log.trace("Found supported card (" + signatureCard.toString() + ") "
- + "in terminal '" + cardTerminal.getName() + "', ATR = "
- + toString(atr.getBytes()) + ".");
- resultCode = CARD_FOUND;
- break;
-
- } catch (CardNotSupportedException e) {
- Card c = newCards.get(cardTerminal);
- if (c != null) {
- ATR atr = c.getATR();
- log.info("Found unsupported card" + " in terminal '"
- + cardTerminal.getName() + "', ATR = "
- + toString(atr.getBytes()) + ".");
- } else {
- log.info("Found unsupported card in terminal '"
- + cardTerminal.getName() + "' without ATR");
- }
- resultCode = CARD_NOT_SUPPORTED;
- }
- }
- } else {
- resultCode = TERMINAL_NOT_PRESENT;
- }
- } else {
- resultCode = PC_SC_NOT_SUPPORTED;
- }
- }
-
- public synchronized SignatureCard getSignatureCard(Locale locale) {
- if (signatureCard != null) {
- signatureCard.setLocale(locale);
- }
- return signatureCard;
- }
-
- public int getResultCode() {
- return resultCode;
- }
-
- public static String toString(byte[] b) {
- StringBuffer sb = new StringBuffer();
- sb.append('[');
- if (b != null && b.length > 0) {
- sb.append(Integer.toHexString((b[0] & 240) >> 4));
- sb.append(Integer.toHexString(b[0] & 15));
- for (int i = 1; i < b.length; i++) {
- sb.append((i % 32 == 0) ? '\n' : ':');
- sb.append(Integer.toHexString((b[i] & 240) >> 4));
- sb.append(Integer.toHexString(b[i] & 15));
- }
- }
- sb.append(']');
- return sb.toString();
- }
-
- public static boolean isUseSWCard() {
- return useSWCard;
- }
-
- public static void setUseSWCard(boolean useSWCard) {
- SMCCHelper.useSWCard = useSWCard;
- }
-}
+package at.gv.egiz.smcc.util;
+
+import java.util.Locale;
+import java.util.Map;
+
+import javax.smartcardio.Card;
+import javax.smartcardio.CardTerminal;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import at.gv.egiz.smcc.CardNotSupportedException;
+import at.gv.egiz.smcc.SignatureCard;
+import at.gv.egiz.smcc.SignatureCardFactory;
+
+public class SMCCHelper {
+
+ public final static int NO_CARD = 0;
+ public final static int PC_SC_NOT_SUPPORTED = 1;
+ public final static int TERMINAL_NOT_PRESENT = 2;
+ public final static int CARD_NOT_SUPPORTED = 3;
+ public final static int CARD_FOUND = 4;
+
+ private final Logger log = LoggerFactory.getLogger(SMCCHelper.class);
+
+ protected SmartCardIO smartCardIO = new SmartCardIO();
+ protected int resultCode = NO_CARD;
+ protected SignatureCard signatureCard = null;
+ protected static boolean useSWCard = false;
+
+ public SMCCHelper() {
+ update();
+ }
+
+ public synchronized void update() {
+ update(-1);
+ }
+
+ public synchronized void update(int sleep) {
+ SignatureCardFactory factory = SignatureCardFactory.getInstance();
+ if (useSWCard) {
+ try {
+ signatureCard = factory.createSignatureCard(null, null);
+ resultCode = CARD_FOUND;
+ } catch (CardNotSupportedException e) {
+ resultCode = CARD_NOT_SUPPORTED;
+ signatureCard = null;
+ }
+ return;
+ }
+ signatureCard = null;
+ resultCode = NO_CARD;
+ // find pcsc support
+ if (smartCardIO.isPCSCSupported()) {
+ // find supported card
+ if (smartCardIO.isTerminalPresent()) {
+ Map<CardTerminal, Card> newCards = null;
+ if (sleep > 0) {
+ smartCardIO.waitForInserted(sleep);
+
+ }
+ newCards = smartCardIO.getCards();
+ for (CardTerminal cardTerminal : newCards.keySet()) {
+ try {
+ Card c = newCards.get(cardTerminal);
+ if (c == null) {
+ throw new CardNotSupportedException();
+ }
+ signatureCard = factory.createSignatureCard(c, cardTerminal);
+ if (log.isTraceEnabled()) {
+ Object[] args = { signatureCard, cardTerminal.getName(),
+ toString(newCards.get(cardTerminal).getATR().getBytes()) };
+ log.trace("Found supported card ({}) in terminal '{}', ATR = {}.", args);
+ }
+ resultCode = CARD_FOUND;
+ break;
+
+ } catch (CardNotSupportedException e) {
+ Card c = newCards.get(cardTerminal);
+ if (c != null) {
+ Object[] args = { cardTerminal.getName(),
+ toString(c.getATR().getBytes()) };
+ log.info("Found unsupported card in terminal '{}', ATR = {}.",
+ args);
+ } else {
+ log.info("Found unsupported card in terminal '{}' without ATR.",
+ cardTerminal.getName());
+ }
+ resultCode = CARD_NOT_SUPPORTED;
+ }
+ }
+ } else {
+ resultCode = TERMINAL_NOT_PRESENT;
+ }
+ } else {
+ resultCode = PC_SC_NOT_SUPPORTED;
+ }
+ }
+
+ public synchronized SignatureCard getSignatureCard(Locale locale) {
+ if (signatureCard != null) {
+ signatureCard.setLocale(locale);
+ }
+ return signatureCard;
+ }
+
+ public int getResultCode() {
+ return resultCode;
+ }
+
+ public static String toString(byte[] b) {
+ StringBuffer sb = new StringBuffer();
+ sb.append('[');
+ if (b != null && b.length > 0) {
+ sb.append(Integer.toHexString((b[0] & 240) >> 4));
+ sb.append(Integer.toHexString(b[0] & 15));
+ for (int i = 1; i < b.length; i++) {
+ sb.append((i % 32 == 0) ? '\n' : ':');
+ sb.append(Integer.toHexString((b[i] & 240) >> 4));
+ sb.append(Integer.toHexString(b[i] & 15));
+ }
+ }
+ sb.append(']');
+ return sb.toString();
+ }
+
+ public static boolean isUseSWCard() {
+ return useSWCard;
+ }
+
+ public static void setUseSWCard(boolean useSWCard) {
+ SMCCHelper.useSWCard = useSWCard;
+ }
+}
diff --git a/smcc/src/main/java/at/gv/egiz/smcc/util/SmartCardIO.java b/smcc/src/main/java/at/gv/egiz/smcc/util/SmartCardIO.java
index b1866894..14ee7549 100644
--- a/smcc/src/main/java/at/gv/egiz/smcc/util/SmartCardIO.java
+++ b/smcc/src/main/java/at/gv/egiz/smcc/util/SmartCardIO.java
@@ -14,191 +14,191 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package at.gv.egiz.smcc.util;
-
+package at.gv.egiz.smcc.util;
+
import java.security.NoSuchAlgorithmException;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.smartcardio.Card;
-import javax.smartcardio.CardException;
-import javax.smartcardio.CardTerminal;
-import javax.smartcardio.CardTerminals;
-import javax.smartcardio.TerminalFactory;
-import javax.smartcardio.CardTerminals.State;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- *
- * @author mcentner
- */
-public class SmartCardIO {
-
- private static final int STATE_INITIALIZED = 1;
-
- private static final int STATE_TERMINAL_FACTORY = 2;
-
- private static final int STATE_TERMINALS = 3;
-
- private static Log log = LogFactory.getLog(SmartCardIO.class);
-
- final Map<CardTerminal, Card> terminalCard_ = new HashMap<CardTerminal, Card>();
-
- int state_ = STATE_INITIALIZED;
-
- TerminalFactory terminalFactory_ = null;
-
- CardTerminals cardTerminals_;
-
- private void updateTerminalFactory() {
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.smartcardio.Card;
+import javax.smartcardio.CardException;
+import javax.smartcardio.CardTerminal;
+import javax.smartcardio.CardTerminals;
+import javax.smartcardio.TerminalFactory;
+import javax.smartcardio.CardTerminals.State;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ * @author mcentner
+ */
+public class SmartCardIO {
+
+ private static final int STATE_INITIALIZED = 1;
+
+ private static final int STATE_TERMINAL_FACTORY = 2;
+
+ private static final int STATE_TERMINALS = 3;
+
+ private final Logger log = LoggerFactory.getLogger(SmartCardIO.class);
+
+ final Map<CardTerminal, Card> terminalCard_ = new HashMap<CardTerminal, Card>();
+
+ int state_ = STATE_INITIALIZED;
+
+ TerminalFactory terminalFactory_ = null;
+
+ CardTerminals cardTerminals_;
+
+ private void updateTerminalFactory() {
TerminalFactory terminalFactory;
try {
terminalFactory = TerminalFactory.getInstance("PC/SC", null);
} catch (NoSuchAlgorithmException e) {
log.info("Failed to get TerminalFactory of type 'PC/SC'.", e);
terminalFactory = TerminalFactory.getDefault();
- }
- log.debug("TerminalFactory : " + terminalFactory);
- if ("PC/SC".equals(terminalFactory.getType())) {
- terminalFactory_ = terminalFactory;
- }
- if(state_ < STATE_TERMINAL_FACTORY) {
- state_ = STATE_TERMINAL_FACTORY;
- }
- }
-
- public boolean isPCSCSupported() {
- if(state_ < STATE_TERMINAL_FACTORY) {
- updateTerminalFactory();
- }
- return terminalFactory_ != null;
- }
-
- private void updateCardTerminals() {
- if(terminalFactory_ != null) {
- cardTerminals_ = terminalFactory_.terminals();
- }
- log.debug("CardTerminals : " + cardTerminals_);
- if (state_ < STATE_TERMINALS) {
- state_ = STATE_TERMINALS;
- }
- }
-
- public CardTerminals getCardTerminals() {
- if(state_ < STATE_TERMINAL_FACTORY) {
- updateTerminalFactory();
- }
- if(state_ < STATE_TERMINALS) {
- updateCardTerminals();
- }
- return cardTerminals_;
- }
-
- public boolean isTerminalPresent() {
- CardTerminals cardTerminals = getCardTerminals();
- if (cardTerminals != null) {
- List<CardTerminal> terminals = null;
- try {
- terminals = cardTerminals.list(State.ALL);
-
- // logging
- if(log.isInfoEnabled()) {
- if (terminals == null || terminals.isEmpty()) {
- log.info("No card terminal found.");
- } else {
- StringBuffer msg = new StringBuffer();
- msg.append("Found " + terminals.size() + " card terminal(s):");
- for (CardTerminal terminal : terminals) {
- msg.append("\n " + terminal.getName());
- }
- log.info(msg.toString());
- }
- }
-
- return terminals != null && !terminals.isEmpty();
- } catch (CardException e) {
- log.info("Failed to list card terminals.", e);
- return false;
- }
- } else {
- return false;
- }
- }
-
- private Map<CardTerminal, Card> updateCards() {
-
- // clear card references if removed
- try {
- log.trace("terminals.list(State.CARD_REMOVAL)");
- for (CardTerminal terminal : cardTerminals_.list(CardTerminals.State.CARD_REMOVAL)) {
- Card card = terminalCard_.remove(terminal);
- log.trace("card removed : " + card);
- }
- } catch (CardException e) {
- log.debug(e);
- }
-
- // check inserted cards
- Map<CardTerminal, Card> newCards = new HashMap<CardTerminal, Card>();
- try {
- log.trace("terminals.list(State.CARD_INSERTION)");
- for (CardTerminal terminal : cardTerminals_.list(CardTerminals.State.CARD_INSERTION)) {
-
- Card card = null;
+ }
+ log.debug("TerminalFactory : {}.", terminalFactory);
+ if ("PC/SC".equals(terminalFactory.getType())) {
+ terminalFactory_ = terminalFactory;
+ }
+ if(state_ < STATE_TERMINAL_FACTORY) {
+ state_ = STATE_TERMINAL_FACTORY;
+ }
+ }
+
+ public boolean isPCSCSupported() {
+ if(state_ < STATE_TERMINAL_FACTORY) {
+ updateTerminalFactory();
+ }
+ return terminalFactory_ != null;
+ }
+
+ private void updateCardTerminals() {
+ if(terminalFactory_ != null) {
+ cardTerminals_ = terminalFactory_.terminals();
+ }
+ log.debug("CardTerminals : {}.", cardTerminals_);
+ if (state_ < STATE_TERMINALS) {
+ state_ = STATE_TERMINALS;
+ }
+ }
+
+ public CardTerminals getCardTerminals() {
+ if(state_ < STATE_TERMINAL_FACTORY) {
+ updateTerminalFactory();
+ }
+ if(state_ < STATE_TERMINALS) {
+ updateCardTerminals();
+ }
+ return cardTerminals_;
+ }
+
+ public boolean isTerminalPresent() {
+ CardTerminals cardTerminals = getCardTerminals();
+ if (cardTerminals != null) {
+ List<CardTerminal> terminals = null;
+ try {
+ terminals = cardTerminals.list(State.ALL);
+
+ // logging
+ if(log.isInfoEnabled()) {
+ if (terminals == null || terminals.isEmpty()) {
+ log.info("No card terminal found.");
+ } else {
+ StringBuffer msg = new StringBuffer();
+ msg.append("Found " + terminals.size() + " card terminal(s):");
+ for (CardTerminal terminal : terminals) {
+ msg.append("\n " + terminal.getName());
+ }
+ log.info(msg.toString());
+ }
+ }
+
+ return terminals != null && !terminals.isEmpty();
+ } catch (CardException e) {
+ log.info("Failed to list card terminals.", e);
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ private Map<CardTerminal, Card> updateCards() {
+
+ // clear card references if removed
+ try {
+ log.trace("terminals.list(State.CARD_REMOVAL)");
+ for (CardTerminal terminal : cardTerminals_.list(CardTerminals.State.CARD_REMOVAL)) {
+ Card card = terminalCard_.remove(terminal);
+ log.trace("card removed : {}", card);
+ }
+ } catch (CardException e) {
+ log.debug("Failed to list terminals.", e);
+ }
+
+ // check inserted cards
+ Map<CardTerminal, Card> newCards = new HashMap<CardTerminal, Card>();
+ try {
+ log.trace("terminals.list(State.CARD_INSERTION)");
+ for (CardTerminal terminal : cardTerminals_.list(CardTerminals.State.CARD_INSERTION)) {
+
+ Card card = null;
try {
log.trace("Trying to connect to card.");
- // try to connect to card
- card = terminal.connect("*");
- } catch (CardException e) {
- log.trace("Failed to connect to card.", e);
- }
-
- // have we seen this card before?
- if (terminalCard_.put(terminal, card) == null) {
- terminalCard_.put(terminal, card);
- newCards.put(terminal, card);
- log.trace("terminal '" + terminal + "' card inserted : " + card);
- }
- }
- } catch (CardException e) {
- log.debug(e);
- }
- return newCards;
-
- }
-
- public Map<CardTerminal, Card> getCards() {
- if(state_ < STATE_TERMINAL_FACTORY) {
- updateTerminalFactory();
- }
- if(state_ < STATE_TERMINALS) {
- updateCardTerminals();
- }
- updateCards();
- Map<CardTerminal, Card> terminalCard = new HashMap<CardTerminal, Card>();
- terminalCard.putAll(terminalCard_);
- return Collections.unmodifiableMap(terminalCard);
- }
-
- public Map<CardTerminal, Card> waitForInserted(int timeout) {
- if(state_ < STATE_TERMINAL_FACTORY) {
- updateTerminalFactory();
- }
- if(state_ < STATE_TERMINALS) {
- updateCardTerminals();
- }
- try {
- // just waiting for a short period of time to allow for abort
- cardTerminals_.waitForChange(timeout);
- } catch (CardException e) {
- log.debug("CardTerminals.waitForChange(" + timeout + ") failed.", e);
- }
- Map<CardTerminal, Card> newCards = new HashMap<CardTerminal, Card>();
- newCards.putAll(updateCards());
- return Collections.unmodifiableMap(newCards);
- }
-} \ No newline at end of file
+ // try to connect to card
+ card = terminal.connect("*");
+ } catch (CardException e) {
+ log.trace("Failed to connect to card.", e);
+ }
+
+ // have we seen this card before?
+ if (terminalCard_.put(terminal, card) == null) {
+ terminalCard_.put(terminal, card);
+ newCards.put(terminal, card);
+ log.trace("terminal '{}' card inserted : {}", terminal, card);
+ }
+ }
+ } catch (CardException e) {
+ log.debug("Failed to list cards.", e);
+ }
+ return newCards;
+
+ }
+
+ public Map<CardTerminal, Card> getCards() {
+ if(state_ < STATE_TERMINAL_FACTORY) {
+ updateTerminalFactory();
+ }
+ if(state_ < STATE_TERMINALS) {
+ updateCardTerminals();
+ }
+ updateCards();
+ Map<CardTerminal, Card> terminalCard = new HashMap<CardTerminal, Card>();
+ terminalCard.putAll(terminalCard_);
+ return Collections.unmodifiableMap(terminalCard);
+ }
+
+ public Map<CardTerminal, Card> waitForInserted(int timeout) {
+ if(state_ < STATE_TERMINAL_FACTORY) {
+ updateTerminalFactory();
+ }
+ if(state_ < STATE_TERMINALS) {
+ updateCardTerminals();
+ }
+ try {
+ // just waiting for a short period of time to allow for abort
+ cardTerminals_.waitForChange(timeout);
+ } catch (CardException e) {
+ log.debug("CardTerminals.waitForChange({}) failed.", timeout, e);
+ }
+ Map<CardTerminal, Card> newCards = new HashMap<CardTerminal, Card>();
+ newCards.putAll(updateCards());
+ return Collections.unmodifiableMap(newCards);
+ }
+}