diff options
25 files changed, 1174 insertions, 750 deletions
diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java index f0cc0a27..848cd17f 100644 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java @@ -62,6 +62,9 @@ public interface PINManagementGUIFacade extends BKUGUIFacade { public static final String ERR_RETRIES = "err.retries"; public static final String ERR_LOCKED = "err.locked"; public static final String ERR_NOT_ACTIVE = "err.not.active"; + public static final String ERR_PIN_FORMAT = "err.pin.format"; + public static final String ERR_PIN_CONFIRMATION = "err.pin.confirmation"; + public static final String ERR_PIN_OPERATION_ABORTED = "err.pin.operation.aborted"; public static final String BUTTON_ACTIVATE = "button.activate"; public static final String BUTTON_UNBLOCK = "button.unblock"; diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/ManagementPINProviderFactory.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/ManagementPINProviderFactory.java index d635b8df..090caf50 100644 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/ManagementPINProviderFactory.java +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/ManagementPINProviderFactory.java @@ -17,38 +17,242 @@ package at.gv.egiz.bku.smccstal.ext; +import at.gv.egiz.bku.gui.BKUGUIFacade; import at.gv.egiz.smcc.ChangePINProvider; import at.gv.egiz.bku.gui.PINManagementGUIFacade; +import at.gv.egiz.bku.smccstal.AbstractPINProvider; +import at.gv.egiz.bku.smccstal.PINProviderFactory; +import at.gv.egiz.smcc.CancelledException; import at.gv.egiz.smcc.ccid.CCID; import at.gv.egiz.smcc.PINProvider; +import at.gv.egiz.smcc.PINSpec; import at.gv.egiz.smcc.SignatureCard; /** * * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at> */ -public abstract class ManagementPINProviderFactory { -// extends at.gv.egiz.bku.smccstal.PINProviderFactory { +public class ManagementPINProviderFactory extends PINProviderFactory { - PINManagementGUIFacade gui; + public ManagementPINProviderFactory(CCID reader, PINManagementGUIFacade gui) { + super(reader, gui); + } - public static ManagementPINProviderFactory getInstance(SignatureCard forCard, - PINManagementGUIFacade gui) { - if (forCard.getReader().hasFeature(CCID.FEATURE_VERIFY_PIN_DIRECT)) { -// forCard.ifdSupportsFeature(SignatureCard.FEATURE_MODIFY_PIN_DIRECT) - return new PinpadPINProviderFactory(gui); +// public static ManagementPINProviderFactory getInstance(SignatureCard forCard, +// PINManagementGUIFacade gui) { +// if (forCard.getReader().hasFeature(CCID.FEATURE_VERIFY_PIN_DIRECT)) { +// return new PinpadPINProviderFactory(gui); +// +// } else { +// return new SoftwarePINProviderFactory(gui); +// } +// } + + public PINProvider getVerifyPINProvider() { + if (reader.hasFeature(CCID.FEATURE_VERIFY_PIN_START)) { + return new PinpadGenericPinProvider(PINManagementGUIFacade.DIALOG.VERIFY); + } else if (reader.hasFeature(CCID.FEATURE_VERIFY_PIN_DIRECT)) { + return new PinpadGenericPinProvider(PINManagementGUIFacade.DIALOG.VERIFY); + } else { + return new SoftwareGenericPinProvider(PINManagementGUIFacade.DIALOG.VERIFY); + } + } + + public PINProvider getActivatePINProvider() { + if (reader.hasFeature(CCID.FEATURE_MODIFY_PIN_START)) { + return new PinpadGenericPinProvider(PINManagementGUIFacade.DIALOG.ACTIVATE); + } else if (reader.hasFeature(CCID.FEATURE_MODIFY_PIN_DIRECT)) { + return new PinpadGenericPinProvider(PINManagementGUIFacade.DIALOG.ACTIVATE); + } else { + return new SoftwareGenericPinProvider(PINManagementGUIFacade.DIALOG.ACTIVATE); + } + } + public ChangePINProvider getChangePINProvider() { + if (reader.hasFeature(CCID.FEATURE_MODIFY_PIN_START)) { + return new PinpadGenericPinProvider(PINManagementGUIFacade.DIALOG.CHANGE); + } else if (reader.hasFeature(CCID.FEATURE_MODIFY_PIN_DIRECT)) { + return new PinpadGenericPinProvider(PINManagementGUIFacade.DIALOG.CHANGE); } else { - return new SoftwarePINProviderFactory(gui); + return new ChangePinProvider(); + } + } + + public PINProvider getUnblockPINProvider() { + if (reader.hasFeature(CCID.FEATURE_VERIFY_PIN_START)) { + return new PinpadGenericPinProvider(PINManagementGUIFacade.DIALOG.UNBLOCK); + } else if (reader.hasFeature(CCID.FEATURE_VERIFY_PIN_DIRECT)) { + return new PinpadGenericPinProvider(PINManagementGUIFacade.DIALOG.UNBLOCK); + } else { + return new SoftwareGenericPinProvider(PINManagementGUIFacade.DIALOG.UNBLOCK); + } + } + + class PinpadGenericPinProvider extends AbstractPINProvider + implements ChangePINProvider { + + protected PINManagementGUIFacade.DIALOG type; + + private PinpadGenericPinProvider(PINManagementGUIFacade.DIALOG type) { + this.type = type; + } + + @Override + public char[] providePIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException { + + showPinpadPINDialog(retries, spec); + retry = true; + return null; + } + + /** + * do not call this method without calling providePIN() + * (no message is displayed) + * @param spec + * @param retries + * @return + */ + @Override + public char[] provideOldPIN(PINSpec spec, int retries) { + return null; + } + + private void showPinpadPINDialog(int retries, PINSpec pinSpec) { + String title, message; + Object[] params; + if (retry) { + title = BKUGUIFacade.TITLE_RETRY; + message = BKUGUIFacade.MESSAGE_RETRIES; + params = new Object[]{String.valueOf(retries)}; + } else if (type == PINManagementGUIFacade.DIALOG.VERIFY) { + title = PINManagementGUIFacade.TITLE_VERIFY_PIN; + message = BKUGUIFacade.MESSAGE_ENTERPIN_PINPAD; + String pinSize = String.valueOf(pinSpec.getMinLength()); + if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { + pinSize += "-" + pinSpec.getMaxLength(); + } + params = new Object[]{pinSpec.getLocalizedName(), pinSize}; + } else if (type == PINManagementGUIFacade.DIALOG.ACTIVATE) { + title = PINManagementGUIFacade.TITLE_ACTIVATE_PIN; + message = PINManagementGUIFacade.MESSAGE_ACTIVATEPIN_PINPAD; + String pinSize = String.valueOf(pinSpec.getMinLength()); + if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { + pinSize += "-" + pinSpec.getMaxLength(); + } + params = new Object[]{pinSpec.getLocalizedName(), pinSize}; + } else if (type == PINManagementGUIFacade.DIALOG.CHANGE) { + title = PINManagementGUIFacade.TITLE_CHANGE_PIN; + message = PINManagementGUIFacade.MESSAGE_CHANGEPIN_PINPAD; + String pinSize = String.valueOf(pinSpec.getMinLength()); + if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { + pinSize += "-" + pinSpec.getMaxLength(); + } + params = new Object[]{pinSpec.getLocalizedName(), pinSize}; + } else { //if (type == DIALOG.UNBLOCK) { + title = PINManagementGUIFacade.TITLE_UNBLOCK_PIN; + message = PINManagementGUIFacade.MESSAGE_UNBLOCKPIN_PINPAD; + String pinSize = String.valueOf(pinSpec.getMinLength()); + if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { + pinSize += "-" + pinSpec.getMaxLength(); + } + params = new Object[]{pinSpec.getLocalizedName(), pinSize}; + } + gui.showMessageDialog(title, message, params); } } - public abstract PINProvider getVerifyPINProvider(); - public abstract PINProvider getActivatePINProvider(); + class SoftwareGenericPinProvider extends AbstractPINProvider { + +// protected PINManagementGUIFacade gui; + protected PINManagementGUIFacade.DIALOG type; + + private SoftwareGenericPinProvider(PINManagementGUIFacade.DIALOG type) { + this.type = type; + } + + @Override + public char[] providePIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException { + + ((PINManagementGUIFacade) gui).showPINDialog(type, spec, + (retry) ? retries : -1, + this, "exec", + this, "back"); + + waitForAction(); + + if ("exec".equals(action)) { + gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, + BKUGUIFacade.MESSAGE_WAIT); + retry = true; + return gui.getPin(); + } else if ("back".equals(action)) { + throw new CancelledException(); + } else { + log.error("unsupported command " + action); + throw new CancelledException(); + } + } + } + + class ChangePinProvider extends AbstractPINProvider + implements ChangePINProvider { - public abstract ChangePINProvider getChangePINProvider(); +// protected PINManagementGUIFacade gui; - public abstract PINProvider getUnblockPINProvider(); + private char[] oldPin; + private char[] newPin; + private ChangePinProvider() { + } + + @Override + public char[] providePIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException { + if (newPin == null) { + getPINs(spec, retries); + } + char[] pin = newPin; + newPin = null; + return pin; + } + + @Override + public char[] provideOldPIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException { + if (oldPin == null) { + getPINs(spec, retries); + } + char[] pin = oldPin; + oldPin = null; + return pin; + } + + private void getPINs(PINSpec spec, int retries) + throws InterruptedException, CancelledException { + + ((PINManagementGUIFacade) gui).showPINDialog( + PINManagementGUIFacade.DIALOG.CHANGE, spec, + (retry) ? retries : -1, + this, "exec", + this, "back"); + + waitForAction(); + + if ("exec".equals(action)) { + gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, + BKUGUIFacade.MESSAGE_WAIT); + retry = true; + oldPin = ((PINManagementGUIFacade) gui).getOldPin(); + newPin = gui.getPin(); + } else if ("back".equals(action)) { + throw new CancelledException(); + } else { + log.error("unsupported command " + action); + throw new CancelledException(); + } + } + } } diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PINManagementRequestHandler.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PINManagementRequestHandler.java index 6b565b26..72a7c4cc 100644 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PINManagementRequestHandler.java +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PINManagementRequestHandler.java @@ -25,6 +25,9 @@ import at.gv.egiz.bku.smccstal.PINProviderFactory; import at.gv.egiz.smcc.CancelledException; import at.gv.egiz.smcc.LockedException; import at.gv.egiz.smcc.NotActivatedException; +import at.gv.egiz.smcc.PINConfirmationException; +import at.gv.egiz.smcc.PINFormatException; +import at.gv.egiz.smcc.PINOperationAbortedException; import at.gv.egiz.smcc.PINProvider; import at.gv.egiz.smcc.PINSpec; import at.gv.egiz.smcc.STARCOSCard; @@ -58,7 +61,6 @@ public class PINManagementRequestHandler extends AbstractRequestHandler { protected static final Log log = LogFactory.getLog(PINManagementRequestHandler.class); protected Map<PINSpec, STATUS> pinStatuses; - private ManagementPINProviderFactory pinProviderFactory; @Override public STALResponse handleRequest(STALRequest request) throws InterruptedException { @@ -89,16 +91,14 @@ public class PINManagementRequestHandler extends AbstractRequestHandler { throw new NullPointerException("no PIN selected for activation/change"); } - if (pinProviderFactory == null) { - pinProviderFactory = - ManagementPINProviderFactory.getInstance(card, gui); - } + ManagementPINProviderFactory ppfac = + new ManagementPINProviderFactory(card.getReader(), gui); try { if ("activate_enterpin".equals(actionCommand)) { log.info("activate " + selectedPIN.getLocalizedName()); - card.activatePIN(selectedPIN, - pinProviderFactory.getActivatePINProvider()); + card.activatePIN(selectedPIN, + ppfac.getActivatePINProvider()); updatePINStatus(selectedPIN, STATUS.ACTIV); gui.showMessageDialog(PINManagementGUIFacade.TITLE_ACTIVATE_SUCCESS, PINManagementGUIFacade.MESSAGE_ACTIVATE_SUCCESS, @@ -108,7 +108,7 @@ public class PINManagementRequestHandler extends AbstractRequestHandler { } else if ("change_enterpin".equals(actionCommand)) { log.info("change " + selectedPIN.getLocalizedName()); card.changePIN(selectedPIN, - pinProviderFactory.getChangePINProvider()); + ppfac.getChangePINProvider()); updatePINStatus(selectedPIN, STATUS.ACTIV); gui.showMessageDialog(PINManagementGUIFacade.TITLE_CHANGE_SUCCESS, PINManagementGUIFacade.MESSAGE_CHANGE_SUCCESS, @@ -119,11 +119,11 @@ public class PINManagementRequestHandler extends AbstractRequestHandler { } else if ("unblock_enterpuk".equals(actionCommand)) { log.info("unblock " + selectedPIN.getLocalizedName()); card.unblockPIN(selectedPIN, - pinProviderFactory.getUnblockPINProvider()); + ppfac.getUnblockPINProvider()); } else if ("verify_enterpin".equals(actionCommand)) { log.info("verify " + selectedPIN.getLocalizedName()); card.verifyPIN(selectedPIN, - pinProviderFactory.getVerifyPINProvider()); + ppfac.getVerifyPINProvider()); updatePINStatus(selectedPIN, STATUS.ACTIV); } } catch (CancelledException ex) { @@ -149,6 +149,29 @@ public class PINManagementRequestHandler extends AbstractRequestHandler { new Object[] {selectedPIN.getLocalizedName()}, this, null); waitForAction(); + } catch (PINConfirmationException ex) { + log.error("confirmation pin does not match new " + selectedPIN.getLocalizedName()); + gui.showErrorDialog(PINManagementGUIFacade.ERR_PIN_CONFIRMATION, + new Object[] {selectedPIN.getLocalizedName()}, + this, null); + waitForAction(); + } catch (PINOperationAbortedException ex) { + log.error("pin operation aborted without further details"); + gui.showErrorDialog(PINManagementGUIFacade.ERR_PIN_OPERATION_ABORTED, + new Object[] {selectedPIN.getLocalizedName()}, + this, null); + waitForAction(); + } catch (PINFormatException ex) { + log.error("wrong format of new " + selectedPIN.getLocalizedName()); +// updatePINStatus(selectedPIN, STATUS.NOT_ACTIV); + String pinSize = String.valueOf(selectedPIN.getMinLength()); + if (selectedPIN.getMinLength() != selectedPIN.getMaxLength()) { + pinSize += "-" + selectedPIN.getMaxLength(); + } + gui.showErrorDialog(PINManagementGUIFacade.ERR_PIN_FORMAT, + new Object[] {selectedPIN.getLocalizedName(), pinSize}, + this, null); + waitForAction(); } } // end if diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PinpadPINProviderFactory.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PinpadPINProviderFactory.java deleted file mode 100644 index a9ad5ef8..00000000 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PinpadPINProviderFactory.java +++ /dev/null @@ -1,133 +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.bku.smccstal.ext; - -import at.gv.egiz.smcc.ChangePINProvider; -import at.gv.egiz.bku.gui.BKUGUIFacade; -import at.gv.egiz.bku.gui.PINManagementGUIFacade; -import at.gv.egiz.bku.gui.PINManagementGUIFacade.DIALOG; -import at.gv.egiz.bku.smccstal.AbstractPINProvider; -import at.gv.egiz.smcc.CancelledException; -import at.gv.egiz.smcc.PINProvider; -import at.gv.egiz.smcc.PINSpec; - -/** - * - * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at> - */ -public class PinpadPINProviderFactory extends ManagementPINProviderFactory { - - protected PinpadPINProviderFactory(PINManagementGUIFacade gui) { - this.gui = gui; - } - - @Override - public PINProvider getVerifyPINProvider() { - return new SimplePinProvider(DIALOG.VERIFY); - } - - @Override - public PINProvider getActivatePINProvider() { - return new SimplePinProvider(DIALOG.ACTIVATE); - } - - @Override - public ChangePINProvider getChangePINProvider() { - return new SimplePinProvider(DIALOG.CHANGE); - } - - @Override - public PINProvider getUnblockPINProvider() { - return new SimplePinProvider(DIALOG.UNBLOCK); - } - - - class SimplePinProvider extends AbstractPINProvider - implements ChangePINProvider { - -// protected PINManagementGUIFacade gui; - protected PINManagementGUIFacade.DIALOG type; - - private SimplePinProvider(PINManagementGUIFacade.DIALOG type) { - this.type = type; - } - - @Override - public char[] providePIN(PINSpec spec, int retries) - throws CancelledException, InterruptedException { - - showPinpadPINDialog(retries, spec); - retry = true; - return null; - } - - /** - * do not call this method without calling providePIN() - * (no message is displayed) - * @param spec - * @param retries - * @return - */ - @Override - public char[] provideOldPIN(PINSpec spec, int retries) { - return null; - } - - private void showPinpadPINDialog(int retries, PINSpec pinSpec) { - String title, message; - Object[] params; - if (retry) { - title = BKUGUIFacade.TITLE_RETRY; - message = BKUGUIFacade.MESSAGE_RETRIES; - params = new Object[]{String.valueOf(retries)}; - } else if (type == DIALOG.VERIFY) { - title = PINManagementGUIFacade.TITLE_VERIFY_PIN; - message = BKUGUIFacade.MESSAGE_ENTERPIN_PINPAD; - String pinSize = String.valueOf(pinSpec.getMinLength()); - if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { - pinSize += "-" + pinSpec.getMaxLength(); - } - params = new Object[]{pinSpec.getLocalizedName(), pinSize}; - } else if (type == DIALOG.ACTIVATE) { - title = PINManagementGUIFacade.TITLE_ACTIVATE_PIN; - message = PINManagementGUIFacade.MESSAGE_ACTIVATEPIN_PINPAD; - String pinSize = String.valueOf(pinSpec.getMinLength()); - if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { - pinSize += "-" + pinSpec.getMaxLength(); - } - params = new Object[]{pinSpec.getLocalizedName(), pinSize}; - } else if (type == DIALOG.CHANGE) { - title = PINManagementGUIFacade.TITLE_CHANGE_PIN; - message = PINManagementGUIFacade.MESSAGE_CHANGEPIN_PINPAD; - String pinSize = String.valueOf(pinSpec.getMinLength()); - if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { - pinSize += "-" + pinSpec.getMaxLength(); - } - params = new Object[]{pinSpec.getLocalizedName(), pinSize}; - } else { //if (type == DIALOG.UNBLOCK) { - title = PINManagementGUIFacade.TITLE_UNBLOCK_PIN; - message = PINManagementGUIFacade.MESSAGE_UNBLOCKPIN_PINPAD; - String pinSize = String.valueOf(pinSpec.getMinLength()); - if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { - pinSize += "-" + pinSpec.getMaxLength(); - } - params = new Object[]{pinSpec.getLocalizedName(), pinSize}; - } - gui.showMessageDialog(title, message, params); - } - } -} diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/SoftwarePINProviderFactory.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/SoftwarePINProviderFactory.java deleted file mode 100644 index e87512d0..00000000 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/SoftwarePINProviderFactory.java +++ /dev/null @@ -1,148 +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.bku.smccstal.ext; - -import at.gv.egiz.bku.gui.BKUGUIFacade; -import at.gv.egiz.smcc.ChangePINProvider; -import at.gv.egiz.bku.gui.PINManagementGUIFacade; -import at.gv.egiz.bku.gui.PINManagementGUIFacade.DIALOG; -import at.gv.egiz.bku.smccstal.AbstractPINProvider; -import at.gv.egiz.smcc.CancelledException; -import at.gv.egiz.smcc.PINProvider; -import at.gv.egiz.smcc.PINSpec; - -/** - * - * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at> - */ -public class SoftwarePINProviderFactory extends ManagementPINProviderFactory { - - protected SoftwarePINProviderFactory(PINManagementGUIFacade gui) { - this.gui = gui; - } - - @Override - public PINProvider getVerifyPINProvider() { - return new SimplePinProvider(DIALOG.VERIFY); - } - - @Override - public PINProvider getActivatePINProvider() { - return new SimplePinProvider(DIALOG.ACTIVATE); - } - - @Override - public ChangePINProvider getChangePINProvider() { - return new ChangePinProvider(); - } - - @Override - public PINProvider getUnblockPINProvider() { - return new SimplePinProvider(DIALOG.UNBLOCK); - } - - class SimplePinProvider extends AbstractPINProvider { - -// protected PINManagementGUIFacade gui; - protected PINManagementGUIFacade.DIALOG type; - - private SimplePinProvider(DIALOG type) { - this.type = type; - } - - @Override - public char[] providePIN(PINSpec spec, int retries) - throws CancelledException, InterruptedException { - - gui.showPINDialog(type, spec, (retry) ? retries : -1, - this, "exec", - this, "back"); - - waitForAction(); - - if ("exec".equals(action)) { - gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, - BKUGUIFacade.MESSAGE_WAIT); - retry = true; - return gui.getPin(); - } else if ("back".equals(action)) { - throw new CancelledException(); - } else { - log.error("unsupported command " + action); - throw new CancelledException(); - } - } - } - - class ChangePinProvider extends AbstractPINProvider - implements ChangePINProvider { - -// protected PINManagementGUIFacade gui; - - private char[] oldPin; - private char[] newPin; - - private ChangePinProvider() { - } - - @Override - public char[] providePIN(PINSpec spec, int retries) - throws CancelledException, InterruptedException { - if (newPin == null) { - getPINs(spec, retries); - } - char[] pin = newPin; - newPin = null; - return pin; - } - - @Override - public char[] provideOldPIN(PINSpec spec, int retries) - throws CancelledException, InterruptedException { - if (oldPin == null) { - getPINs(spec, retries); - } - char[] pin = oldPin; - oldPin = null; - return pin; - } - - private void getPINs(PINSpec spec, int retries) - throws InterruptedException, CancelledException { - - gui.showPINDialog(PINManagementGUIFacade.DIALOG.CHANGE, spec, - (retry) ? retries : -1, - this, "exec", - this, "back"); - - waitForAction(); - - if ("exec".equals(action)) { - gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, - BKUGUIFacade.MESSAGE_WAIT); - retry = true; - oldPin = gui.getOldPin(); - newPin = gui.getPin(); - } else if ("back".equals(action)) { - throw new CancelledException(); - } else { - log.error("unsupported command " + action); - throw new CancelledException(); - } - } - } -} diff --git a/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties b/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties index c6d219d4..15fc2827 100644 --- a/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties +++ b/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties @@ -55,9 +55,12 @@ err.activate=<html>Beim Aktivieren der {0} trat ein Fehler auf.</html> err.change=<html>Beim \u00C4ndern der {0} trat ein Fehler auf.</html> err.unblock=<html>Das Entsperren der {0} wird nicht unterst\u00FCtzt.</html> err.verify=<html>VERIFY ERROR (TODO)</html> -err.retries=<html>Falscher {0}, noch {1} Versuche</html> +err.retries=<html>Falsche {0}, noch {1} Versuche</html> err.locked=<html>{0} gesperrt.</html> err.not.active=<html>{0} nicht aktiviert.</html> +err.pin.format=<html>Ung\u00FCltige {0} L\u00E4nge, verlangt sind {1} Stellen.</html> +err.pin.confirmation=<html>{0} und Best\u00E4tigung stimmen nicht \u00FCberein.</html> +err.pin.operation.aborted=<html>Der Vorgang f\u00FCr {0} wurde abgebrochen.</html> status.not.active=NICHT AKTIV status.active=AKTIV diff --git a/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties b/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties index b4bededf..8cc9d01a 100644 --- a/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties +++ b/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties @@ -55,6 +55,9 @@ err.unblock=<html>Unblocking of {0} is not supported.</html> err.retries=<html>Wrong {0}, {1} tries remaining</html> err.locked=<html>{0} locked</html> err.not.active=<html>{0} not activated.</html> +err.pin.format=<html>Invalid {0} length, {1} digit(s) required.</html> +err.pin.confirmation=<html>{0} and confirmation do not match.</html> +err.pin.operation.aborted=<html>The operation on {0} was aborted.</html> status.not.active=NOT ACTIVE status.active=ACTIVE diff --git a/nbactions.xml b/nbactions.xml new file mode 100644 index 00000000..4c3d57a9 --- /dev/null +++ b/nbactions.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<actions> + <action> + <actionName>CUSTOM-Install_SkipTest</actionName> + <displayName>Install_SkipTest</displayName> + <goals> + <goal>install</goal> + </goals> + <properties> + <maven.test.skip>true</maven.test.skip> + </properties> + </action> + </actions> 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 06e4a018..d064b821 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java @@ -401,15 +401,16 @@ public class ACOSCard extends AbstractSignatureCard { @Override protected int verifyPIN(byte kid, char[] pin) - throws LockedException, NotActivatedException, CancelledException, TimeoutException, SignatureCardException { + throws LockedException, NotActivatedException, CancelledException, TimeoutException, PINFormatException, PINOperationAbortedException, SignatureCardException { try { byte[] sw; if (reader.hasFeature(CCID.FEATURE_VERIFY_PIN_DIRECT)) { - log.debug("verify PIN on IFD"); - sw = reader.transmitControlCommand( - CCID.FEATURE_VERIFY_PIN_DIRECT, - getPINVerifyStructure(kid)); + log.debug("verify pin on cardreader"); + sw = reader.verifyPinDirect(getPINVerifyStructure(kid)); // int sw = (resp[resp.length-2] & 0xff) << 8 | resp[resp.length-1] & 0xff; + } else if (reader.hasFeature(CCID.FEATURE_VERIFY_PIN_START)) { + log.debug("verify pin on cardreader"); + sw = reader.verifyPin(getPINVerifyStructure(kid)); } else { byte[] pinBlock = encodePINBlock(pin); CardChannel channel = getCardChannel(); @@ -442,6 +443,8 @@ public class ACOSCard extends AbstractSignatureCard { throw new TimeoutException("[64:00]"); } else if (sw[0] == (byte) 0x64 && sw[1] == (byte) 0x01) { throw new CancelledException("[64:01]"); + } else if (sw[0] == (byte) 0x64 && sw[1] == (byte) 0x03) { + throw new PINFormatException("[64:03]"); } log.error("Failed to verify pin: SW=" + SMCCHelper.toString(sw)); @@ -465,15 +468,15 @@ public class ACOSCard extends AbstractSignatureCard { */ @Override protected int changePIN(byte kid, char[] oldPin, char[] newPin) - throws LockedException, NotActivatedException, CancelledException, TimeoutException, SignatureCardException { + throws LockedException, NotActivatedException, CancelledException, PINFormatException, PINConfirmationException, TimeoutException, PINOperationAbortedException, SignatureCardException { try { byte[] sw; if (reader.hasFeature(CCID.FEATURE_MODIFY_PIN_DIRECT)) { - log.debug("modify PIN on IFD"); - sw = reader.transmitControlCommand( - CCID.FEATURE_MODIFY_PIN_DIRECT, - getPINModifyStructure(kid)); -// int sw = (resp[resp.length-2] & 0xff) << 8 | resp[resp.length-1] & 0xff; + log.debug("modify pin on cardreader"); + sw = reader.modifyPinDirect(getPINModifyStructure(kid)); + } else if (reader.hasFeature(CCID.FEATURE_MODIFY_PIN_START)) { + log.debug("modify pin on cardreader"); + sw = reader.modifyPin(getPINModifyStructure(kid)); } else { byte[] cmd = new byte[16]; System.arraycopy(encodePINBlock(oldPin), 0, cmd, 0, 8); @@ -504,6 +507,13 @@ public class ACOSCard extends AbstractSignatureCard { throw new TimeoutException("[64:00]"); } else if (sw[0] == (byte) 0x64 && sw[1] == (byte) 0x01) { throw new CancelledException("[64:01]"); + } else if (sw[0] == (byte) 0x64 && sw[1] == (byte) 0x02) { + throw new PINConfirmationException("[64:02]"); + } else if (sw[0] == (byte) 0x64 && sw[1] == (byte) 0x03) { + throw new PINFormatException("[64:03]"); + } else if (sw[0] == (byte) 0x6a && sw[1] == (byte) 0x80) { + log.info("invalid parameter, assume wrong pin size"); + throw new PINFormatException("[6a:80]"); } log.error("Failed to change pin: SW=" + SMCCHelper.toString(sw)); @@ -559,7 +569,7 @@ public class ACOSCard extends AbstractSignatureCard { byte bmPINLengthFormat = (byte) 0x00; // 000 0 0000 // ^-------- System bit units is bit // ^^^^--- no PIN length - byte wPINMaxExtraDigitL = + byte wPINMaxExtraDigitL = //TODO compare ints, not bytes (reader.getwPINMaxExtraDigitL() < (byte) 0x08) ? reader.getwPINMaxExtraDigitL() : (byte) 0x08; byte wPINMaxExtraDigitH = 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 47c27369..7dd3ee78 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java @@ -29,21 +29,16 @@ package at.gv.egiz.smcc; import at.gv.egiz.smcc.ccid.CCID; -import at.gv.egiz.smcc.ccid.DefaultReader; import at.gv.egiz.smcc.ccid.ReaderFactory; import at.gv.egiz.smcc.util.SMCCHelper; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Locale; -import java.util.Map; 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; @@ -152,8 +147,8 @@ public abstract class AbstractSignatureCard implements SignatureCard { * @throws at.gv.egiz.smcc.SignatureCardException */ protected abstract int verifyPIN(byte kid, char[] pin) - throws LockedException, NotActivatedException, CancelledException, TimeoutException, SignatureCardException; - + throws LockedException, NotActivatedException, CancelledException, PINFormatException, TimeoutException, PINOperationAbortedException, SignatureCardException; + /** * CHANGE(?) APDU * If IFD supports VERIFY_PIN on pinpad, parameter pin may be empty. @@ -162,7 +157,7 @@ public abstract class AbstractSignatureCard implements SignatureCard { * @throws at.gv.egiz.smcc.SignatureCardException if activation fails */ protected abstract void activatePIN(byte kid, char[] pin) - throws CancelledException, TimeoutException, SignatureCardException; + throws CancelledException, PINFormatException, PINConfirmationException, TimeoutException, PINOperationAbortedException, SignatureCardException; /** * CHANGE(?) APDU @@ -173,7 +168,7 @@ public abstract class AbstractSignatureCard implements SignatureCard { * @throws at.gv.egiz.smcc.SignatureCardException if change fails */ protected abstract int changePIN(byte kid, char[] oldPin, char[] newPin) - throws CancelledException, TimeoutException, SignatureCardException; + throws LockedException, NotActivatedException, CancelledException, PINFormatException, PINConfirmationException, TimeoutException, PINOperationAbortedException, SignatureCardException; /** * encode the pin as needed in VERIFY/CHANGE APDUs @@ -595,7 +590,8 @@ public abstract class AbstractSignatureCard implements SignatureCard { */ @Override public void changePIN(PINSpec pinSpec, ChangePINProvider pinProvider) - throws LockedException, NotActivatedException, CancelledException, TimeoutException, SignatureCardException, InterruptedException { + throws LockedException, NotActivatedException, CancelledException, + TimeoutException, SignatureCardException, InterruptedException { try { getCard().beginExclusive(); diff --git a/smcc/src/main/java/at/gv/egiz/smcc/PINConfirmationException.java b/smcc/src/main/java/at/gv/egiz/smcc/PINConfirmationException.java new file mode 100644 index 00000000..115e6d5f --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/PINConfirmationException.java @@ -0,0 +1,43 @@ +/* +* 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; + +/** + * TODO check whether card readers distinguish specific reason (pin too short?) + * and add getters/setters + * + * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at> + */ +public class PINConfirmationException extends SignatureCardException { + + public PINConfirmationException() { + super(); + } + + public PINConfirmationException(String message, Throwable cause) { + super(message, cause); + } + + public PINConfirmationException(String message) { + super(message); + } + + public PINConfirmationException(Throwable cause) { + super(cause); + } + +} diff --git a/smcc/src/main/java/at/gv/egiz/smcc/PINFormatException.java b/smcc/src/main/java/at/gv/egiz/smcc/PINFormatException.java new file mode 100644 index 00000000..28a13fdb --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/PINFormatException.java @@ -0,0 +1,43 @@ +/* +* 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; + +/** + * TODO check whether card readers distinguish specific reason (pin too short?) + * and add getters/setters + * + * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at> + */ +public class PINFormatException extends SignatureCardException { + + public PINFormatException() { + super(); + } + + public PINFormatException(String message, Throwable cause) { + super(message, cause); + } + + public PINFormatException(String message) { + super(message); + } + + public PINFormatException(Throwable cause) { + super(cause); + } + +} diff --git a/smcc/src/main/java/at/gv/egiz/smcc/PINOperationAbortedException.java b/smcc/src/main/java/at/gv/egiz/smcc/PINOperationAbortedException.java new file mode 100644 index 00000000..7337f59e --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/PINOperationAbortedException.java @@ -0,0 +1,43 @@ +/* +* 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; + +/** + * TODO check whether card readers distinguish specific reason (pin too short?) + * and add getters/setters + * + * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at> + */ +public class PINOperationAbortedException extends SignatureCardException { + + public PINOperationAbortedException() { + super(); + } + + public PINOperationAbortedException(String message, Throwable cause) { + super(message, cause); + } + + public PINOperationAbortedException(String message) { + super(message); + } + + public PINOperationAbortedException(Throwable cause) { + super(cause); + } + +} 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 bc6a2316..b9c68b06 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java @@ -28,7 +28,7 @@ // package at.gv.egiz.smcc; -import at.gv.egiz.smcc.ccid.DefaultReader; +import at.gv.egiz.smcc.ccid.CCID; import at.gv.egiz.smcc.util.SMCCHelper; import java.util.Arrays; import javax.smartcardio.CardChannel; @@ -319,6 +319,8 @@ public class STARCOSCard extends AbstractSignatureCard { return createSignature(hash, AID_DF_SS, pin, KID_PIN_SS, DST_SS); } catch (VerificationFailedException e) { retries = e.getRetries(); + } catch (PINFormatException e) { + log.debug("wrong pin size entered, retry"); } finally { getCard().endExclusive(); } @@ -454,15 +456,16 @@ public class STARCOSCard extends AbstractSignatureCard { @Override protected int verifyPIN(byte kid, char[] pin) - throws LockedException, NotActivatedException, SignatureCardException { + throws LockedException, NotActivatedException, TimeoutException, CancelledException, PINFormatException, PINOperationAbortedException, SignatureCardException { try { byte[] sw; - if (reader.hasFeature(DefaultReader.FEATURE_VERIFY_PIN_DIRECT)) { - log.debug("verify PIN on IFD"); - sw = reader.transmitControlCommand( - DefaultReader.FEATURE_VERIFY_PIN_DIRECT, - getPINVerifyStructure(kid)); + if (reader.hasFeature(CCID.FEATURE_VERIFY_PIN_DIRECT)) { + log.debug("verify pin on cardreader"); + sw = reader.verifyPinDirect(getPINVerifyStructure(kid)); // int sw = (resp[resp.length-2] & 0xff) << 8 | resp[resp.length-1] & 0xff; + } else if (reader.hasFeature(CCID.FEATURE_VERIFY_PIN_START)) { + log.debug("verify pin on cardreader"); + sw = reader.verifyPin(getPINVerifyStructure(kid)); } else { byte[] pinBlock = encodePINBlock(pin); CardChannel channel = getCardChannel(); @@ -492,6 +495,8 @@ public class STARCOSCard extends AbstractSignatureCard { throw new TimeoutException("[64:00]"); } else if (sw[0] == (byte) 0x64 && sw[1] == (byte) 0x01) { throw new CancelledException("[64:01]"); + } else if (sw[0] == (byte) 0x64 && sw[1] == (byte) 0x03) { + throw new PINFormatException("[64:03]"); } log.error("Failed to verify pin: SW=" + SMCCHelper.toString(sw)); @@ -539,15 +544,15 @@ public class STARCOSCard extends AbstractSignatureCard { @Override protected int changePIN(byte kid, char[] oldPin, char[] newPin) - throws LockedException, NotActivatedException, CancelledException, TimeoutException, SignatureCardException { + throws LockedException, CancelledException, PINFormatException, PINConfirmationException, TimeoutException, PINOperationAbortedException, SignatureCardException { try { byte[] sw; - if (reader.hasFeature(DefaultReader.FEATURE_MODIFY_PIN_DIRECT)) { - log.debug("modify PIN on IFD"); - sw = reader.transmitControlCommand( - DefaultReader.FEATURE_MODIFY_PIN_DIRECT, - getPINModifyStructure(kid)); -// int sw = (resp[resp.length-2] & 0xff) << 8 | resp[resp.length-1] & 0xff; + if (reader.hasFeature(CCID.FEATURE_MODIFY_PIN_DIRECT)) { + log.debug("modify pin on cardreader"); + sw = reader.modifyPinDirect(getPINModifyStructure(kid)); + } else if (reader.hasFeature(CCID.FEATURE_MODIFY_PIN_START)) { + log.debug("modify pin on cardreader"); + sw = reader.modifyPin(getPINModifyStructure(kid)); } else { byte[] cmd = new byte[16]; System.arraycopy(encodePINBlock(oldPin), 0, cmd, 0, 8); @@ -583,6 +588,13 @@ public class STARCOSCard extends AbstractSignatureCard { throw new TimeoutException("[64:00]"); } else if (sw[0] == (byte) 0x64 && sw[1] == (byte) 0x01) { throw new CancelledException("[64:01]"); + } else if (sw[0] == (byte) 0x64 && sw[1] == (byte) 0x02) { + throw new PINConfirmationException("[64:02]"); + } else if (sw[0] == (byte) 0x64 && sw[1] == (byte) 0x03) { + throw new PINFormatException("[64:03]"); + } else if (sw[0] == (byte) 0x6a && sw[1] == (byte) 0x80) { + log.info("invalid parameter, assume wrong pin size"); + throw new PINFormatException("[6a:80]"); } log.error("Failed to change pin: SW=" + SMCCHelper.toString(sw)); @@ -595,15 +607,15 @@ public class STARCOSCard extends AbstractSignatureCard { @Override protected void activatePIN(byte kid, char[] pin) - throws CancelledException, TimeoutException, SignatureCardException { + throws CancelledException, PINFormatException, PINConfirmationException, TimeoutException, PINOperationAbortedException, SignatureCardException { try { byte[] sw; - if (reader.hasFeature(DefaultReader.FEATURE_MODIFY_PIN_DIRECT)) { - log.debug("activate PIN on IFD"); - sw = reader.transmitControlCommand( - DefaultReader.FEATURE_MODIFY_PIN_DIRECT, - getActivatePINModifyStructure(kid)); -// int sw = (resp[resp.length-2] & 0xff) << 8 | resp[resp.length-1] & 0xff; + if (reader.hasFeature(CCID.FEATURE_MODIFY_PIN_DIRECT)) { + log.debug("activate pin on cardreader"); + sw = reader.modifyPinDirect(getActivatePINModifyStructure(kid)); + } else if (reader.hasFeature(CCID.FEATURE_MODIFY_PIN_START)) { + log.debug("activate pin on cardreader"); + sw = reader.modifyPin(getActivatePINModifyStructure(kid)); } else { CardChannel channel = getCardChannel(); ResponseAPDU resp = transmit(channel, @@ -630,6 +642,10 @@ public class STARCOSCard extends AbstractSignatureCard { throw new TimeoutException("[64:00]"); } else if (sw[0] == (byte) 0x64 && sw[1] == (byte) 0x01) { throw new CancelledException("[64:01]"); + } else if (sw[0] == (byte) 0x64 && sw[1] == (byte) 0x02) { + throw new PINConfirmationException("[64:02]"); + } else if (sw[0] == (byte) 0x64 && sw[1] == (byte) 0x03) { + throw new PINFormatException("[64:03]"); } log.error("Failed to activate pin: SW=" + SMCCHelper.toString(sw)); @@ -683,6 +699,7 @@ public class STARCOSCard extends AbstractSignatureCard { byte bmPINLengthFormat = (byte) 0x04; // 000 0 0100 // ^-------- System bit units is bit // ^^^^--- PIN length is at the 4th position bit + //TODO compare ints, not bytes byte wPINMaxExtraDigitL = // Max=12 digits (Gemplus support max 8) (reader.getwPINMaxExtraDigitL() < (byte) 0x12) ? reader.getwPINMaxExtraDigitL() : (byte) 0x12; 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 253ac7a0..2ed1fe64 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java @@ -430,13 +430,6 @@ public class SWCard implements SignatureCard { } @Override - public byte[] transmitControlCommand(Byte feature, byte[] ctrlCommand) - throws SignatureCardException { - throw new SignatureCardException(CCID.FEATURES[feature.intValue()] + - " not supported"); - } - - @Override public byte getbTimeOut() { return 0; } @@ -465,6 +458,31 @@ public class SWCard implements SignatureCard { public Card connect() { return null; } + + @Override + public String getName() { + return "Software CardReader"; + } + + @Override + public byte[] verifyPin(byte[] PIN_VERIFY) throws CardException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public byte[] verifyPinDirect(byte[] PIN_VERIFY) throws CardException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public byte[] modifyPin(byte[] PIN_MODIFY) throws CardException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public byte[] modifyPinDirect(byte[] PIN_MODIFY) throws CardException { + throw new UnsupportedOperationException("Not supported yet."); + } }; } } 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 ad530ad5..c06074f2 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java @@ -128,7 +128,7 @@ public interface SignatureCard { throws LockedException, NotActivatedException, CancelledException, SignatureCardException, InterruptedException; public void changePIN(PINSpec pinSpec, ChangePINProvider pinProvider) - throws LockedException, NotActivatedException, CancelledException, SignatureCardException, InterruptedException; + throws LockedException, NotActivatedException, CancelledException, PINFormatException, SignatureCardException, InterruptedException; public void activatePIN(PINSpec pinSpec, PINProvider pinProvider) throws CancelledException, SignatureCardException, InterruptedException; diff --git a/smcc/src/main/java/at/gv/egiz/smcc/ccid/CCID.java b/smcc/src/main/java/at/gv/egiz/smcc/ccid/CCID.java index 2c56ce98..56ebaffe 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/ccid/CCID.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/ccid/CCID.java @@ -45,17 +45,48 @@ public interface CCID { "FEATURE_WRITE_DISPLAY", "FEATURE_GET_KEY", "FEATURE_IFD_DISPLAY_PROPERTIES"}; - - Byte FEATURE_IFD_PIN_PROPERTIES = new Byte((byte) 10); - Byte FEATURE_MCT_READER_DIRECT = new Byte((byte) 8); - Byte FEATURE_MODIFY_PIN_DIRECT = new Byte((byte) 7); - Byte FEATURE_VERIFY_PIN_DIRECT = new Byte((byte) 6); - + + 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); + //TODO continue list + + String getName(); + Card connect() throws CardException; boolean hasFeature(Byte feature); /** + * not supported by OMNIKEY CardMan 3621 with ACOS card + * @param PIN_VERIFY + * @return + * @throws at.gv.egiz.smcc.PINOperationAbortedException + * @throws javax.smartcardio.CardException + */ + byte[] verifyPin(byte[] PIN_VERIFY) throws PINOperationAbortedException, CardException; + + byte[] verifyPinDirect(byte[] PIN_VERIFY) throws CardException; + + /** + * not supported by OMNIKEY CardMan 3621 with ACOS card + * @param PIN_MODIFY + * @return + * @throws at.gv.egiz.smcc.PINOperationAbortedException + * @throws javax.smartcardio.CardException + */ + byte[] modifyPin(byte[] PIN_MODIFY) throws PINOperationAbortedException, CardException; + + byte[] modifyPinDirect(byte[] PIN_MODIFY) throws CardException; + + /** * * @param feature the corresponding control code will be transmitted * @param ctrlCommand @@ -63,7 +94,7 @@ public interface CCID { * @throws at.gv.egiz.smcc.SignatureCardException if feature is not supported * or card communication fails */ - byte[] transmitControlCommand(Byte feature, byte[] ctrlCommand) throws SignatureCardException; +// byte[] transmitControlCommand(Byte feature, byte[] ctrlCommand) throws SignatureCardException; /** * allow subclasses to override default (deal with reader bugs) diff --git a/smcc/src/main/java/at/gv/egiz/smcc/ccid/DefaultReader.java b/smcc/src/main/java/at/gv/egiz/smcc/ccid/DefaultReader.java index 2cc77dc9..9b1787a0 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/ccid/DefaultReader.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/ccid/DefaultReader.java @@ -20,6 +20,8 @@ import at.gv.egiz.smcc.*; import at.gv.egiz.smcc.util.SMCCHelper; import java.util.HashMap; import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; import javax.smartcardio.Card; import javax.smartcardio.CardException; import javax.smartcardio.CardTerminal; @@ -35,12 +37,17 @@ public class DefaultReader implements CCID { protected final static Log log = LogFactory.getLog(DefaultReader.class); private static int CTL_CODE(int code) { - return 0x42000000 + 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); } int IOCTL_GET_FEATURE_REQUEST = CTL_CODE(3400); - protected Card icc; protected CardTerminal ct; @@ -58,14 +65,19 @@ public class DefaultReader implements CCID { features = queryFeatures(); } - public Card connect() throws CardException { //SignatureCardException { -// try { + /** + * + * @return the card terminals name + */ + @Override + public String getName() { + return ct.getName(); + } + + @Override + public Card connect() throws CardException { icc = ct.connect("*"); return icc; -// } catch (CardException ex) { -// log.error(ex.getMessage(), ex); -// throw new SignatureCardException("Failed to connect to card: " + ex.getMessage()); -// } } Map<Byte, Integer> queryFeatures() { @@ -81,7 +93,7 @@ public class DefaultReader implements CCID { " on " + ct.getName()); } byte[] resp = icc.transmitControlCommand(IOCTL_GET_FEATURE_REQUEST, - new byte[]{}); + new byte[0]); if (log.isTraceEnabled()) { log.trace("Response TLV " + SMCCHelper.toString(resp)); @@ -91,8 +103,10 @@ public class DefaultReader implements CCID { // control code value for supported feature (in big endian) for (int i = 0; i < resp.length; i += 6) { Byte feature = new Byte(resp[i]); - int ioctlBigEndian = (resp[i + 2] << 24) | - (resp[i + 3] << 16) | (resp[i + 4] << 8) | resp[i + 5]; + int ioctlBigEndian = ((0xff & resp[i + 2]) << 24) | + ((0xff & resp[i + 3]) << 16) | + ((0xff & resp[i + 4]) << 8) | + (0xff & resp[i + 5]); Integer ioctl = new Integer(ioctlBigEndian); if (log.isInfoEnabled()) { log.info("CCID supports " + FEATURES[feature.intValue()] + @@ -117,37 +131,29 @@ public class DefaultReader implements CCID { return false; } -// public Integer getIOCTL(Byte feature) { -// if (features != null) { -// return features.get(feature); +// protected byte[] transmitControlCommand(Byte feature, byte[] ctrlCommand) +// throws CardException { +// try { +// if (!features.containsKey(feature)) { +// throw new CardException(FEATURES[feature.intValue()] + " not supported"); +// } +// int ioctl = features.get(feature); +// if (log.isTraceEnabled()) { +// log.trace("CtrlCommand (" + Integer.toHexString(ioctl) + +// ") " + SMCCHelper.toString(ctrlCommand)); +// } +// byte[] resp = icc.transmitControlCommand(ioctl, ctrlCommand); +// if (log.isTraceEnabled()) { +// log.trace("CtrlCommand Response " + SMCCHelper.toString(resp)); +// } +// return resp; +// } catch (CardException ex) { +// log.error(ex.getMessage()); +// throw new SignatureCardException("Failed to transmit CtrlCommand for " + +// FEATURES[feature.intValue()]); // } -// return null; // } - @Override - public byte[] transmitControlCommand(Byte feature, byte[] ctrlCommand) - throws SignatureCardException { - try { - if (!features.containsKey(feature)) { - throw new SignatureCardException(FEATURES[feature.intValue()] + " not supported"); - } - int ioctl = features.get(feature); - if (log.isTraceEnabled()) { - log.trace("CtrlCommand (" + Integer.toHexString(ioctl) + - ") " + SMCCHelper.toString(ctrlCommand)); - } - byte[] resp = icc.transmitControlCommand(ioctl, ctrlCommand); - if (log.isTraceEnabled()) { - log.trace("CtrlCommand Response " + SMCCHelper.toString(resp)); - } - return resp; - } catch (CardException ex) { - log.error(ex.getMessage()); - throw new SignatureCardException("Failed to transmit CtrlCommand for " + - FEATURES[feature.intValue()]); - } - } - @Override public byte getbTimeOut() { @@ -162,7 +168,7 @@ public class DefaultReader implements CCID { @Override public byte getwPINMaxExtraDigitL() { - return (byte) 0x12; + return (byte) 0x12; // signed int } @Override @@ -175,6 +181,265 @@ public class DefaultReader implements CCID { return (byte) 0x02; // validation key pressed } + void verifyPinStart(byte[] PIN_VERIFY) throws CardException { + if (!features.containsKey(FEATURE_VERIFY_PIN_START)) { + throw new CardException("FEATURE_VERIFY_PIN_START not supported"); + } + int ioctl = features.get(FEATURE_VERIFY_PIN_START); + if (log.isTraceEnabled()) { + 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"); + throw new CardException("ERROR_INVALID_PARAMETER"); + } else { + log.error("unexpected response to VERIFY_PIN_START: " + + SMCCHelper.toString(resp)); + throw new CardException("unexpected response to VERIFY_PIN_START: " + + SMCCHelper.toString(resp)); + } + } + } + + byte[] verifyPinFinish() throws CardException { + if (!features.containsKey(FEATURE_VERIFY_PIN_FINISH)) { + throw new CardException("FEATURE_VERIFY_FINISH_FINISH not supported"); + } + int ioctl = features.get(FEATURE_VERIFY_PIN_FINISH); + if (log.isTraceEnabled()) { + 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)); + } + return resp; + } + log.error("unexpected response to VERIFY_PIN_FINISH: " + + SMCCHelper.toString(resp)); + throw new CardException("unexpected response to VERIFY_PIN_FINISH: " + + SMCCHelper.toString(resp)); + } + + void modifyPinStart(byte[] PIN_MODIFY) throws CardException { + if (!features.containsKey(FEATURE_MODIFY_PIN_START)) { + throw new CardException("FEATURE_MODIFY_PIN_START not supported"); + } + int ioctl = features.get(FEATURE_MODIFY_PIN_START); + if (log.isTraceEnabled()) { + log.trace("MODFIY_PIN_START (" + Integer.toHexString(ioctl) + + ") " + SMCCHelper.toString(PIN_MODIFY)); + } + 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"); + throw new CardException("ERROR_INVALID_PARAMETER"); + } else { + log.error("unexpected response to MODIFY_PIN_START: " + + SMCCHelper.toString(resp)); + throw new CardException("unexpected response to MODIFY_PIN_START: " + + SMCCHelper.toString(resp)); + } + } + } + + byte[] modifyPinFinish() throws CardException { + if (!features.containsKey(FEATURE_MODIFY_PIN_FINISH)) { + throw new CardException("FEATURE_MODIFY_FINISH_FINISH not supported"); + } + int ioctl = features.get(FEATURE_MODIFY_PIN_FINISH); + if (log.isTraceEnabled()) { + 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)); + } + return resp; + } + log.error("unexpected response to MODIFY_PIN_FINISH: " + + SMCCHelper.toString(resp)); + throw new CardException("unexpected response to MODIFY_PIN_FINISH: " + + SMCCHelper.toString(resp)); + } + + + byte getKeyPressed() throws CardException { + if (!features.containsKey(FEATURE_GET_KEY_PRESSED)) { + throw new CardException("FEATURE_GET_KEY_PRESSED not supported"); + } + int ioctl = features.get(FEATURE_GET_KEY_PRESSED); +// if (log.isTraceEnabled()) { +// log.trace("GET_KEY_PRESSED (" + Integer.toHexString(ioctl) + ")"); +// } + byte[] resp = icc.transmitControlCommand(ioctl, new byte[0]); + if (resp != null && resp.length == 1) { +// if (log.isTraceEnabled()) { +// log.trace("response " + SMCCHelper.toString(resp)); +// } + return resp[0]; + } + log.error("unexpected response to GET_KEY_PRESSED: " + + SMCCHelper.toString(resp)); + throw new CardException("unexpected response to GET_KEY_PRESSED: " + + SMCCHelper.toString(resp)); + } + + + + @Override + public byte[] verifyPinDirect(byte[] PIN_VERIFY) throws CardException { + if (!features.containsKey(FEATURE_VERIFY_PIN_DIRECT)) { + throw new CardException("FEATURE_VERIFY_PIN_DIRECT not supported"); + } + int ioctl = features.get(FEATURE_VERIFY_PIN_DIRECT); + if (log.isTraceEnabled()) { + 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)); + } + return resp; + } + + @Override + public byte[] verifyPin(byte[] PIN_VERIFY) throws PINOperationAbortedException, CardException { + verifyPinStart(PIN_VERIFY); + byte resp; + do { + resp = getKeyPressed(); + if (resp == (byte) 0x00) { + synchronized(this) { + try { + wait(200); + } catch (InterruptedException ex) { + log.error("interrupted in VERIFY_PIN"); + } + } + } else if (resp == (byte) 0x0d) { + log.trace("user confirmed"); + break; + } else if (resp == (byte) 0x2b) { + log.trace("user entered valid key (0-9)"); + } else if (resp == (byte) 0x1b) { + log.info("user cancelled VERIFY_PIN via cancel button"); + return verifyPinFinish(); +// return new byte[] { (byte) 0x64, (byte) 0x01 }; + } else if (resp == (byte) 0x08) { + log.trace("user pressed correction/backspace button"); + } else if (resp == (byte) 0x0e) { + log.trace("timeout occured"); + return verifyPinFinish(); // return 0x64 0x00 + } else if (resp == (byte) 0x40) { + log.trace("PIN_Operation_Aborted"); + throw new PINOperationAbortedException("PIN_Operation_Aborted"); + } else if (resp == (byte) 0x0a) { + log.trace("all keys cleared"); + } else { + log.error("unexpected response to GET_KEY_PRESSED: " + + Integer.toHexString(resp)); + throw new CardException("unexpected response to GET_KEY_PRESSED: " + + Integer.toHexString(resp)); + } + } while (true); //resp != (byte) 0x0d); + + return verifyPinFinish(); + } + + @Override + public byte[] modifyPin(byte[] PIN_MODIFY) throws PINOperationAbortedException, CardException { + modifyPinStart(PIN_MODIFY); + log.debug(PIN_MODIFY[9] + " pin confirmations expected"); + + byte resp; + short pinConfirmations = 0; + do { + resp = getKeyPressed(); + if (resp == (byte) 0x00) { + synchronized(this) { + try { + wait(200); + } catch (InterruptedException ex) { + log.error("interrupted in MODIFY_PIN"); + } + } + } else if (resp == (byte) 0x0d) { + log.trace("user confirmed"); + pinConfirmations++; + continue; + } else if (resp == (byte) 0x2b) { + log.trace("user entered valid key (0-9)"); + } else if (resp == (byte) 0x1b) { + log.info("user cancelled MODIFY_PIN via cancel button"); +// return verifyPinFinish(); + return new byte[] { (byte) 0x64, (byte) 0x01 }; + } else if (resp == (byte) 0x08) { + log.trace("user pressed correction/backspace button"); + } else if (resp == (byte) 0x0e) { + log.trace("timeout occured"); + return new byte[] { (byte) 0x64, (byte) 0x00 }; +// return verifyPinFinish(); // return 0x64 0x00 + } else if (resp == (byte) 0x40) { + log.trace("PIN_Operation_Aborted"); + throw new PINOperationAbortedException("PIN_Operation_Aborted"); + } else if (resp == (byte) 0x0a) { + log.trace("all keys cleared"); + } else { + log.error("unexpected response to GET_KEY_PRESSED: " + + Integer.toHexString(resp)); + throw new CardException("unexpected response to GET_KEY_PRESSED: " + + Integer.toHexString(resp)); + } + } while (pinConfirmations < PIN_MODIFY[9]); + + return modifyPinFinish(); + } + + /** + * NOT SUPPORTED FOR ACOS ON OMNIKEY CardMan 3621 + * + * @param PIN_MODIFY + * @return + * @throws javax.smartcardio.CardException + */ + @Override + public byte[] modifyPinDirect(byte[] PIN_MODIFY) throws CardException { + if (!features.containsKey(FEATURE_MODIFY_PIN_DIRECT)) { + throw new CardException("FEATURE_MODIFY_PIN_DIRECT not supported"); + } + int ioctl = features.get(FEATURE_MODIFY_PIN_DIRECT); + if (log.isTraceEnabled()) { + 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)); + } + return resp; + } + + +//[TRACE] SmartCardIO - terminal 'PC/SC terminal OMNIKEY CardMan 3621 0' card inserted : PC/SC card in OMNIKEY CardMan 3621 0, protocol T=1, state OK +//[TRACE] DefaultReader - GET_FEATURE_REQUEST 313520 on OMNIKEY CardMan 3621 0 +//[TRACE] DefaultReader - Response TLV [01:04:00:31:30:00:02:04:00:31:2f:d4:03:04:00:31:30:04:04:04:00:31:2f:dc:05:04:00:31:2f:e0:0a:04 +//00:31:30:08] +//[INFO] DefaultReader - CCID supports FEATURE_VERIFY_PIN_START: 313000 +//[INFO] DefaultReader - CCID supports FEATURE_VERIFY_PIN_FINISH: ffffffd4 +//[INFO] DefaultReader - CCID supports FEATURE_MODIFY_PIN_START: 313004 +//[INFO] DefaultReader - CCID supports FEATURE_MODIFY_PIN_FINISH: ffffffdc +//[INFO] DefaultReader - CCID supports FEATURE_GET_KEY_PRESSED: ffffffe0 +//[INFO] DefaultReader - CCID supports FEATURE_IFD_PIN_PROPERTIES: 313008 +//[TRACE] AbstractSignatureCard - Setting IFS (information field size) to 254 + // protected byte ifdGetKeyPressed() throws CardException { // if (ifdSupportsFeature(FEATURE_VERIFY_PIN_DIRECT)) { diff --git a/smcc/src/main/java/at/gv/egiz/smcc/ccid/OMNIKEYCardMan3621.java b/smcc/src/main/java/at/gv/egiz/smcc/ccid/OMNIKEYCardMan3621.java new file mode 100644 index 00000000..35dd4f99 --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/ccid/OMNIKEYCardMan3621.java @@ -0,0 +1,39 @@ +/* + * 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.ccid; + +import javax.smartcardio.Card; +import javax.smartcardio.CardTerminal; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Fails with ACOS cards (Problem might be 'short' VERIFY which is not supported by ACOS) + * TODO + * + * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at> + */ +public class OMNIKEYCardMan3621 extends DefaultReader { + + protected static final Log log = LogFactory.getLog(OMNIKEYCardMan3621.class); + + public OMNIKEYCardMan3621(Card icc, CardTerminal ct) { + super(icc, ct); + log.warn("This card reader does not support ACOS cards."); + log.debug("TODO: fall back to software pin entry"); + } +} diff --git a/smcc/src/main/java/at/gv/egiz/smcc/ccid/ReaderFactory.java b/smcc/src/main/java/at/gv/egiz/smcc/ccid/ReaderFactory.java index 2cfcef19..07c16c3e 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/ccid/ReaderFactory.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/ccid/ReaderFactory.java @@ -29,6 +29,8 @@ public class ReaderFactory { public static CCID getReader(Card icc, CardTerminal ct) { if ("Gemplus GemPC Pinpad 00 00".equals(ct.getName())) { return new GemplusGemPCPinpad(icc, ct); + } else if ("OmniKey CardMan 3621 00 00".equals(ct.getName())) { + return new OMNIKEYCardMan3621(icc, ct); } return new DefaultReader(icc, ct); } diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/InfoBoxReadRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/InfoBoxReadRequestHandler.java index 94444922..eeb97290 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/InfoBoxReadRequestHandler.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/InfoBoxReadRequestHandler.java @@ -37,21 +37,20 @@ public class InfoBoxReadRequestHandler extends AbstractRequestHandler { private static Log log = LogFactory.getLog(InfoBoxReadRequestHandler.class); - protected PINProviderFactory pinProviderFactory; +// protected PINProviderFactory pinProviderFactory; @Override public STALResponse handleRequest(STALRequest request) throws InterruptedException { if (request instanceof InfoboxReadRequest) { InfoboxReadRequest infoBox = (InfoboxReadRequest) request; - if (pinProviderFactory == null) { - pinProviderFactory = PINProviderFactory.getInstance(card, gui); - } + try { if (infoBox.getInfoboxIdentifier().equals("IdentityLink")) { newSTALMessage("Message.RequestCaption", "Message.IdentityLink"); log.debug("Handling identitylink infobox"); byte[] resp = card.getInfobox(infoBox.getInfoboxIdentifier(), - pinProviderFactory.getCardPINProvider(), + new PINProviderFactory(card.getReader(), gui) + .getCardPINProvider(), infoBox.getDomainIdentifier()); if (resp == null) { log.info("Got null as result->user cancelled"); @@ -98,7 +97,8 @@ public class InfoBoxReadRequestHandler extends AbstractRequestHandler { log.warn("Unknown infobox identifier: " + infoBox.getInfoboxIdentifier() + " trying generic request"); byte[] resp = card.getInfobox(infoBox.getInfoboxIdentifier(), - pinProviderFactory.getCardPINProvider(), + new PINProviderFactory(card.getReader(), gui) + .getCardPINProvider(), infoBox.getDomainIdentifier()); if (resp == null) { return new ErrorResponse(6001); diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/PINProviderFactory.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/PINProviderFactory.java index ce1b2d00..78ae6c2b 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/PINProviderFactory.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/PINProviderFactory.java @@ -18,31 +18,305 @@ package at.gv.egiz.bku.smccstal; import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.smcc.CancelledException; import at.gv.egiz.smcc.ccid.CCID; import at.gv.egiz.smcc.PINProvider; -import at.gv.egiz.smcc.SignatureCard; +import at.gv.egiz.smcc.PINSpec; import at.gv.egiz.stal.signedinfo.SignedInfoType; +import java.security.DigestException; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; /** * * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at> */ -public abstract class PINProviderFactory { +public class PINProviderFactory { + + protected static final Log log = LogFactory.getLog(PINProviderFactory.class); + + protected CCID reader; + protected BKUGUIFacade gui; + + /** + * don't reuse the instance if the card reader might have changed! + * @param reader + * @param gui + */ + public PINProviderFactory(CCID reader, BKUGUIFacade gui) { + log.trace("PINProviderFactory for " + reader.getName()); + this.reader = reader; + this.gui = gui; + } + - BKUGUIFacade gui; - public static PINProviderFactory getInstance(SignatureCard forCard, - BKUGUIFacade gui) { - if (forCard.getReader().hasFeature(CCID.FEATURE_VERIFY_PIN_DIRECT)) { - return new PinpadPINProviderFactory(gui); +// public static PINProviderFactory getInstance(SignatureCard forCard, +// BKUGUIFacade gui) { +// if (forCard.getReader().hasFeature(CCID.FEATURE_VERIFY_PIN_DIRECT) || +// forCard.getReader().hasFeature(CCID.FEATURE_VERIFY_PIN_DIRECT)) { +// return new PinpadPINProviderFactory(gui); +// } else { +// return new SoftwarePINProviderFactory(gui); +// } +// } + + /** + * don't reuse the instance if the card reader might have changed! + * @param reader + * @param gui + * @return + */ +// public static PINProviderFactory getInstance(CCID reader, BKUGUIFacade gui) { +// log.trace("PINProviderFactory for " + reader.getName()); +// return new PINProviderFactory(reader, gui); +// } + + public PINProvider getSignaturePINProvider(SecureViewer viewer, + SignedInfoType signedInfo) { + if (reader.hasFeature(CCID.FEATURE_VERIFY_PIN_START) || + reader.hasFeature(CCID.FEATURE_VERIFY_PIN_DIRECT)) { + log.debug("pinpad signature-pin provider"); + return new PinpadSignaturePinProvider(viewer, signedInfo); } else { - return new SoftwarePINProviderFactory(gui); + log.debug("software signature-pin provider"); + return new SoftwareSignaturePinProvider(viewer, signedInfo); } } - public abstract PINProvider getSignaturePINProvider(SecureViewer viewer, - SignedInfoType signedInfo); - - public abstract PINProvider getCardPINProvider(); + public PINProvider getCardPINProvider() { + if (reader.hasFeature(CCID.FEATURE_VERIFY_PIN_START) || + reader.hasFeature(CCID.FEATURE_VERIFY_PIN_DIRECT)) { + log.debug("pinpad card-pin provider"); + return new PinpadCardPinProvider(); + } else { + log.debug("software card-pin provider"); + return new SoftwareCardPinProvider(); + } + } + + class SoftwareSignaturePinProvider extends AbstractPINProvider { + + protected SecureViewer viewer; + protected SignedInfoType signedInfo; + + private SoftwareSignaturePinProvider(SecureViewer viewer, + SignedInfoType signedInfo) { + this.viewer = viewer; + this.signedInfo = signedInfo; + } + + @Override + public char[] providePIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException { + + gui.showSignaturePINDialog(spec, (retry) ? retries : -1, + this, "sign", + this, "cancel", + this, "secureViewer"); + + do { + waitForAction(); + + if ("secureViewer".equals(action)) { + try { + viewer.displayDataToBeSigned(signedInfo, this, "pinEntry"); + } catch (DigestException ex) { + log.error("Bad digest value: " + ex.getMessage()); + gui.showErrorDialog(BKUGUIFacade.ERR_INVALID_HASH, + new Object[]{ex.getMessage()}, + this, "error"); + } catch (Exception ex) { + log.error("Could not display hashdata inputs: " + + ex.getMessage()); + gui.showErrorDialog(BKUGUIFacade.ERR_DISPLAY_HASHDATA, + new Object[]{ex.getMessage()}, + this, "error"); + } + } else if ("sign".equals(action)) { + gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, + BKUGUIFacade.MESSAGE_WAIT); + retry = true; + return gui.getPin(); + } else if ("pinEntry".equals(action)) { + gui.showSignaturePINDialog(spec, (retry) ? retries : -1, + this, "sign", + this, "cancel", + this, "secureViewer"); + } else if ("cancel".equals(action) || + "error".equals(action)) { + gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, + BKUGUIFacade.MESSAGE_WAIT); + throw new CancelledException(spec.getLocalizedName() + + " entry cancelled"); + } else { + log.error("unknown action command " + action); + } + } while (true); + } + } + + class SoftwareCardPinProvider extends AbstractPINProvider { + + private SoftwareCardPinProvider() { + } + + @Override + public char[] providePIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException { + + gui.showCardPINDialog(spec, (retry) ? retries : -1, + this, "ok", + this, "cancel"); + + waitForAction(); + + gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, + BKUGUIFacade.MESSAGE_WAIT); + + if ("cancel".equals(action)) { + throw new CancelledException(spec.getLocalizedName() + + " entry cancelled"); + } + retry = true; + return gui.getPin(); + } + } + + class PinpadSignaturePinProvider extends AbstractPINProvider { +// protected BKUGUIFacade gui; + protected SecureViewer viewer; + protected ViewerThread viewerThread; + protected SignedInfoType signedInfo; + + + private PinpadSignaturePinProvider(SecureViewer viewer, + SignedInfoType signedInfo) { + this.viewer = viewer; + this.signedInfo = signedInfo; + } + + protected class ViewerThread extends Thread { + + PINSpec pinSpec; + int retries; + + public ViewerThread(PINSpec pinSpec, int retries) { + this.pinSpec = pinSpec; + this.retries = retries; + } + + @Override + public void run() { + + try { + + gui.showPinpadSignaturePINDialog(pinSpec, retries, + PinpadSignaturePinProvider.this, "secureViewer"); + + while (true) { + waitForAction(); + + if ("secureViewer".equals(action)) { + viewer.displayDataToBeSigned(signedInfo, + PinpadSignaturePinProvider.this, "pinEntry"); + } else if ("pinEntry".equals(action)) { + gui.showPinpadSignaturePINDialog(pinSpec, retries, + PinpadSignaturePinProvider.this, "secureViewer"); + } else { + log.error("unsupported action command: " + action); + } + } + + } catch (DigestException ex) { + log.error("Bad digest value: " + ex.getMessage()); + gui.showErrorDialog(BKUGUIFacade.ERR_INVALID_HASH, + new Object[]{ex.getMessage()}); + } catch (InterruptedException ex) { + log.info("pinpad secure viewer thread interrupted"); + } catch (Exception ex) { + log.error("Could not display hashdata inputs: " + + ex.getMessage()); + gui.showErrorDialog(BKUGUIFacade.ERR_DISPLAY_HASHDATA, + new Object[]{ex.getMessage()}); + } + } + } + + @Override + public char[] providePIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException { + + if (viewerThread != null) { + updateViewerThread(retries); + } else { + viewerThread = new ViewerThread(spec, -1); + viewerThread.start(); + } +// if (viewerThread != null) { +// log.trace("interrupt old secure viewer thread"); +// viewerThread.interrupt(); +// } +// viewerThread = new ViewerThread(spec, (retry) ? retries : -1); +// log.trace("start new secure viewer thread"); +// viewerThread.start(); + + retry = true; + return null; + } + + private synchronized void updateViewerThread(int retries) { + log.trace("update viewer thread"); + viewerThread.retries = retries; + action = "pinEntry"; + actionPerformed = true; + notify(); + } + + +// @Override +// protected void finalize() throws Throwable { +// if (viewerThread != null) { +// viewerThread.interrupt(); +// } +// log.info("finalizing Pinpad SignaturePinProvider"); +// super.finalize(); +// } + } + + class PinpadCardPinProvider extends AbstractPINProvider { + + private PinpadCardPinProvider() { + } + + @Override + public char[] providePIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException { + + showPinpadPINDialog(retries, spec); + retry = true; + return null; + + } + + private void showPinpadPINDialog(int retries, PINSpec pinSpec) { + String title, message; + Object[] params; + if (retry) { + title = BKUGUIFacade.TITLE_RETRY; + message = BKUGUIFacade.MESSAGE_RETRIES; + params = new Object[]{String.valueOf(retries)}; + } else { + title = BKUGUIFacade.TITLE_CARDPIN; + message = BKUGUIFacade.MESSAGE_ENTERPIN_PINPAD; + String pinSize = String.valueOf(pinSpec.getMinLength()); + if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { + pinSize += "-" + pinSpec.getMaxLength(); + } + params = new Object[]{pinSpec.getLocalizedName(), pinSize}; + } + gui.showMessageDialog(title, message, params); + } + } } diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/PinpadPINProviderFactory.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/PinpadPINProviderFactory.java deleted file mode 100644 index c109ceba..00000000 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/PinpadPINProviderFactory.java +++ /dev/null @@ -1,186 +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.bku.smccstal; - -import at.gv.egiz.bku.gui.BKUGUIFacade; -import at.gv.egiz.smcc.CancelledException; -import at.gv.egiz.smcc.PINProvider; -import at.gv.egiz.smcc.PINSpec; -import at.gv.egiz.stal.signedinfo.SignedInfoType; -import java.security.DigestException; - -/** - * - * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at> - */ -public class PinpadPINProviderFactory extends PINProviderFactory { - - protected PinpadPINProviderFactory(BKUGUIFacade gui) { - this.gui = gui; - } - - @Override - public PINProvider getSignaturePINProvider(SecureViewer viewer, - SignedInfoType signedInfo) { - - return new SignaturePinProvider(viewer, signedInfo); - } - - @Override - public PINProvider getCardPINProvider() { - return new CardPinProvider(); - } - - class SignaturePinProvider extends AbstractPINProvider { - -// protected BKUGUIFacade gui; - protected SecureViewer viewer; - protected ViewerThread viewerThread; - protected SignedInfoType signedInfo; - - - private SignaturePinProvider(SecureViewer viewer, - SignedInfoType signedInfo) { - this.viewer = viewer; - this.signedInfo = signedInfo; - } - - protected class ViewerThread extends Thread { - - PINSpec pinSpec; - int retries; - - public ViewerThread(PINSpec pinSpec, int retries) { - this.pinSpec = pinSpec; - this.retries = retries; - } - - @Override - public void run() { - - try { - - gui.showPinpadSignaturePINDialog(pinSpec, retries, - SignaturePinProvider.this, "secureViewer"); - - while (true) { - waitForAction(); - - if ("secureViewer".equals(action)) { - viewer.displayDataToBeSigned(signedInfo, - SignaturePinProvider.this, "pinEntry"); - } else if ("pinEntry".equals(action)) { - gui.showPinpadSignaturePINDialog(pinSpec, retries, - SignaturePinProvider.this, "secureViewer"); - } else { - log.error("unsupported action command: " + action); - } - } - - } catch (DigestException ex) { - log.error("Bad digest value: " + ex.getMessage()); - gui.showErrorDialog(BKUGUIFacade.ERR_INVALID_HASH, - new Object[]{ex.getMessage()}); - } catch (InterruptedException ex) { - log.info("pinpad secure viewer thread interrupted"); - } catch (Exception ex) { - log.error("Could not display hashdata inputs: " + - ex.getMessage()); - gui.showErrorDialog(BKUGUIFacade.ERR_DISPLAY_HASHDATA, - new Object[]{ex.getMessage()}); - } - } - } - - @Override - public char[] providePIN(PINSpec spec, int retries) - throws CancelledException, InterruptedException { - - if (viewerThread != null) { - updateViewerThread(retries); - } else { - viewerThread = new ViewerThread(spec, -1); - viewerThread.start(); - } -// if (viewerThread != null) { -// log.trace("interrupt old secure viewer thread"); -// viewerThread.interrupt(); -// } -// viewerThread = new ViewerThread(spec, (retry) ? retries : -1); -// log.trace("start new secure viewer thread"); -// viewerThread.start(); - - retry = true; - return null; - } - - private synchronized void updateViewerThread(int retries) { - log.trace("update viewer thread"); - viewerThread.retries = retries; - action = "pinEntry"; - actionPerformed = true; - notify(); - } - - -// @Override -// protected void finalize() throws Throwable { -// if (viewerThread != null) { -// viewerThread.interrupt(); -// } -// log.info("finalizing Pinpad SignaturePinProvider"); -// super.finalize(); -// } - } - - class CardPinProvider extends AbstractPINProvider { - - private CardPinProvider() { - } - - @Override - public char[] providePIN(PINSpec spec, int retries) - throws CancelledException, InterruptedException { - - showPinpadPINDialog(retries, spec); - retry = true; - return null; - - } - - private void showPinpadPINDialog(int retries, PINSpec pinSpec) { - String title, message; - Object[] params; - if (retry) { - title = BKUGUIFacade.TITLE_RETRY; - message = BKUGUIFacade.MESSAGE_RETRIES; - params = new Object[]{String.valueOf(retries)}; - } else { - title = BKUGUIFacade.TITLE_CARDPIN; - message = BKUGUIFacade.MESSAGE_ENTERPIN_PINPAD; - String pinSize = String.valueOf(pinSpec.getMinLength()); - if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { - pinSize += "-" + pinSpec.getMaxLength(); - } - params = new Object[]{pinSpec.getLocalizedName(), pinSize}; - } - gui.showMessageDialog(title, message, params); - } - } - } - diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java index 7a4f6572..56fc8804 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java @@ -50,7 +50,7 @@ public class SignRequestHandler extends AbstractRequestHandler { private static Log log = LogFactory.getLog(SignRequestHandler.class); private static JAXBContext jaxbContext; - private PINProviderFactory pinProviderFactory; +// private PINProviderFactory pinProviderFactory; private SecureViewer secureViewer; static { @@ -86,11 +86,9 @@ public class SignRequestHandler extends AbstractRequestHandler { md.update(signReq.getSignedInfo()); KeyboxName kb = SignatureCard.KeyboxName.getKeyboxName(signReq.getKeyIdentifier()); - if (pinProviderFactory == null) { - pinProviderFactory = PINProviderFactory.getInstance(card, gui); - } - byte[] resp = card.createSignature(md.digest(), kb, - pinProviderFactory.getSignaturePINProvider(secureViewer, si.getValue())); + byte[] resp = card.createSignature(md.digest(), kb, + new PINProviderFactory(card.getReader(), gui) + .getSignaturePINProvider(secureViewer, si.getValue())); if (resp == null) { return new ErrorResponse(6001); } diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SoftwarePINProviderFactory.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SoftwarePINProviderFactory.java deleted file mode 100644 index 7d36c2c3..00000000 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SoftwarePINProviderFactory.java +++ /dev/null @@ -1,137 +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.bku.smccstal; - -import at.gv.egiz.bku.gui.BKUGUIFacade; -import at.gv.egiz.smcc.*; -import at.gv.egiz.stal.HashDataInput; -import at.gv.egiz.stal.signedinfo.SignedInfoType; -import java.security.DigestException; -import java.util.List; - -/** - * - * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at> - */ -public class SoftwarePINProviderFactory extends PINProviderFactory { - - protected SoftwarePINProviderFactory(BKUGUIFacade gui) { - this.gui = gui; - } - - @Override - public PINProvider getSignaturePINProvider(SecureViewer viewer, - SignedInfoType signedInfo) { - return new SignaturePinProvider(viewer, signedInfo); - } - - @Override - public PINProvider getCardPINProvider() { - return new CardPinProvider(); - } - - class SignaturePinProvider extends AbstractPINProvider { - -// protected BKUGUIFacade gui; - protected SecureViewer viewer; - protected SignedInfoType signedInfo; - - private SignaturePinProvider(SecureViewer viewer, - SignedInfoType signedInfo) { - this.viewer = viewer; - this.signedInfo = signedInfo; - } - - @Override - public char[] providePIN(PINSpec spec, int retries) - throws CancelledException, InterruptedException { - - gui.showSignaturePINDialog(spec, (retry) ? retries : -1, - this, "sign", - this, "cancel", - this, "secureViewer"); - - do { - waitForAction(); - - if ("secureViewer".equals(action)) { - try { - viewer.displayDataToBeSigned(signedInfo, this, "pinEntry"); - } catch (DigestException ex) { - log.error("Bad digest value: " + ex.getMessage()); - gui.showErrorDialog(BKUGUIFacade.ERR_INVALID_HASH, - new Object[]{ex.getMessage()}, - this, "error"); - } catch (Exception ex) { - log.error("Could not display hashdata inputs: " + - ex.getMessage()); - gui.showErrorDialog(BKUGUIFacade.ERR_DISPLAY_HASHDATA, - new Object[]{ex.getMessage()}, - this, "error"); - } - } else if ("sign".equals(action)) { - gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, - BKUGUIFacade.MESSAGE_WAIT); - retry = true; - return gui.getPin(); - } else if ("pinEntry".equals(action)) { - gui.showSignaturePINDialog(spec, (retry) ? retries : -1, - this, "sign", - this, "cancel", - this, "secureViewer"); - } else if ("cancel".equals(action) || - "error".equals(action)) { - gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, - BKUGUIFacade.MESSAGE_WAIT); - throw new CancelledException(spec.getLocalizedName() + - " entry cancelled"); - } else { - log.error("unknown action command " + action); - } - } while (true); - } - } - - class CardPinProvider extends AbstractPINProvider { - -// protected BKUGUIFacade gui; - - private CardPinProvider() { - } - - @Override - public char[] providePIN(PINSpec spec, int retries) - throws CancelledException, InterruptedException { - - gui.showCardPINDialog(spec, (retry) ? retries : -1, - this, "ok", - this, "cancel"); - - waitForAction(); - - gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, - BKUGUIFacade.MESSAGE_WAIT); - - if ("cancel".equals(action)) { - throw new CancelledException(spec.getLocalizedName() + - " entry cancelled"); - } - retry = true; - return gui.getPin(); - } - } -} |