From 2a1df5e58e44f8d77f34eb80df74e8c0d27caceb Mon Sep 17 00:00:00 2001 From: clemenso Date: Wed, 18 Mar 2009 22:27:28 +0000 Subject: 1.1-rc5 (pinProviderFactories, gui refactoring, signatureCard, secureViewer) git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@322 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../src/main/java/at/gv/egiz/smcc/STARCOSCard.java | 479 +++++++++++++-------- 1 file changed, 307 insertions(+), 172 deletions(-) (limited to 'smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java') 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 3c5f38a2..91245c50 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java @@ -30,7 +30,6 @@ package at.gv.egiz.smcc; import at.gv.egiz.smcc.util.SMCCHelper; import java.util.Arrays; -import javax.smartcardio.Card; import javax.smartcardio.CardChannel; import javax.smartcardio.CardException; import javax.smartcardio.CommandAPDU; @@ -223,15 +222,12 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard //new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("card.pin.name")); int retries = -1; - String pin = null; + char[] pin = null; boolean pinRequiered = false; do { if (pinRequiered) { pin = provider.providePIN(spec, retries); - if (pin == null) { - throw new CancelledException(); - } } try { getCard().beginExclusive(); @@ -240,7 +236,7 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard throw new NotActivatedException(); } catch (SecurityStatusNotSatisfiedException e) { pinRequiered = true; - retries = verifyPIN(null, KID_PIN_CARD); + retries = verifyPIN(KID_PIN_CARD); } catch (VerificationFailedException e) { pinRequiered = true; retries = e.getRetries(); @@ -316,20 +312,17 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard //new PINSpec(6, 10, "[0-9]", getResourceBundle().getString("sig.pin.name")); int retries = -1; - String pin = null; + char[] pin = null; do { try { getCard().beginExclusive(); selectFileAID(AID_DF_SS); - retries = verifyPIN(null, KID_PIN_SS); + retries = verifyPIN(KID_PIN_SS); //, null); } finally { getCard().endExclusive(); } pin = provider.providePIN(spec, retries); - if (pin == null) { - throw new CancelledException(); - } try { getCard().beginExclusive(); return createSignature(hash, AID_DF_SS, pin, KID_PIN_SS, DST_SS); @@ -349,15 +342,12 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard //new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("card.pin.name")); int retries = -1; - String pin = null; + char[] pin = null; boolean pinRequiered = false; do { if (pinRequiered) { pin = provider.providePIN(spec, retries); - if (pin == null) { - throw new CancelledException(); - } } try { getCard().beginExclusive(); @@ -366,7 +356,7 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard throw new NotActivatedException(); } catch (SecurityStatusNotSatisfiedException e) { pinRequiered = true; - retries = verifyPIN(null, KID_PIN_CARD); + retries = verifyPIN(KID_PIN_CARD); } catch (VerificationFailedException e) { pinRequiered = true; retries = e.getRetries(); @@ -389,13 +379,18 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard } + + //////////////////////////////////////////////////////////////////////// + // PROTECTED METHODS (assume exclusive card access) + //////////////////////////////////////////////////////////////////////// + protected ResponseAPDU selectFileFID(byte[] fid) throws CardException, SignatureCardException { CardChannel channel = getCardChannel(); return transmit(channel, new CommandAPDU(0x00, 0xA4, 0x02, 0x04, fid, 256)); } - private byte[] createSignature(byte[] hash, byte[] aid, String pin, byte kid, + private byte[] createSignature(byte[] hash, byte[] aid, char[] pin, byte kid, byte[] dst) throws CardException, SignatureCardException { // SELECT MF @@ -403,7 +398,7 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard // SELECT DF selectFileAID(aid); // VERIFY - int retries = verifyPIN(pin, kid); + int retries = verifyPIN(kid, pin); if (retries != -1) { throw new VerificationFailedException(retries); } @@ -417,7 +412,6 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard } - private void selectMF() throws CardException, SignatureCardException { CardChannel channel = getCardChannel(); ResponseAPDU resp = transmit(channel, new CommandAPDU(0x00, 0xA4, 0x00, @@ -467,58 +461,85 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard } } - /** - * VERIFY PIN - *

