diff options
Diffstat (limited to 'smcc/src/main')
5 files changed, 193 insertions, 68 deletions
diff --git a/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java b/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java index 57925240..c2c62fd8 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java @@ -31,6 +31,7 @@ package at.gv.egiz.smcc; import at.gv.egiz.smcc.util.SMCCHelper; import java.nio.charset.Charset; +import javax.smartcardio.Card; import javax.smartcardio.CardChannel; import javax.smartcardio.CardException; import javax.smartcardio.CommandAPDU; @@ -334,8 +335,8 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { } @Override - public int verifyPIN(String pin, byte kid) throws LockedException, NotActivatedException, SignatureCardException { - + protected int verifyPIN(String pin, byte kid) throws LockedException, NotActivatedException, SignatureCardException { + CardChannel channel = getCardChannel(); ResponseAPDU resp; @@ -343,13 +344,17 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { if (pin != null) { resp = transmit(channel, new CommandAPDU(0x00, 0x20, 0x00, kid, encodePINBlock(pin)), false); } else { + //TODO this is not supported resp = transmit(channel, new CommandAPDU(0x00, 0x20, 0x00, kid), false); } } catch (CardException ex) { log.error("smart card communication failed: " + ex.getMessage()); throw new SignatureCardException("smart card communication failed: " + ex.getMessage(), ex); } - + + //6A 00 (falshe P1/P2) nicht in contextAID + //69 85 (nutzungsbedingungen nicht erfüllt) in DF_Sig und nicht sigpin + if (resp.getSW() == 0x63c0) { throw new LockedException("PIN locked."); } else if (resp.getSW1() == 0x63 && resp.getSW2() >> 4 == 0xc) { @@ -363,7 +368,6 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { throw new SignatureCardException("Failed to verify pin: SW=" + Integer.toHexString(resp.getSW()) + "."); } - } private void mseSetDST(int p1, int p2, byte[] dst) throws CardException, SignatureCardException { @@ -432,8 +436,7 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { * @param pin * @return a 8 byte pin block */ - @Override - public byte[] encodePINBlock(String pin) { + private byte[] encodePINBlock(String pin) { byte[] asciiPIN = pin.getBytes(Charset.forName("ASCII")); byte[] encodedPIN = new byte[8]; System.arraycopy(asciiPIN, 0, encodedPIN, 0, Math.min(asciiPIN.length, @@ -443,7 +446,72 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { } @Override - public void activatePIN(byte kid, byte[] contextAID, String pin) throws SignatureCardException { + public void activatePIN(PINSpec pinSpec, String pin) throws SignatureCardException { throw new SignatureCardException("PIN activation not supported by this card"); } + + /** + * SCARD_E_NOT_TRANSACTED inf/dec PIN not active (pcsc crash) + * @param pinSpec + * @param oldPIN + * @param newPIN + * @throws at.gv.egiz.smcc.LockedException + * @throws at.gv.egiz.smcc.VerificationFailedException + * @throws at.gv.egiz.smcc.NotActivatedException + * @throws at.gv.egiz.smcc.SignatureCardException + */ + @Override + public void changePIN(PINSpec pinSpec, String oldPIN, String newPIN) + throws LockedException, VerificationFailedException, NotActivatedException, SignatureCardException { + Card icc = getCard(); + try { + icc.beginExclusive(); + CardChannel channel = icc.getBasicChannel(); + + if (pinSpec.getContextAID() != null) { + ResponseAPDU responseAPDU = transmit(channel, + new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, pinSpec.getContextAID())); + if (responseAPDU.getSW() != 0x9000) { + icc.endExclusive(); + String msg = "Select AID " + SMCCHelper.toString(pinSpec.getContextAID()) + + ": SW=" + Integer.toHexString(responseAPDU.getSW()); + log.error(msg); + throw new SignatureCardException(msg); + } + } + + byte[] cmd = new byte[16]; + System.arraycopy(encodePINBlock(oldPIN), 0, cmd, 0, 8); + System.arraycopy(encodePINBlock(newPIN), 0, cmd, 8, 8); + + ResponseAPDU responseAPDU = transmit(channel, + new CommandAPDU(0x00, 0x24, 0x00, pinSpec.getKID(), cmd), false); + + icc.endExclusive(); + + log.debug("change pin returned SW=" + Integer.toHexString(responseAPDU.getSW())); + + if (responseAPDU.getSW() == 0x63c0) { + log.error(pinSpec.getLocalizedName() + " locked"); + throw new LockedException(); + } else if (responseAPDU.getSW1() == 0x63 && responseAPDU.getSW2() >> 4 == 0xc) { + int retries = responseAPDU.getSW2() & 0x0f; + log.error("wrong " + pinSpec.getLocalizedName() + ", " + retries + " retries"); + throw new VerificationFailedException(retries); + } else if (responseAPDU.getSW() == 0x6983) { + // sig-pin only (card not transacted for inf/dec pin) + log.error(pinSpec.getLocalizedName() + " not activated"); + throw new NotActivatedException(); + } else if (responseAPDU.getSW() != 0x9000) { + String msg = "Failed to change " + pinSpec.getLocalizedName() + + ": SW=" + Integer.toHexString(responseAPDU.getSW()); + log.error(msg); + throw new SignatureCardException(msg); + } + } catch (CardException ex) { + log.error("Failed to change " + pinSpec.getLocalizedName() + + ": " + ex.getMessage()); + throw new SignatureCardException(ex.getMessage(), ex); + } + } } 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 63301bd1..39952bb9 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java @@ -37,6 +37,8 @@ import java.util.List; import java.util.Locale; import java.util.ResourceBundle; +import java.util.logging.Level; +import java.util.logging.Logger; import javax.smartcardio.ATR; import javax.smartcardio.Card; import javax.smartcardio.CardChannel; @@ -117,8 +119,8 @@ public abstract class AbstractSignatureCard implements SignatureCard { protected abstract ResponseAPDU selectFileFID(byte[] fid) throws CardException, SignatureCardException; - // made public -// protected abstract int verifyPIN(String pin, byte kid) throws CardException, SignatureCardException; + protected abstract int verifyPIN(String pin, byte kid) + throws LockedException, NotActivatedException, SignatureCardException; protected byte[] readRecord(int recordNumber) throws SignatureCardException, CardException { @@ -321,7 +323,7 @@ public abstract class AbstractSignatureCard implements SignatureCard { throw new VerificationFailedException(retries); } } - + return readBinaryTLV(maxLength, (byte) 0x30); @@ -443,53 +445,40 @@ public abstract class AbstractSignatureCard implements SignatureCard { return pinSpecs; } - public void changePIN(byte kid, byte[] contextAID, String oldPIN, String newPIN) throws SignatureCardException, VerificationFailedException { + @Override + public int verifyPIN(PINSpec pinSpec, String pin) throws LockedException, NotActivatedException, SignatureCardException { + Card icc = getCard(); try { icc.beginExclusive(); CardChannel channel = icc.getBasicChannel(); - if (contextAID != null) { + if (pinSpec.getContextAID() != null) { ResponseAPDU responseAPDU = transmit(channel, - new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, contextAID)); + new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, pinSpec.getContextAID())); if (responseAPDU.getSW() != 0x9000) { icc.endExclusive(); - String msg = "Failed to change PIN " + SMCCHelper.toString(new byte[]{kid}) + - ": Failed to select AID " + SMCCHelper.toString(contextAID) + + String msg = "Failed to verify PIN " + + SMCCHelper.toString(new byte[]{pinSpec.getKID()}) + + ": Failed to verify AID " + + SMCCHelper.toString(pinSpec.getContextAID()) + ": " + SMCCHelper.toString(responseAPDU.getBytes()); log.error(msg); throw new SignatureCardException(msg); } } + return verifyPIN(pin, pinSpec.getKID()); - byte[] cmd = new byte[16]; - System.arraycopy(encodePINBlock(oldPIN), 0, cmd, 0, 8); - System.arraycopy(encodePINBlock(newPIN), 0, cmd, 8, 8); - - ResponseAPDU responseAPDU = transmit(channel, - new CommandAPDU(0x00, 0x24, 0x00, kid, cmd), false); - - icc.endExclusive(); - - if (responseAPDU.getSW1() == 0x63 && responseAPDU.getSW2() >> 4 == 0xc) { - int retries = responseAPDU.getSW2() & 0x0f; - log.error("Failed VERIFY PIN, " + retries + " tries left"); - throw new VerificationFailedException(retries); - } - if (responseAPDU.getSW() != 0x9000) { - String msg = "Failed to change PIN " - + SMCCHelper.toString(new byte[]{kid}) + ": " - + SMCCHelper.toString(responseAPDU.getBytes()); - log.error(msg); - throw new SignatureCardException(msg); + } catch (CardException ex) { + log.error("failed to verify pinspec: " + ex.getMessage(), ex); + throw new SignatureCardException(ex); + } finally { + try { + icc.endExclusive(); + } catch (CardException ex) { + log.trace("failed to end exclusive card access: " + ex.getMessage()); } - } catch (CardException ex) { - log.error("Failed to change PIN: " + ex.getMessage()); - throw new SignatureCardException(ex.getMessage(), ex); } } - - abstract byte[] encodePINBlock(String pin); - } 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 b1288f74..3c5f38a2 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java @@ -512,7 +512,7 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard throw new LockedException(); } else if (resp.getSW() == 0x6984) { // PIN LCS = "Initialized" (-> not activated) - throw new NotActivatedException("PIN not set."); + throw new NotActivatedException(); } else if (resp.getSW() == 0x9000) { return -1; // success } else { @@ -552,8 +552,7 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard * @return a 8 byte pin block consisting of length byte (0x2X), * the BCD encoded pin and a 0xFF padding */ - @Override - public byte[] encodePINBlock(String pin) { + private byte[] encodePINBlock(String pin) { char[] pinChars = pin.toCharArray(); int numDigits = pinChars.length; int numBytes = (int) Math.ceil(numDigits/2.0); @@ -572,37 +571,108 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard return pinBlock; } - public void activatePIN(byte kid, byte[] contextAID, String pin) throws SignatureCardException { + @Override + public void activatePIN(PINSpec pinSpec, String pin) + throws SignatureCardException { Card icc = getCard(); try { icc.beginExclusive(); CardChannel channel = icc.getBasicChannel(); - if (contextAID != null) { + if (pinSpec.getContextAID() != null) { ResponseAPDU responseAPDU = transmit(channel, - new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, contextAID)); + new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, pinSpec.getContextAID())); if (responseAPDU.getSW() != 0x9000) { icc.endExclusive(); - String msg = "Failed to activate PIN " + SMCCHelper.toString(new byte[]{kid}) + - ": Failed to select AID " + SMCCHelper.toString(contextAID) + - ": " + SMCCHelper.toString(responseAPDU.getBytes()); + String msg = "Select AID " + SMCCHelper.toString(pinSpec.getContextAID()) + + ": SW=" + Integer.toHexString(responseAPDU.getSW()); log.error(msg); throw new SignatureCardException(msg); } } ResponseAPDU responseAPDU = transmit(channel, - new CommandAPDU(0x00, 0x24, 0x01, kid, encodePINBlock(pin)), false); + new CommandAPDU(0x00, 0x24, 0x01, pinSpec.getKID(), encodePINBlock(pin)), + false); icc.endExclusive(); - if (responseAPDU.getSW() != 0x9000) { - String msg = "Failed to activate PIN " + SMCCHelper.toString(new byte[]{kid}) + ": " + SMCCHelper.toString(responseAPDU.getBytes()); + log.debug("activate pin returned SW=" + Integer.toHexString(responseAPDU.getSW())); + + if (responseAPDU.getSW() != 0x9000) { + String msg = "Failed to activate " + pinSpec.getLocalizedName() + + ": SW=" + Integer.toHexString(responseAPDU.getSW()); + log.error(msg); + throw new SignatureCardException(msg); + } + } catch (CardException ex) { + log.error("Failed to activate " + pinSpec.getLocalizedName() + + ": " + ex.getMessage()); + throw new SignatureCardException(ex.getMessage(), ex); + } + } + + /** + * activates pin (newPIN) if not active + * @param pinSpec + * @param oldPIN + * @param newPIN + * @throws at.gv.egiz.smcc.LockedException + * @throws at.gv.egiz.smcc.VerificationFailedException + * @throws at.gv.egiz.smcc.NotActivatedException + * @throws at.gv.egiz.smcc.SignatureCardException + */ + @Override + public void changePIN(PINSpec pinSpec, String oldPIN, String newPIN) + throws LockedException, VerificationFailedException, NotActivatedException, SignatureCardException { + Card icc = getCard(); + try { + icc.beginExclusive(); + CardChannel channel = icc.getBasicChannel(); + + if (pinSpec.getContextAID() != null) { + ResponseAPDU responseAPDU = transmit(channel, + new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, pinSpec.getContextAID())); + if (responseAPDU.getSW() != 0x9000) { + icc.endExclusive(); + String msg = "Select AID " + SMCCHelper.toString(pinSpec.getContextAID()) + + ": SW=" + Integer.toHexString(responseAPDU.getSW()); + log.error(msg); + throw new SignatureCardException(msg); + } + } + + byte[] cmd = new byte[16]; + System.arraycopy(encodePINBlock(oldPIN), 0, cmd, 0, 8); + System.arraycopy(encodePINBlock(newPIN), 0, cmd, 8, 8); + + ResponseAPDU responseAPDU = transmit(channel, + new CommandAPDU(0x00, 0x24, 0x00, pinSpec.getKID(), cmd), false); + + icc.endExclusive(); + + log.debug("change pin returned SW=" + Integer.toHexString(responseAPDU.getSW())); + + // activates pin (newPIN) if not active + if (responseAPDU.getSW() == 0x63c0) { + log.error(pinSpec.getLocalizedName() + " locked"); + throw new LockedException(); + } else if (responseAPDU.getSW1() == 0x63 && responseAPDU.getSW2() >> 4 == 0xc) { + int retries = responseAPDU.getSW2() & 0x0f; + log.error("wrong " + pinSpec.getLocalizedName() + ", " + retries + " retries"); + throw new VerificationFailedException(retries); + } else if (responseAPDU.getSW() == 0x6983) { + log.error(pinSpec.getLocalizedName() + " locked"); + throw new LockedException(); + } else if (responseAPDU.getSW() != 0x9000) { + String msg = "Failed to change " + pinSpec.getLocalizedName() + + ": SW=" + Integer.toHexString(responseAPDU.getSW()); log.error(msg); throw new SignatureCardException(msg); } } catch (CardException ex) { - log.error("Failed to activate PIN: " + ex.getMessage()); + log.error("Failed to change " + pinSpec.getLocalizedName() + + ": " + ex.getMessage()); throw new SignatureCardException(ex.getMessage(), ex); } } 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 57aeb994..d7763be0 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java @@ -394,21 +394,20 @@ public class SWCard implements SignatureCard { } @Override - public int verifyPIN(String pin, byte kid) throws LockedException, NotActivatedException, SignatureCardException { - return -1; - } - - @Override public List<PINSpec> getPINSpecs() { return new ArrayList<PINSpec>(); } @Override - public void changePIN(byte kid, byte[] contextAID, String oldPIN, String newPIN) throws SignatureCardException, VerificationFailedException { + public int verifyPIN(PINSpec pinSpec, String pin) throws LockedException, NotActivatedException, SignatureCardException { + return -1; } @Override - public void activatePIN(byte kid, byte[] contextAID, String pin) throws SignatureCardException { + public void changePIN(PINSpec pinSpec, String oldPIN, String newPIN) throws LockedException, VerificationFailedException, NotActivatedException, SignatureCardException { } + @Override + public void activatePIN(PINSpec pinSpec, String pin) throws SignatureCardException { + } } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java index a88593bc..3c2273b9 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java @@ -125,21 +125,20 @@ public interface SignatureCard { /** * + * @param pinSpec descriptor which pin to verify * @param pin may be null to test the PIN status - * @param kid * @return the number of remaining retries or -1 * @throws at.gv.egiz.smcc.LockedException * @throws at.gv.egiz.smcc.NotActivatedException * @throws at.gv.egiz.smcc.SignatureCardException */ - public int verifyPIN(String pin, byte kid) throws LockedException, NotActivatedException, SignatureCardException; + public int verifyPIN(PINSpec pinSpec, String pin) + throws LockedException, NotActivatedException, SignatureCardException; - public void changePIN(byte kid, byte[] contextAID, - String oldPIN, String newPIN) - throws SignatureCardException, VerificationFailedException; + public void changePIN(PINSpec pinSpec, String oldPIN, String newPIN) + throws LockedException, VerificationFailedException, NotActivatedException, SignatureCardException; - public void activatePIN(byte kid, byte[] contextAID, - String pin) + public void activatePIN(PINSpec pinSpec, String pin) throws SignatureCardException; /** |