From b1c8641a63a67e3c64d948f9e8dce5c01e11e2dd Mon Sep 17 00:00:00 2001 From: mcentner Date: Wed, 5 May 2010 15:29:01 +0000 Subject: 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 --- smcc/keystore.ks | Bin 5635 -> 5639 bytes smcc/pom.xml | 15 +- smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java | 134 ++++---- .../at/gv/egiz/smcc/AbstractSignatureCard.java | 22 +- smcc/src/main/java/at/gv/egiz/smcc/BELPICCard.java | 23 +- smcc/src/main/java/at/gv/egiz/smcc/EstEIDCard.java | 280 ++++++++++++++++ .../at/gv/egiz/smcc/ExclSignatureCardProxy.java | 11 +- smcc/src/main/java/at/gv/egiz/smcc/ITCard.java | 24 +- .../main/java/at/gv/egiz/smcc/LogCardChannel.java | 16 +- .../at/gv/egiz/smcc/PINConfirmationException.java | 3 + .../java/at/gv/egiz/smcc/PINFormatException.java | 3 + .../java/at/gv/egiz/smcc/PINMgmtSignatureCard.java | 20 +- smcc/src/main/java/at/gv/egiz/smcc/PINSpec.java | 239 -------------- smcc/src/main/java/at/gv/egiz/smcc/PinInfo.java | 258 +++++++++++++++ smcc/src/main/java/at/gv/egiz/smcc/PtEidCard.java | 310 ++++++++++++++++++ .../src/main/java/at/gv/egiz/smcc/STARCOSCard.java | 218 +++++++------ smcc/src/main/java/at/gv/egiz/smcc/SWCard.java | 12 +- .../java/at/gv/egiz/smcc/SignatureCardFactory.java | 61 +++- .../java/at/gv/egiz/smcc/pin/gui/ModifyPINGUI.java | 10 +- .../at/gv/egiz/smcc/pin/gui/ModifyPINProvider.java | 6 +- .../main/java/at/gv/egiz/smcc/pin/gui/PINGUI.java | 6 +- .../java/at/gv/egiz/smcc/pin/gui/PINProvider.java | 4 +- .../java/at/gv/egiz/smcc/reader/CardReader.java | 32 +- .../at/gv/egiz/smcc/reader/DefaultCardReader.java | 16 +- .../at/gv/egiz/smcc/reader/PinpadCardReader.java | 167 +++++----- .../java/at/gv/egiz/smcc/reader/ReaderFactory.java | 32 +- .../java/at/gv/egiz/smcc/util/ISO7816Utils.java | 51 ++- .../main/java/at/gv/egiz/smcc/util/SMCCHelper.java | 268 +++++++-------- .../java/at/gv/egiz/smcc/util/SmartCardIO.java | 358 ++++++++++----------- .../at/gv/egiz/smcc/EstEIDCard.properties | 1 + .../resources/at/gv/egiz/smcc/PtEidCard.properties | 1 + .../resources/at/gv/egiz/smcc/SWCard.properties | 17 + smcc/src/test/java/at/gv/egiz/smcc/CardTest.java | 16 +- .../java/at/gv/egiz/smcc/acos/A03CardTest.java | 4 +- .../java/at/gv/egiz/smcc/acos/A04CardTest.java | 4 +- .../java/at/gv/egiz/smcc/card/CreateSignature.java | 108 +++++++ .../java/at/gv/egiz/smcc/card/ReadCertiticate.java | 56 ++++ .../egiz/smcc/pin/gui/CancelChangePINProvider.java | 6 +- .../at/gv/egiz/smcc/pin/gui/CancelPINProvider.java | 4 +- .../at/gv/egiz/smcc/pin/gui/ChangePINProvider.java | 6 +- .../at/gv/egiz/smcc/pin/gui/DummyChangePINGUI.java | 10 +- .../java/at/gv/egiz/smcc/pin/gui/DummyPINGUI.java | 6 +- .../gv/egiz/smcc/pin/gui/InterruptPINProvider.java | 4 +- .../smcc/pin/gui/InvalidChangePINProvider.java | 6 +- .../gv/egiz/smcc/pin/gui/InvalidPINProvider.java | 4 +- .../gv/egiz/smcc/pin/gui/SMCCTestPINProvider.java | 4 +- .../egiz/smcc/starcos/STARCOSCardChannelEmul.java | 4 +- .../at/gv/egiz/smcc/starcos/STARCOSCardTest.java | 30 +- .../at/gv/egiz/smcc/starcos/STARCOSG3CardTest.java | 24 +- 49 files changed, 1888 insertions(+), 1026 deletions(-) create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/EstEIDCard.java delete mode 100644 smcc/src/main/java/at/gv/egiz/smcc/PINSpec.java create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/PinInfo.java create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/PtEidCard.java create mode 100644 smcc/src/main/resources/at/gv/egiz/smcc/EstEIDCard.properties create mode 100644 smcc/src/main/resources/at/gv/egiz/smcc/PtEidCard.properties create mode 100644 smcc/src/main/resources/at/gv/egiz/smcc/SWCard.properties create mode 100644 smcc/src/test/java/at/gv/egiz/smcc/card/CreateSignature.java create mode 100644 smcc/src/test/java/at/gv/egiz/smcc/card/ReadCertiticate.java (limited to 'smcc') diff --git a/smcc/keystore.ks b/smcc/keystore.ks index 824c3a40..ba0b4652 100644 Binary files a/smcc/keystore.ks and b/smcc/keystore.ks differ diff --git a/smcc/pom.xml b/smcc/pom.xml index 3febe352..a5a61cd9 100644 --- a/smcc/pom.xml +++ b/smcc/pom.xml @@ -1,15 +1,15 @@ - bku + mocca at.gv.egiz - 1.2.14-SNAPSHOT + 1.3.0-SNAPSHOT 4.0.0 at.gv.egiz smcc smcc jar - 1.2.14-SNAPSHOT + ${project.parent.version} http://bku.egiz.gv.at @@ -24,8 +24,8 @@ - commons-logging - commons-logging + org.slf4j + slf4j-api junit @@ -37,10 +37,5 @@ iaik_jce_full_signed test - \ No newline at end of file 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 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 pinSpecs = new ArrayList(); + 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 */ 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 */ 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 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/PINSpec.java deleted file mode 100644 index f68edbed..00000000 --- a/smcc/src/main/java/at/gv/egiz/smcc/PINSpec.java +++ /dev/null @@ -1,239 +0,0 @@ -/* -* Copyright 2008 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.util.Locale; -import java.util.MissingResourceException; -import java.util.ResourceBundle; - -/** - * - * @author mcentner - */ -public class PINSpec { - - /** - * The minimum PIN length. - */ - protected int minLength = 0; - - /** - * The maximum PIN length or -1 if not specified. - */ - protected int maxLength = -1; - - /** - * The recommended PIN length or -1 if not specified. - */ - protected int recLength = -1; - - /** - * The regular expression pattern of a single PIN digit or character. - */ - protected String rexepPattern; - - /** - * The name of the corresponding resource bundle. - */ - protected String resourceBundleName; - - /** - * The key of the PIN name in the resource bundle. - */ - protected 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; - - /** - * The context AID of the key id. - */ - protected byte[] context_aid; - - /** - * 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. - * - * @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 resourceBundleName the name of a ResourceBundle for this PIN - * @param resourceKey the key to look up the (localized) name of this 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 resourceBundleName, String resourceKey, byte kid, byte[] contextAID) { - - this.minLength = minLenght; - this.maxLength = maxLength; - this.rexepPattern = rexepPattern; - this.resourceBundleName = resourceBundleName; - 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 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[])}. - */ - public String getLocalizedName() { - if (name != null) { - return name; - } else if (resourceBundleName != null){ - try { - return ResourceBundle.getBundle(resourceBundleName).getString(nameKey); - } catch (MissingResourceException e) { - } - } - return nameKey; - } - - /** - * @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[])} - */ - public String getLocalizedName(Locale locale) { - if (name != null) { - return name; - } else if (resourceBundleName != null) { - try { - return ResourceBundle.getBundle(resourceBundleName, locale).getString(nameKey); - } catch (MissingResourceException e) { - } - } - return nameKey; - } - - /** - * @return the recommended PIN length if specified and - * recommended is true, or - * minLength-maxLength - */ - public String getLocalizedLength() { - - if (recLength > 0) { - return "" + recLength; - } else if (maxLength == minLength) { - return "" + minLength; - } else if (maxLength > minLength) { - return minLength + "-" + maxLength; - } else { - return minLength + "+"; - } - - } - - /** - * @return the minimum length of the PIN - */ - public int getMinLength() { - return minLength; - } - - /** - * @return the maximum length of the PIN, or -1 if not specified. - */ - public int getMaxLength() { - return maxLength; - } - - /** - * @return the minimum length of the PIN - */ - public int getRecMinLength() { - return (recLength >= minLength) ? recLength : minLength; - } - - /** - * @return the maximum length of the PIN - */ - public int getRecMaxLength() { - return (recLength >= minLength) ? recLength : maxLength; - } - - /** - * @return the recommended length of the PIN, or -1 if not specified - */ - public int getRecLength() { - return recLength; - } - - /** - * @return the regular expression pattern of one single digit or character - */ - public String getRexepPattern() { - return rexepPattern; - } - - /** - * @return the key id of the PIN - */ - public byte getKID() { - return kid; - } - - /** - * @return the AID the KID is valid in, or null if KID is global - */ - public byte[] getContextAID() { - return context_aid; - } - -} diff --git a/smcc/src/main/java/at/gv/egiz/smcc/PinInfo.java b/smcc/src/main/java/at/gv/egiz/smcc/PinInfo.java new file mode 100644 index 00000000..d2acf666 --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/PinInfo.java @@ -0,0 +1,258 @@ +/* +* Copyright 2008 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.util.Locale; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +/** + * + * @author mcentner + */ +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 final int minLength; + + /** + * The maximum PIN length or -1 if not specified. + */ + protected final int maxLength; + + /** + * The recommended PIN length or -1 if not specified. + */ + protected int recLength = -1; + + /** + * The regular expression pattern of a single PIN digit or character. + */ + protected final String rexepPattern; + + /** + * The name of the corresponding resource bundle. + */ + protected final String resourceBundleName; + + /** + * The key of the PIN name in the resource bundle. + */ + protected final String nameKey; + + /** + * The key id to be used in VERIFY or CHANGE REFERENCE DATA APDUs. + */ + protected final byte kid; + + /** + * The context AID of the key id. + */ + 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. + * + * @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 resourceBundleName the name of a ResourceBundle for this PIN + * @param resourceKey the key to look up the (localized) name of this PIN + * @param kid the key id of the PIN + * @param contextAID the AID the KID is valid in + */ + public PinInfo(int minLenght, int maxLength, String rexepPattern, + String resourceBundleName, String resourceKey, byte kid, byte[] contextAID, int maxRetries) { + + this.minLength = minLenght; + this.maxLength = maxLength; + this.rexepPattern = rexepPattern; + this.resourceBundleName = resourceBundleName; + this.nameKey = resourceKey + ".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 + */ + public String getLocalizedName() { + if (resourceBundleName != null){ + try { + return ResourceBundle.getBundle(resourceBundleName).getString(nameKey); + } catch (MissingResourceException e) { + } + } + return nameKey; + } + + /** + * @param locale the locale for which the name should be returned + * @return the localized name of the PIN, + */ + public String getLocalizedName(Locale locale) { + if (resourceBundleName != null) { + try { + return ResourceBundle.getBundle(resourceBundleName, locale).getString(nameKey); + } catch (MissingResourceException e) { + } + } + return nameKey; + } + + /** + * @return the recommended PIN length if specified and + * recommended is true, or + * minLength-maxLength + */ + public String getLocalizedLength() { + + if (recLength > 0) { + return "" + recLength; + } else if (maxLength == minLength) { + return "" + minLength; + } else if (maxLength > minLength) { + return minLength + "-" + maxLength; + } else { + return minLength + "+"; + } + + } + + /** + * @return the minimum length of the PIN + */ + public int getMinLength() { + return minLength; + } + + /** + * @return the maximum length of the PIN, or -1 if not specified. + */ + public int getMaxLength() { + return maxLength; + } + + /** + * @return the minimum length of the PIN + */ + public int getRecMinLength() { + return (recLength >= minLength) ? recLength : minLength; + } + + /** + * @return the maximum length of the PIN + */ + public int getRecMaxLength() { + return (recLength >= minLength) ? recLength : maxLength; + } + + /** + * @return the recommended length of the PIN, or -1 if not specified + */ + public int getRecLength() { + return recLength; + } + + /** + * @return the regular expression pattern of one single digit or character + */ + public String getRexepPattern() { + return rexepPattern; + } + + /** + * @return the key id of the PIN + */ + public byte getKID() { + return kid; + } + + /** + * @return the AID the KID is valid in, or null if KID is global + */ + 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 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 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 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 queryFeatures(Card icc) { + Logger log = LoggerFactory.getLogger(ReaderFactory.class); Map features = new HashMap(); - 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 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 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 terminalCard_ = new HashMap(); - - 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 terminalCard_ = new HashMap(); + + 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 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 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 newCards = new HashMap(); - 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 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 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 newCards = new HashMap(); + 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 getCards() { - if(state_ < STATE_TERMINAL_FACTORY) { - updateTerminalFactory(); - } - if(state_ < STATE_TERMINALS) { - updateCardTerminals(); - } - updateCards(); - Map terminalCard = new HashMap(); - terminalCard.putAll(terminalCard_); - return Collections.unmodifiableMap(terminalCard); - } - - public Map 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 newCards = new HashMap(); - 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 getCards() { + if(state_ < STATE_TERMINAL_FACTORY) { + updateTerminalFactory(); + } + if(state_ < STATE_TERMINALS) { + updateCardTerminals(); + } + updateCards(); + Map terminalCard = new HashMap(); + terminalCard.putAll(terminalCard_); + return Collections.unmodifiableMap(terminalCard); + } + + public Map 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 newCards = new HashMap(); + newCards.putAll(updateCards()); + return Collections.unmodifiableMap(newCards); + } +} diff --git a/smcc/src/main/resources/at/gv/egiz/smcc/EstEIDCard.properties b/smcc/src/main/resources/at/gv/egiz/smcc/EstEIDCard.properties new file mode 100644 index 00000000..e2deab5b --- /dev/null +++ b/smcc/src/main/resources/at/gv/egiz/smcc/EstEIDCard.properties @@ -0,0 +1 @@ +qs.pin.name=PIN \ No newline at end of file diff --git a/smcc/src/main/resources/at/gv/egiz/smcc/PtEidCard.properties b/smcc/src/main/resources/at/gv/egiz/smcc/PtEidCard.properties new file mode 100644 index 00000000..c64bca9e --- /dev/null +++ b/smcc/src/main/resources/at/gv/egiz/smcc/PtEidCard.properties @@ -0,0 +1 @@ +sig.pin.name=PIN \ No newline at end of file diff --git a/smcc/src/main/resources/at/gv/egiz/smcc/SWCard.properties b/smcc/src/main/resources/at/gv/egiz/smcc/SWCard.properties new file mode 100644 index 00000000..ba5212d4 --- /dev/null +++ b/smcc/src/main/resources/at/gv/egiz/smcc/SWCard.properties @@ -0,0 +1,17 @@ +# Copyright 2008 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. + +sw.pin.name=KeyStore-Password +sw.pin.length=unlimited diff --git a/smcc/src/test/java/at/gv/egiz/smcc/CardTest.java b/smcc/src/test/java/at/gv/egiz/smcc/CardTest.java index 44e48836..17a8a03f 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/CardTest.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/CardTest.java @@ -26,7 +26,6 @@ import java.io.IOException; import java.io.UnsupportedEncodingException; import java.security.NoSuchAlgorithmException; import java.util.Arrays; -import java.util.List; import javax.smartcardio.Card; @@ -38,7 +37,6 @@ import at.gv.egiz.smcc.pin.gui.DummyPINGUI; import at.gv.egiz.smcc.pin.gui.ModifyPINGUI; import at.gv.egiz.smcc.pin.gui.PINGUI; import at.gv.egiz.smcc.pin.gui.SMCCTestPINProvider; -import org.junit.Ignore; @SuppressWarnings("restriction") public abstract class CardTest { @@ -144,7 +142,7 @@ public abstract class CardTest { PINGUI pinProvider = new DummyPINGUI() { @Override - public char[] providePIN(PINSpec spec, int retries) + public char[] providePIN(PinInfo spec, int retries) throws CancelledException, InterruptedException { try { @@ -174,7 +172,7 @@ public abstract class CardTest { PINGUI pinProvider = new DummyPINGUI() { @Override - public char[] providePIN(PINSpec spec, int retries) + public char[] providePIN(PinInfo spec, int retries) throws CancelledException, InterruptedException { try { @@ -195,13 +193,13 @@ public abstract class CardTest { } @Test - public void testGetPinSpecs() throws CardNotSupportedException { + public void testGetPinSpecs() throws CardNotSupportedException, SignatureCardException { PINMgmtSignatureCard signatureCard = (PINMgmtSignatureCard) createSignatureCard(); - List specs = signatureCard.getPINSpecs(); + PinInfo[] specs = signatureCard.getPinInfos(); assertNotNull(specs); - assertTrue(specs.size() > 0); + assertTrue(specs.length > 0); } @@ -214,9 +212,9 @@ public abstract class CardTest { ModifyPINGUI pinProvider = new CancelChangePINProvider(); - List specs = signatureCard.getPINSpecs(); + PinInfo[] specs = signatureCard.getPinInfos(); - signatureCard.activatePIN(specs.get(0), pinProvider); + signatureCard.activatePIN(specs[0], pinProvider); } } \ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/acos/A03CardTest.java b/smcc/src/test/java/at/gv/egiz/smcc/acos/A03CardTest.java index 3a8ac41c..4a94c623 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/acos/A03CardTest.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/acos/A03CardTest.java @@ -32,7 +32,7 @@ import at.gv.egiz.smcc.NotActivatedException; import at.gv.egiz.smcc.PINFormatException; import at.gv.egiz.smcc.PINMgmtSignatureCard; import at.gv.egiz.smcc.pin.gui.SMCCTestPINProvider; -import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.PinInfo; import at.gv.egiz.smcc.SignatureCard; import at.gv.egiz.smcc.SignatureCardException; import at.gv.egiz.smcc.SignatureCardFactory; @@ -70,7 +70,7 @@ public class A03CardTest extends ACOSCardTest { applDEC.setPin(ACOSApplDEC.KID_PIN_DEC, defaultPin); applDEC.setPin(A03ApplDEC.KID_PIN_INF, defaultPin); - for (PINSpec pinSpec : signatureCard.getPINSpecs()) { + for (PinInfo pinSpec : signatureCard.getPinInfos()) { char[] pin = defaultPin; diff --git a/smcc/src/test/java/at/gv/egiz/smcc/acos/A04CardTest.java b/smcc/src/test/java/at/gv/egiz/smcc/acos/A04CardTest.java index 1cbea1b3..a7a5eef4 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/acos/A04CardTest.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/acos/A04CardTest.java @@ -36,7 +36,7 @@ import at.gv.egiz.smcc.LockedException; import at.gv.egiz.smcc.NotActivatedException; import at.gv.egiz.smcc.PINFormatException; import at.gv.egiz.smcc.PINMgmtSignatureCard; -import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.PinInfo; import at.gv.egiz.smcc.SignatureCard; import at.gv.egiz.smcc.SignatureCardException; import at.gv.egiz.smcc.SignatureCardFactory; @@ -80,7 +80,7 @@ public class A04CardTest extends ACOSCardTest { ACOSApplDEC applDEC = (ACOSApplDEC) card.getApplication(ACOSAppl.AID_DEC); applDEC.setPin(ACOSApplDEC.KID_PIN_DEC, defaultPin); - for (PINSpec pinSpec : signatureCard.getPINSpecs()) { + for (PinInfo pinSpec : signatureCard.getPinInfos()) { char[] pin = defaultPin; diff --git a/smcc/src/test/java/at/gv/egiz/smcc/card/CreateSignature.java b/smcc/src/test/java/at/gv/egiz/smcc/card/CreateSignature.java new file mode 100644 index 00000000..956bcc99 --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/card/CreateSignature.java @@ -0,0 +1,108 @@ +/* +* 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.card; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.math.BigInteger; +import java.nio.charset.Charset; +import java.util.Formatter; +import java.util.Locale; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PinInfo; +import at.gv.egiz.smcc.SignatureCard; +import at.gv.egiz.smcc.SignatureCardException; +import at.gv.egiz.smcc.SignatureCard.KeyboxName; +import at.gv.egiz.smcc.pin.gui.PINGUI; +import at.gv.egiz.smcc.util.SMCCHelper; + +public class CreateSignature { + + /** + * @param args + * @throws Exception + */ + public static void main(String[] args) throws Exception { + + SMCCHelper helper = new SMCCHelper(); + + SignatureCard signatureCard = helper.getSignatureCard(Locale.getDefault()); + + if (signatureCard == null) { + return; + } + + InputStream data = new ByteArrayInputStream("just a test".getBytes(Charset.forName("UTF-8"))); + byte[] signature = createSignature(signatureCard, KeyboxName.SECURE_SIGNATURE_KEYPAIR, data); + Formatter printf = new Formatter(System.out); + printf.format("Signature: %1$x", new BigInteger(signature)); + + } + + public static byte[] createSignature(SignatureCard signatureCard, KeyboxName keyboxName, InputStream data) throws SignatureCardException, InterruptedException, IOException { + return signatureCard.createSignature(data, keyboxName, new ConsolePINGUI(), "http://www.w3.org/2000/09/xmldsig#rsa-sha1"); + } + + public static class ConsolePINGUI implements PINGUI { + + @Override + public void allKeysCleared() { + } + + @Override + public void correctionButtonPressed() { + } + + @Override + public void enterPIN(PinInfo spec, int retries) throws CancelledException, + InterruptedException { + } + + @Override + public void enterPINDirect(PinInfo spec, int retries) + throws CancelledException, InterruptedException { + } + + @Override + public void validKeyPressed() { + } + + @Override + public char[] providePIN(PinInfo pinSpec, int retries) + throws CancelledException, InterruptedException { + System.out.print("Enter " + pinSpec.getLocalizedName() + ": "); + BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); + String pin; + try { + pin = in.readLine(); + } catch (IOException e) { + throw new CancelledException(e); + } + if (pin == null || pin.length() == 0) { + throw new CancelledException(); + } + return pin.toCharArray(); + } + + } + +} diff --git a/smcc/src/test/java/at/gv/egiz/smcc/card/ReadCertiticate.java b/smcc/src/test/java/at/gv/egiz/smcc/card/ReadCertiticate.java new file mode 100644 index 00000000..38a4042a --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/card/ReadCertiticate.java @@ -0,0 +1,56 @@ +/* +* 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.card; + +import java.io.ByteArrayInputStream; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.Locale; + +import at.gv.egiz.smcc.SignatureCard; +import at.gv.egiz.smcc.SignatureCardException; +import at.gv.egiz.smcc.SignatureCard.KeyboxName; +import at.gv.egiz.smcc.util.SMCCHelper; + +public class ReadCertiticate { + + public static void main(String[] args) throws Exception { + + SMCCHelper helper = new SMCCHelper(); + + SignatureCard signatureCard = helper.getSignatureCard(Locale.getDefault()); + + if (signatureCard == null) { + return; + } + + X509Certificate cert = readCertificate(signatureCard, KeyboxName.SECURE_SIGNATURE_KEYPAIR); + System.out.println(cert.toString()); + + } + + public static X509Certificate readCertificate(SignatureCard signatureCard, + KeyboxName keyboxName) throws SignatureCardException, + InterruptedException, CertificateException { + byte[] certificate = signatureCard.getCertificate(KeyboxName.SECURE_SIGNATURE_KEYPAIR); + CertificateFactory certificateFactory = CertificateFactory.getInstance("X509"); + return (X509Certificate) certificateFactory.generateCertificate(new ByteArrayInputStream(certificate)); + } + +} diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/CancelChangePINProvider.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/CancelChangePINProvider.java index dffe7e29..1c720a14 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/CancelChangePINProvider.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/CancelChangePINProvider.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; public class CancelChangePINProvider extends DummyChangePINGUI implements ModifyPINGUI { @@ -25,13 +25,13 @@ public class CancelChangePINProvider extends DummyChangePINGUI implements Modify } @Override - public char[] provideCurrentPIN(PINSpec spec, int retries) + public char[] provideCurrentPIN(PinInfo spec, int retries) throws CancelledException, InterruptedException { throw new CancelledException("cancelled by cancelPINProvider"); } @Override - public char[] provideNewPIN(PINSpec spec) + public char[] provideNewPIN(PinInfo spec) throws CancelledException, InterruptedException { throw new CancelledException("cancelled by cancelPINProvider"); } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/CancelPINProvider.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/CancelPINProvider.java index 77f19345..7da3ec5c 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/CancelPINProvider.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/CancelPINProvider.java @@ -17,12 +17,12 @@ 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 class CancelPINProvider extends DummyPINGUI implements PINGUI { @Override - public char[] providePIN(PINSpec spec, int retries) + public char[] providePIN(PinInfo spec, int retries) throws CancelledException, InterruptedException { throw new CancelledException("cancelled by cancelPINProvider"); } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/ChangePINProvider.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/ChangePINProvider.java index 5eb8b9a1..50bc0784 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/ChangePINProvider.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/ChangePINProvider.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; public class ChangePINProvider extends DummyChangePINGUI implements ModifyPINGUI { @@ -35,14 +35,14 @@ public class ChangePINProvider extends DummyChangePINGUI implements ModifyPINGUI } @Override - public char[] provideCurrentPIN(PINSpec spec, int retries) + public char[] provideCurrentPIN(PinInfo spec, int retries) throws CancelledException, InterruptedException { provided++; return oldPin; } @Override - public char[] provideNewPIN(PINSpec spec) { + public char[] provideNewPIN(PinInfo spec) { return pin; } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/DummyChangePINGUI.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/DummyChangePINGUI.java index fff89409..e6192417 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/DummyChangePINGUI.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/DummyChangePINGUI.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; public abstract class DummyChangePINGUI implements ModifyPINGUI { @@ -47,22 +47,22 @@ public abstract class DummyChangePINGUI implements ModifyPINGUI { } @Override - public void modifyPINDirect(PINSpec spec, int retries) throws CancelledException, InterruptedException { + public void modifyPINDirect(PinInfo spec, int retries) throws CancelledException, InterruptedException { throw new UnsupportedOperationException("Not supported yet."); } @Override - public void enterCurrentPIN(PINSpec spec, int retries) { + public void enterCurrentPIN(PinInfo spec, int retries) { throw new UnsupportedOperationException("Not supported yet."); } @Override - public void enterNewPIN(PINSpec spec) { + public void enterNewPIN(PinInfo spec) { throw new UnsupportedOperationException("Not supported yet."); } @Override - public void confirmNewPIN(PINSpec spec) { + public void confirmNewPIN(PinInfo spec) { throw new UnsupportedOperationException("Not supported yet."); } } \ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/DummyPINGUI.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/DummyPINGUI.java index 4d99b5c1..27d268c5 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/DummyPINGUI.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/DummyPINGUI.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 abstract class DummyPINGUI implements PINGUI { @Override - public void enterPINDirect(PINSpec spec, int retries) throws CancelledException, InterruptedException { + public void enterPINDirect(PinInfo spec, int retries) throws CancelledException, InterruptedException { throw new UnsupportedOperationException("Not supported yet."); } @Override - public void enterPIN(PINSpec spec, int retries) throws CancelledException, InterruptedException { + public void enterPIN(PinInfo spec, int retries) throws CancelledException, InterruptedException { throw new UnsupportedOperationException("Not supported yet."); } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InterruptPINProvider.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InterruptPINProvider.java index 5706b888..814ced11 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InterruptPINProvider.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InterruptPINProvider.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; @SuppressWarnings("restriction") public class InterruptPINProvider extends DummyPINGUI implements PINGUI { @@ -26,7 +26,7 @@ public class InterruptPINProvider extends DummyPINGUI implements PINGUI { } @Override - public char[] providePIN(PINSpec spec, int retries) + public char[] providePIN(PinInfo spec, int retries) throws CancelledException, InterruptedException { throw new InterruptedException("interrupted by cancelPINProvider"); } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InvalidChangePINProvider.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InvalidChangePINProvider.java index 69c9f42a..53732d82 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InvalidChangePINProvider.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InvalidChangePINProvider.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; public class InvalidChangePINProvider extends DummyChangePINGUI implements ModifyPINGUI { @@ -35,7 +35,7 @@ public class InvalidChangePINProvider extends DummyChangePINGUI implements Modif } @Override - public char[] provideCurrentPIN(PINSpec spec, int retries) + public char[] provideCurrentPIN(PinInfo spec, int retries) throws CancelledException, InterruptedException { if (provided >= numWrongTries) { throw new CancelledException("Number of wrong tries reached: " + provided); @@ -50,7 +50,7 @@ public class InvalidChangePINProvider extends DummyChangePINGUI implements Modif } @Override - public char[] provideNewPIN(PINSpec spec) { + public char[] provideNewPIN(PinInfo spec) { return pin; } } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InvalidPINProvider.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InvalidPINProvider.java index db01fd0d..695ec964 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InvalidPINProvider.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InvalidPINProvider.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; public class InvalidPINProvider extends DummyPINGUI implements PINGUI { @@ -32,7 +32,7 @@ public class InvalidPINProvider extends DummyPINGUI implements PINGUI { } @Override - public char[] providePIN(PINSpec spec, int retries) + public char[] providePIN(PinInfo spec, int retries) throws CancelledException, InterruptedException { if (provided >= numWrongTries) { throw new CancelledException("Number of wrong tries reached: " + provided); diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/SMCCTestPINProvider.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/SMCCTestPINProvider.java index dffc90d7..e6fd67d5 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/SMCCTestPINProvider.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/SMCCTestPINProvider.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; public class SMCCTestPINProvider extends DummyPINGUI implements PINGUI { @@ -29,7 +29,7 @@ public class SMCCTestPINProvider extends DummyPINGUI implements PINGUI { } @Override - public char[] providePIN(PINSpec spec, int retries) + public char[] providePIN(PinInfo spec, int retries) throws CancelledException, InterruptedException { provided++; return pin; diff --git a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardChannelEmul.java b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardChannelEmul.java index 2e0c54eb..f37f12dd 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardChannelEmul.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardChannelEmul.java @@ -364,7 +364,7 @@ public class STARCOSCardChannelEmul extends CardChannelEmul { } PIN pin; - if (currentAppl != null) { + if ((command.getP2() & 0x80) > 0 && currentAppl != null) { pin = currentAppl.pins.get(command.getP2()); } else { pin = globalPins.get(command.getP2()); @@ -388,7 +388,7 @@ public class STARCOSCardChannelEmul extends CardChannelEmul { if (response.getSW() == 0x9000) { PIN pin; - if (currentAppl != null) { + if ((command.getP2() & 0x80) > 0 && currentAppl != null) { pin = currentAppl.pins.get(command.getP2()); } else { pin = globalPins.get(command.getP2()); diff --git a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardTest.java b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardTest.java index 154884d4..82e48d64 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardTest.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardTest.java @@ -41,7 +41,7 @@ import at.gv.egiz.smcc.NotActivatedException; import at.gv.egiz.smcc.PIN; import at.gv.egiz.smcc.PINFormatException; import at.gv.egiz.smcc.PINMgmtSignatureCard; -import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.PinInfo; import at.gv.egiz.smcc.SignatureCard; import at.gv.egiz.smcc.SignatureCardException; import at.gv.egiz.smcc.SignatureCardFactory; @@ -258,17 +258,17 @@ public class STARCOSCardTest extends CardTest { PINMgmtSignatureCard signatureCard = (PINMgmtSignatureCard) createSignatureCard( STARCOSCardEmul.DEFAULT_SS_PIN, STARCOSCardEmul.DEFAULT_SS_PIN, PIN.STATE_RESET); - for (PINSpec pinSpec : signatureCard.getPINSpecs()) { + for (PinInfo pinInfo : signatureCard.getPinInfos()) { char[] pin = "123456".toCharArray(); - for (int i = pinSpec.getMinLength(); i <= pinSpec.getMaxLength(); i++) { - signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(pin)); + for (int i = pinInfo.getMinLength(); i <= pinInfo.getMaxLength(); i++) { + signatureCard.verifyPIN(pinInfo, new SMCCTestPINProvider(pin)); char[] newPin = new char[i]; Arrays.fill(newPin, '0'); signatureCard - .changePIN(pinSpec, new ChangePINProvider(pin, newPin)); - signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(newPin)); + .changePIN(pinInfo, new ChangePINProvider(pin, newPin)); + signatureCard.verifyPIN(pinInfo, new SMCCTestPINProvider(newPin)); pin = newPin; } } @@ -283,20 +283,20 @@ public class STARCOSCardTest extends CardTest { PINMgmtSignatureCard signatureCard = (PINMgmtSignatureCard) createSignatureCard( null, null, PIN.STATE_PIN_NOTACTIVE); - for (PINSpec pinSpec : signatureCard.getPINSpecs()) { + for (PinInfo pinInfo : signatureCard.getPinInfos()) { - char[] pin = "1234567890".substring(0, pinSpec.getMinLength()).toCharArray(); + char[] pin = "1234567890".substring(0, pinInfo.getMinLength()).toCharArray(); boolean notActive = false; try { - signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(pin)); + signatureCard.verifyPIN(pinInfo, new SMCCTestPINProvider(pin)); } catch (NotActivatedException ex) { notActive = true; } assertTrue(notActive); - signatureCard.activatePIN(pinSpec, new ChangePINProvider(null, pin)); - signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(pin)); + signatureCard.activatePIN(pinInfo, new ChangePINProvider(null, pin)); + signatureCard.verifyPIN(pinInfo, new SMCCTestPINProvider(pin)); } } @@ -307,13 +307,13 @@ public class STARCOSCardTest extends CardTest { PINMgmtSignatureCard signatureCard = (PINMgmtSignatureCard) createSignatureCard(); - for (PINSpec pinSpec : signatureCard.getPINSpecs()) { + for (PinInfo pinInfo : signatureCard.getPinInfos()) { char[] invalidPin = "999999".toCharArray(); int numInvalidTries = 2; InvalidPINProvider invalidPinProvider = new InvalidPINProvider(invalidPin, numInvalidTries); try { - signatureCard.verifyPIN(pinSpec, invalidPinProvider); + signatureCard.verifyPIN(pinInfo, invalidPinProvider); } catch (CancelledException ex) { } finally { assertTrue(invalidPinProvider.getProvided() == numInvalidTries); @@ -328,7 +328,7 @@ public class STARCOSCardTest extends CardTest { PINMgmtSignatureCard signatureCard = (PINMgmtSignatureCard) createSignatureCard(); - for (PINSpec pinSpec : signatureCard.getPINSpecs()) { + for (PinInfo pinInfo : signatureCard.getPinInfos()) { char[] invalidPin = "999999".toCharArray(); int numInvalidTries = 2; @@ -336,7 +336,7 @@ public class STARCOSCardTest extends CardTest { new InvalidChangePINProvider(invalidPin, invalidPin, numInvalidTries); try { - signatureCard.changePIN(pinSpec, invalidPinProvider); + signatureCard.changePIN(pinInfo, invalidPinProvider); } catch (CancelledException ex) { } finally { assertTrue(invalidPinProvider.getProvided() == numInvalidTries); diff --git a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSG3CardTest.java b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSG3CardTest.java index 06744c82..1d8507b2 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSG3CardTest.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSG3CardTest.java @@ -24,7 +24,6 @@ import java.util.Arrays; import org.junit.Test; import at.gv.egiz.smcc.CancelledException; -import at.gv.egiz.smcc.CardEmul; import at.gv.egiz.smcc.CardNotSupportedException; import at.gv.egiz.smcc.CardTerminalEmul; import at.gv.egiz.smcc.CardTest; @@ -34,12 +33,11 @@ import at.gv.egiz.smcc.NotActivatedException; import at.gv.egiz.smcc.PIN; import at.gv.egiz.smcc.PINFormatException; import at.gv.egiz.smcc.PINMgmtSignatureCard; -import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.PinInfo; import at.gv.egiz.smcc.SignatureCard; import at.gv.egiz.smcc.SignatureCardException; import at.gv.egiz.smcc.SignatureCardFactory; import at.gv.egiz.smcc.pin.gui.SMCCTestPINProvider; -import org.junit.Ignore; public class STARCOSG3CardTest extends CardTest { @@ -72,17 +70,17 @@ public class STARCOSG3CardTest extends CardTest { PINMgmtSignatureCard signatureCard = (PINMgmtSignatureCard) createSignatureCard( STARCOSG3CardEmul.DEFAULT_SS_PIN, STARCOSG3CardEmul.DEFAULT_SS_PIN, PIN.STATE_RESET); - for (PINSpec pinSpec : signatureCard.getPINSpecs()) { + for (PinInfo pinInfo : signatureCard.getPinInfos()) { char[] pin = "123456".toCharArray(); - for (int i = pinSpec.getMinLength(); i <= pinSpec.getMaxLength(); i++) { - signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(pin)); + for (int i = pinInfo.getMinLength(); i <= pinInfo.getMaxLength(); i++) { + signatureCard.verifyPIN(pinInfo, new SMCCTestPINProvider(pin)); char[] newPin = new char[i]; Arrays.fill(newPin, '0'); signatureCard - .changePIN(pinSpec, new ChangePINProvider(pin, newPin)); - signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(newPin)); + .changePIN(pinInfo, new ChangePINProvider(pin, newPin)); + signatureCard.verifyPIN(pinInfo, new SMCCTestPINProvider(newPin)); pin = newPin; } } @@ -97,21 +95,21 @@ public class STARCOSG3CardTest extends CardTest { PINMgmtSignatureCard signatureCard = (PINMgmtSignatureCard) createSignatureCard( STARCOSG3CardEmul.TRANSPORT_SS_PIN, STARCOSG3CardEmul.TRANSPORT_SS_PIN, PIN.STATE_PIN_NOTACTIVE); - for (PINSpec pinSpec : signatureCard.getPINSpecs()) { + for (PinInfo pinInfo : signatureCard.getPinInfos()) { - char[] pin = "123456789".substring(0, pinSpec.getMinLength()).toCharArray(); + char[] pin = "123456789".substring(0, pinInfo.getMinLength()).toCharArray(); char[] transportPIN = "123456".toCharArray(); boolean notActive = false; try { - signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(pin)); + signatureCard.verifyPIN(pinInfo, new SMCCTestPINProvider(pin)); } catch (NotActivatedException ex) { notActive = true; } assertTrue(notActive); - signatureCard.activatePIN(pinSpec, new ChangePINProvider(transportPIN, pin)); - signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(pin)); + signatureCard.activatePIN(pinInfo, new ChangePINProvider(transportPIN, pin)); + signatureCard.verifyPIN(pinInfo, new SMCCTestPINProvider(pin)); } } -- cgit v1.2.3