- * If pin is null only the PIN status is checked and - * returned. - *

- * - * @param pin - * the PIN (may be null) - * @param kid - * the KID of the PIN to be verified - * - * @return -1 if VERIFY PIN was successful, or the number of possible retries - * - * @throws LockedException - * if the pin is locked - * @throws NotActivatedException - * if the card application has not been activated - * @throws SignatureCardException - * if VERIFY PIN fails for some other reason (card communication error) - */ @Override - public int verifyPIN(String pin, byte kid) throws LockedException, NotActivatedException, SignatureCardException { + protected int verifyPIN(byte kid, char[] pin) + throws LockedException, NotActivatedException, SignatureCardException { try { - CardChannel channel = getCardChannel(); - - ResponseAPDU resp; - if (pin == null) { - resp = transmit(channel, new CommandAPDU(0x00, 0x20, 0x00, kid)); + byte[] sw; + if (ifdSupportsFeature(FEATURE_VERIFY_PIN_DIRECT)) { + log.debug("verify PIN on IFD"); + sw = transmitControlCommand( + ifdCtrlCmds.get(FEATURE_VERIFY_PIN_DIRECT), + getPINVerifyStructure(kid)); +// int sw = (resp[resp.length-2] & 0xff) << 8 | resp[resp.length-1] & 0xff; } else { - // BCD encode PIN and marshal PIN block byte[] pinBlock = encodePINBlock(pin); - resp = transmit(channel, new CommandAPDU(0x00, 0x20, 0x00, kid, pinBlock), false); + CardChannel channel = getCardChannel(); + ResponseAPDU resp = transmit(channel, + new CommandAPDU(0x00, 0x20, 0x00, kid, pinBlock), false); + sw = new byte[2]; + sw[0] = (byte) resp.getSW1(); + sw[1] = (byte) resp.getSW2(); + } + if (sw[0] == (byte) 0x90 && sw[1] == (byte) 0x00) { + return -1; + } else if (sw[0] == (byte) 0x63 && sw[1] == (byte) 0xc0) { + throw new LockedException("[63:c0]"); + } else if (sw[0] == (byte) 0x63 && (sw[1] & 0xf0) >> 4 == 0xc) { + return sw[1] & 0x0f; + } else if (sw[0] == (byte) 0x69 && sw[1] == (byte) 0x83) { + //Authentisierungsmethode gesperrt + throw new LockedException("[69:83]"); + } else if (sw[0] == (byte) 0x69 && sw[1] == (byte) 0x84) { + //referenzierte Daten sind reversibel gesperrt (invalidated) + throw new NotActivatedException("[69:84]"); + } else if (sw[0] == (byte) 0x69 && sw[1] == (byte) 0x85) { + //Benutzungsbedingungen nicht erfüllt + throw new NotActivatedException("[69:85]"); + } else if (sw[0] == (byte) 0x64 && sw[1] == (byte) 0x00) { + throw new TimeoutException("[64:00]"); + } else if (sw[0] == (byte) 0x64 && sw[1] == (byte) 0x01) { + throw new CancelledException("[64:01]"); } + log.error("Failed to verify pin: SW=" + + SMCCHelper.toString(sw)); + throw new SignatureCardException(SMCCHelper.toString(sw)); + + } catch (CardException ex) { + log.error("smart card communication failed: " + ex.getMessage()); + throw new SignatureCardException("smart card communication failed: " + ex.getMessage(), ex); + } + } - if (resp.getSW() == 0x63c0) { - throw new LockedException("PIN locked."); - } else if (resp.getSW1() == 0x63 && resp.getSW2() >> 4 == 0xc) { - // return number of possible retries + @Override + protected int verifyPIN(byte kid) + throws LockedException, NotActivatedException, SignatureCardException { + try { + CardChannel channel = getCardChannel(); + ResponseAPDU resp = transmit(channel, + new CommandAPDU(0x00, 0x20, 0x00, kid), false); + + if (resp.getSW() == 0x9000) { + return -1; + } else if (resp.getSW() == 0x63c0) { + throw new LockedException("[63:c0]"); + } else if (resp.getSW1() == 0x63 && (resp.getSW2() & 0xf0) >> 4 == 0xc) { return resp.getSW2() & 0x0f; } else if (resp.getSW() == 0x6983) { - throw new LockedException(); + //Authentisierungsmethode gesperrt + throw new LockedException("[69:83]"); } else if (resp.getSW() == 0x6984) { - // PIN LCS = "Initialized" (-> not activated) - throw new NotActivatedException(); - } else if (resp.getSW() == 0x9000) { - return -1; // success - } else { - throw new SignatureCardException("Failed to verify pin: SW=" - + Integer.toHexString(resp.getSW())); + //referenzierte Daten sind reversibel gesperrt (invalidated) + throw new NotActivatedException("[69:84]"); + } else if (resp.getSW() == 0x6985) { + //Benutzungsbedingungen nicht erfüllt + throw new NotActivatedException("[69:85]"); } + log.error("Failed to verify pin: SW=" + + Integer.toHexString(resp.getSW())); + throw new SignatureCardException("[" + Integer.toHexString(resp.getSW()) + "]"); + } catch (CardException ex) { log.error("smart card communication failed: " + ex.getMessage()); throw new SignatureCardException("smart card communication failed: " + ex.getMessage(), ex); @@ -526,24 +547,95 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard } @Override - public void reset() throws SignatureCardException { + protected int changePIN(byte kid, char[] oldPin, char[] newPin) + throws LockedException, NotActivatedException, CancelledException, TimeoutException, SignatureCardException { try { - super.reset(); - log.debug("select MF (e-card workaround)"); - CardChannel channel = getCardChannel(); - ResponseAPDU resp = transmit(channel, new CommandAPDU(0x00, 0xA4, 0x00, 0x0C)); - if (resp.getSW() != 0x9000) { - throw new SignatureCardException("Failed to select MF after RESET: SW=" + Integer.toHexString(resp.getSW()) + "."); + byte[] sw; + if (ifdSupportsFeature(FEATURE_MODIFY_PIN_DIRECT)) { + log.debug("modify PIN on IFD"); + sw = transmitControlCommand( + ifdCtrlCmds.get(FEATURE_MODIFY_PIN_DIRECT), + getPINModifyStructure(kid)); +// int sw = (resp[resp.length-2] & 0xff) << 8 | resp[resp.length-1] & 0xff; + } else { + byte[] cmd = new byte[16]; + System.arraycopy(encodePINBlock(oldPin), 0, cmd, 0, 8); + System.arraycopy(encodePINBlock(newPin), 0, cmd, 8, 8); + + CardChannel channel = getCardChannel(); + + ResponseAPDU resp = transmit(channel, + new CommandAPDU(0x00, 0x24, 0x00, kid, cmd), false); + + sw = new byte[2]; + sw[0] = (byte) resp.getSW1(); + sw[1] = (byte) resp.getSW2(); + } + + // activates pin (newPIN) if not active + if (sw[0] == (byte) 0x90 && sw[1] == (byte) 0x00) { + return -1; + } else if (sw[0] == (byte) 0x63 && sw[1] == (byte) 0xc0) { + throw new LockedException("[63:c0]"); + } else if (sw[0] == (byte) 0x63 && (sw[1] & 0xf0) >> 4 == 0xc) { + return sw[1] & 0x0f; + } else if (sw[0] == (byte) 0x69 && sw[1] == (byte) 0x83) { + //Authentisierungsmethode gesperrt + throw new LockedException("[69:83]"); +// } else if (sw[0] == (byte) 0x69 && sw[1] == (byte) 0x84) { +// //referenzierte Daten sind reversibel gesperrt (invalidated) +// throw new NotActivatedException("[69:84]"); +// } else if (sw[0] == (byte) 0x69 && sw[1] == (byte) 0x85) { +// //Benutzungsbedingungen nicht erfüllt +// throw new NotActivatedException("[69:85]"); + } else if (sw[0] == (byte) 0x64 && sw[1] == (byte) 0x00) { + throw new TimeoutException("[64:00]"); + } else if (sw[0] == (byte) 0x64 && sw[1] == (byte) 0x01) { + throw new CancelledException("[64:01]"); } + log.error("Failed to change pin: SW=" + + SMCCHelper.toString(sw)); + throw new SignatureCardException(SMCCHelper.toString(sw)); } catch (CardException ex) { - log.error("Failed to select MF after RESET: " + ex.getMessage(), ex); - throw new SignatureCardException("Failed to select MF after RESET"); + log.error("smart card communication failed: " + ex.getMessage()); + throw new SignatureCardException("smart card communication failed: " + ex.getMessage(), ex); } } + @Override + protected void activatePIN(byte kid, char[] pin) + throws CancelledException, TimeoutException, SignatureCardException { + try { + CardChannel channel = getCardChannel(); + ResponseAPDU resp = transmit(channel, + new CommandAPDU(0x00, 0x24, 0x01, kid, encodePINBlock(pin)), false); + + log.trace("activate pin returned SW=" + Integer.toHexString(resp.getSW())); - public String toString() { - return "e-card"; + if (resp.getSW1() == 0x9000) { + return; + } else if (resp.getSW() == 0x6983) { + //Authentisierungsmethode gesperrt + throw new LockedException("[69:83]"); + } else if (resp.getSW() == 0x6984) { + //referenzierte Daten sind reversibel gesperrt (invalidated) + throw new NotActivatedException("[69:84]"); + } else if (resp.getSW() == 0x6985) { + //Benutzungsbedingungen nicht erfüllt + throw new NotActivatedException("[69:85]"); + } else if (resp.getSW() == 0x6400) { + throw new TimeoutException("[64:00]"); + } else if (resp.getSW() == 0x6401) { + throw new CancelledException("[64:01]"); + } + log.error("Failed to activate pin: SW=" + + Integer.toHexString(resp.getSW())); + throw new SignatureCardException("[" + Integer.toHexString(resp.getSW()) + "]"); + + } catch (CardException ex) { + log.error("smart card communication failed: " + ex.getMessage()); + throw new SignatureCardException("smart card communication failed: " + ex.getMessage(), ex); + } } /** @@ -552,17 +644,20 @@ 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 */ - private byte[] encodePINBlock(String pin) { - char[] pinChars = pin.toCharArray(); - int numDigits = pinChars.length; + @Override + protected byte[] encodePINBlock(char[] pin) throws SignatureCardException { + if (pin == null || pin.length > 12) { + throw new SignatureCardException("invalid pin: " + pin); + } + int numDigits = pin.length; int numBytes = (int) Math.ceil(numDigits/2.0); byte[] pinBlock = new byte[8]; pinBlock[0] = (byte) (0x20 | numDigits); for (int i = 0; i < numBytes; i++) { - int p1 = 16*Character.digit(pinChars[i*2], 16); - int p2 = (i*2+1 < numDigits) ? Character.digit(pinChars[i*2+1], 16) : 0xf; + int p1 = 16*Character.digit(pin[i*2], 16); + int p2 = (i*2+1 < numDigits) ? Character.digit(pin[i*2+1], 16) : 0xf; pinBlock[i+1] = (byte) (p1 + p2); } Arrays.fill(pinBlock, numBytes + 1, pinBlock.length, (byte) 0xff); @@ -570,111 +665,151 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard return pinBlock; } + + private byte[] getPINVerifyStructure(byte kid) { + + byte bTimeOut = (byte) 00; // Default time out + byte bTimeOut2 = (byte) 00; // Default time out + byte bmFormatString = (byte) 0x89; // 1 0001 0 01 + // ^------------ System unit = byte + // ^^^^------- PIN position in the frame = 1 byte + // ^----- PIN justification left + // ^^-- BCD format + byte bmPINBlockString = (byte) 0x47; // 0100 0111 + // ^^^^--------- PIN length size: 4 bits + // ^^^^---- Length PIN = 7 bytes + byte bmPINLengthFormat = (byte) 0x04; // 000 0 0100 + // ^-------- System bit units is bit + // ^^^^--- PIN length is at the 4th position bit + byte wPINMaxExtraDigitL = (byte) 0x04; // Max=4 digits + byte wPINMaxExtraDigitH = (byte) 0x04; // Min=4 digits + byte bEntryValidationCondition = 0x02; // Max size reach or Validation key pressed + byte bNumberMessage = (byte) 0x00; // No message + byte wLangIdL = (byte) 0x0C; // - English? + byte wLangIdH = (byte) 0x04; // \ + byte bMsgIndex = (byte) 0x00; // Default Msg + + byte[] apdu = new byte[] { + (byte) 0x00, (byte) 0x20, (byte) 0x00, kid, (byte) 0x08, // CLA INS P1 P2 LC + (byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, // Data + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff // ... + }; + + int offset = 0; + byte[] pinVerifyStructure = new byte[offset + 19 + apdu.length]; + pinVerifyStructure[offset++] = bTimeOut; + pinVerifyStructure[offset++] = bTimeOut2; + pinVerifyStructure[offset++] = bmFormatString; + pinVerifyStructure[offset++] = bmPINBlockString; + pinVerifyStructure[offset++] = bmPINLengthFormat; + pinVerifyStructure[offset++] = wPINMaxExtraDigitL; + pinVerifyStructure[offset++] = wPINMaxExtraDigitH; + pinVerifyStructure[offset++] = bEntryValidationCondition; + pinVerifyStructure[offset++] = bNumberMessage; + pinVerifyStructure[offset++] = wLangIdL; + pinVerifyStructure[offset++] = wLangIdH; + pinVerifyStructure[offset++] = bMsgIndex; + + pinVerifyStructure[offset++] = 0x00; + pinVerifyStructure[offset++] = 0x00; + pinVerifyStructure[offset++] = 0x00; + + pinVerifyStructure[offset++] = (byte) apdu.length; + pinVerifyStructure[offset++] = 0x00; + pinVerifyStructure[offset++] = 0x00; + pinVerifyStructure[offset++] = 0x00; + System.arraycopy(apdu, 0, pinVerifyStructure, offset, apdu.length); - @Override - public void activatePIN(PINSpec pinSpec, String pin) - throws 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); - } - } - - ResponseAPDU responseAPDU = transmit(channel, - new CommandAPDU(0x00, 0x24, 0x01, pinSpec.getKID(), encodePINBlock(pin)), - false); - - icc.endExclusive(); - - log.debug("activate pin returned SW=" + Integer.toHexString(responseAPDU.getSW())); + return pinVerifyStructure; + } - 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); - } + private byte[] getPINModifyStructure(byte kid) { + + byte bTimeOut = (byte) 00; // Default time out + byte bTimeOut2 = (byte) 00; // Default time out + byte bmFormatString = (byte) 0x89; // 1 0001 0 01 + // ^------------ System unit = byte + // ^^^^------- PIN position in the frame = 1 byte + // ^----- PIN justification left + // ^^-- BCD format + byte bmPINBlockString = (byte) 0x47; // 0100 0111 + // ^^^^--------- PIN length size: 4 bits + // ^^^^---- Length PIN = 7 bytes + byte bmPINLengthFormat = (byte) 0x04; // 000 0 0100 + // ^-------- System bit units is bit + // ^^^^--- PIN length is at the 4th position bit + byte bInsertionOffsetOld = (byte) 0x01; // insertion position offset in bytes + byte bInsertionOffsetNew = (byte) 0x08; // insertion position offset in bytes + byte wPINMaxExtraDigitL = (byte) 0x04; // Min=4 digits + byte wPINMaxExtraDigitH = (byte) 0x04; // Max=12 digits + byte bConfirmPIN = (byte) 0x00; // ??? need for confirm pin + byte bEntryValidationCondition = 0x02; // Max size reach or Validation key pressed + byte bNumberMessage = (byte) 0x00; // No message + byte wLangIdL = (byte) 0x0C; // - English? + byte wLangIdH = (byte) 0x04; // \ + byte bMsgIndex1 = (byte) 0x00; // Default Msg + byte bMsgIndex2 = (byte) 0x00; // Default Msg + byte bMsgIndex3 = (byte) 0x00; // Default Msg + + byte[] apdu = new byte[] { + (byte) 0x00, (byte) 0x24, (byte) 0x00, kid, (byte) 0x10, // CLA INS P1 P2 LC + (byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, // Data + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, // ... + (byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, // Data + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff // ... + }; + + int offset = 0; + byte[] pinModifyStructure = new byte[offset + 24 + apdu.length]; + pinModifyStructure[offset++] = bTimeOut; + pinModifyStructure[offset++] = bTimeOut2; + pinModifyStructure[offset++] = bmFormatString; + pinModifyStructure[offset++] = bmPINBlockString; + pinModifyStructure[offset++] = bmPINLengthFormat; + pinModifyStructure[offset++] = bInsertionOffsetOld; + pinModifyStructure[offset++] = bInsertionOffsetNew; + pinModifyStructure[offset++] = wPINMaxExtraDigitL; + pinModifyStructure[offset++] = wPINMaxExtraDigitH; + pinModifyStructure[offset++] = bConfirmPIN; + pinModifyStructure[offset++] = bEntryValidationCondition; + pinModifyStructure[offset++] = bNumberMessage; + pinModifyStructure[offset++] = wLangIdL; + pinModifyStructure[offset++] = wLangIdH; + pinModifyStructure[offset++] = bMsgIndex1; + pinModifyStructure[offset++] = bMsgIndex2; + pinModifyStructure[offset++] = bMsgIndex3; + + pinModifyStructure[offset++] = 0x00; + pinModifyStructure[offset++] = 0x00; + pinModifyStructure[offset++] = 0x00; + + pinModifyStructure[offset++] = (byte) apdu.length; + pinModifyStructure[offset++] = 0x00; + pinModifyStructure[offset++] = 0x00; + pinModifyStructure[offset++] = 0x00; + System.arraycopy(apdu, 0, pinModifyStructure, offset, apdu.length); + +// log.debug("PIN MODIFY " + SMCCHelper.toString(pinModifyStructure)); + return pinModifyStructure; } - /** - * 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(); + public void reset() throws SignatureCardException { 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); + super.reset(); + log.debug("select MF (e-card workaround)"); + CardChannel channel = getCardChannel(); + ResponseAPDU resp = transmit(channel, new CommandAPDU(0x00, 0xA4, 0x00, 0x0C)); + if (resp.getSW() != 0x9000) { + throw new SignatureCardException("Failed to select MF after RESET: SW=" + Integer.toHexString(resp.getSW()) + "."); } } catch (CardException ex) { - log.error("Failed to change " + pinSpec.getLocalizedName() + - ": " + ex.getMessage()); - throw new SignatureCardException(ex.getMessage(), ex); + log.error("Failed to select MF after RESET: " + ex.getMessage(), ex); + throw new SignatureCardException("Failed to select MF after RESET"); } } + public String toString() { + return "e-card"; + } } -- cgit v1.2.3