diff options
51 files changed, 2905 insertions, 1628 deletions
diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletBKUWorker.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletBKUWorker.java index eb6cf30b..9b9735f6 100644 --- a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletBKUWorker.java +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletBKUWorker.java @@ -60,14 +60,15 @@ public class AppletBKUWorker extends AbstractBKUWorker implements Runnable { @Override public void run() { - gui.showWelcomeDialog(); + gui.showMessageDialog(BKUGUIFacade.TITLE_WELCOME, + BKUGUIFacade.MESSAGE_WELCOME); try { STALPortType stalPort = applet.getSTALPort(); STALTranslator stalTranslator = applet.getSTALTranslator(); addRequestHandler(SignRequest.class, - new AppletHashDataDisplay(stalPort, sessionId)); + new AppletSecureViewer(stalPort, sessionId)); GetNextRequestResponseType nextRequestResp = stalPort.connect(sessionId); diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletHashDataDisplay.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletSecureViewer.java index 2ed9aa5b..e2551e2d 100644 --- a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletHashDataDisplay.java +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletSecureViewer.java @@ -16,6 +16,7 @@ */ package at.gv.egiz.bku.online.applet; +import at.gv.egiz.bku.smccstal.SecureViewer; import java.security.DigestException; import java.security.MessageDigest; import java.util.ArrayList; @@ -45,13 +46,13 @@ import java.security.NoSuchAlgorithmException; * * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at> */ -public class AppletHashDataDisplay extends SignRequestHandler { +public class AppletSecureViewer extends SignRequestHandler { - private static final Log log = LogFactory.getLog(AppletHashDataDisplay.class); + private static final Log log = LogFactory.getLog(AppletSecureViewer.class); protected STALPortType stalPort; protected String sessId; - public AppletHashDataDisplay(STALPortType stalPort, String sessId) { + public AppletSecureViewer(STALPortType stalPort, String sessId) { if (stalPort == null || sessId == null) { throw new NullPointerException("STAL port must not be null"); } @@ -66,13 +67,14 @@ public class AppletHashDataDisplay extends SignRequestHandler { * @throws java.lang.Exception */ @Override - public void displayHashDataInputs(List<ReferenceType> signedReferences) throws DigestException, Exception { + public void displayDataToBeSigned(List<ReferenceType> signedReferences) + throws DigestException, Exception { - List<GetHashDataInputResponseType.Reference> hdi = getHashDataInput(signedReferences); + List<GetHashDataInputResponseType.Reference> hdi = getHashDataInput(signedReferences); List<HashDataInput> verifiedHashDataInputs = verifyHashDataInput(signedReferences, hdi); if (verifiedHashDataInputs.size() > 0) { - gui.showHashDataInputDialog(verifiedHashDataInputs, this, "hashDataDone"); + gui.showSecureViewer(verifiedHashDataInputs, this, "hashDataDone"); } else { throw new Exception("No signature data (apart from any QualifyingProperties or a Manifest)"); } @@ -84,7 +86,8 @@ public class AppletHashDataDisplay extends SignRequestHandler { * @return * @throws at.gv.egiz.stal.service.GetHashDataInputFault */ - private List<GetHashDataInputResponseType.Reference> getHashDataInput(List<ReferenceType> signedReferences) throws GetHashDataInputFault, Exception { + private List<GetHashDataInputResponseType.Reference> getHashDataInput(List<ReferenceType> signedReferences) + throws GetHashDataInputFault, Exception { GetHashDataInputType request = new GetHashDataInputType(); request.setSessionId(sessId); @@ -129,7 +132,8 @@ public class AppletHashDataDisplay extends SignRequestHandler { * @throws java.security.NoSuchAlgorithmException * @throws Exception if no hashdata input is provided for a signed reference */ - private List<HashDataInput> verifyHashDataInput(List<ReferenceType> signedReferences, List<GetHashDataInputResponseType.Reference> hashDataInputs) throws DigestException, NoSuchAlgorithmException, Exception { + private List<HashDataInput> verifyHashDataInput(List<ReferenceType> signedReferences, List<GetHashDataInputResponseType.Reference> hashDataInputs) + throws DigestException, NoSuchAlgorithmException, Exception { ArrayList<HashDataInput> verifiedHashDataInputs = new ArrayList<HashDataInput>(); diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java index c904be0c..159dd29d 100644 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java @@ -56,8 +56,6 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac /** remember the pinSpec to return to worker */ protected PINSpec pinSpec; - protected enum DIALOG { VERIFY, ACTIVATE, CHANGE, UNBLOCK }; - public PINManagementGUI(Container contentPane, Locale locale, Style guiStyle, @@ -235,43 +233,110 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac } @Override - public void showActivatePINDialog(final PINSpec pin, - final ActionListener okListener, final String okCommand, - final ActionListener cancelListener, final String cancelCommand) { - log.debug("scheduling activate pin dialog"); - showPINDialog(DIALOG.ACTIVATE, pin, okListener, okCommand, cancelListener, cancelCommand); + public void showPINDialog(DIALOG type, PINSpec pinSpec, + ActionListener okListener, String okCommand, + ActionListener cancelListener, String cancelCommand) { + showPINDialog(type, pinSpec, -1, false, + okListener, okCommand, cancelListener, cancelCommand); + } + + @Override + public void showPINDialog(DIALOG type, PINSpec pinSpec, int retries, + ActionListener okListener, String okCommand, + ActionListener cancelListener, String cancelCommand) { + showPINDialog(type, pinSpec, retries, false, + okListener, okCommand, cancelListener, cancelCommand); } + @Override + public void showPinpadPINDialog(DIALOG type, PINSpec pinSpec, int retries) { + String title, msg; + Object[] params; + if (retries < 0) { + params = new Object[2]; + if (shortText) { + params[0] = "PIN"; + } else { + params[0] = pinSpec.getLocalizedName(); + } + String pinSize = String.valueOf(pinSpec.getMinLength()); + if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { + pinSize += "-" + pinSpec.getMaxLength(); + } + params[1] = pinSize; + if (type == DIALOG.CHANGE) { + log.debug("show change pin dialog"); + title = TITLE_CHANGE_PIN; + msg = MESSAGE_CHANGEPIN_PINPAD; + } else if (type == DIALOG.ACTIVATE) { + log.debug("show activate pin dialog"); + title = TITLE_ACTIVATE_PIN; + msg = MESSAGE_ENTERPIN_PINPAD; + } else if (type == DIALOG.VERIFY) { + log.debug("show verify pin dialog"); + title = TITLE_VERIFY_PIN; + msg = MESSAGE_ENTERPIN_PINPAD; + } else { + log.debug("show unblock pin dialog"); + title = TITLE_UNBLOCK_PIN; + msg = MESSAGE_ENTERPIN_PINPAD; + } + + } else { + log.debug("show retry pin dialog"); + title = TITLE_RETRY; + msg = (retries < 2) ? + MESSAGE_LAST_RETRY : MESSAGE_RETRIES; + params = new Object[] {String.valueOf(retries)}; + } + showMessageDialog(title, msg, params); + } private void showPINDialog(final DIALOG type, final PINSpec pinSpec, + final int retries, final boolean pinpad, final ActionListener okListener, final String okCommand, final ActionListener cancelListener, final String cancelCommand) { + log.debug("scheduling pin dialog"); + SwingUtilities.invokeLater(new Runnable() { @Override public void run() { - String HELP_TOPIC, TITLE, MESSAGE_MGMT; + String HELP_TOPIC, TITLE, MESSAGE_MGMT, MESSAGE_MGMT_PARAM; HELP_TOPIC = HELP_PINMGMT; - if (type == DIALOG.CHANGE) { - log.debug("show change pin dialog"); - TITLE = TITLE_CHANGE_PIN; - MESSAGE_MGMT = MESSAGE_CHANGE_PIN; - } else if (type == DIALOG.ACTIVATE) { - log.debug("show activate pin dialog"); - TITLE = TITLE_ACTIVATE_PIN; - MESSAGE_MGMT = MESSAGE_ACTIVATE_PIN; - oldPinField = null; - } else if (type == DIALOG.VERIFY) { - log.debug("show verify pin dialog"); - TITLE = TITLE_VERIFY_PIN; - MESSAGE_MGMT = MESSAGE_VERIFY_PIN; + if (retries < 0) { + if (type == DIALOG.CHANGE) { + log.debug("show change pin dialog"); + TITLE = TITLE_CHANGE_PIN; + MESSAGE_MGMT = MESSAGE_CHANGE_PIN; + } else if (type == DIALOG.ACTIVATE) { + log.debug("show activate pin dialog"); + TITLE = TITLE_ACTIVATE_PIN; + MESSAGE_MGMT = MESSAGE_ACTIVATE_PIN; + oldPinField = null; + } else if (type == DIALOG.VERIFY) { + log.debug("show verify pin dialog"); + TITLE = TITLE_VERIFY_PIN; + MESSAGE_MGMT = MESSAGE_VERIFY_PIN; + } else { + log.debug("show unblock pin dialog"); + TITLE = TITLE_UNBLOCK_PIN; + MESSAGE_MGMT = MESSAGE_UNBLOCK_PIN; + } + if (shortText) { + MESSAGE_MGMT_PARAM = "PIN"; + } else { + MESSAGE_MGMT_PARAM = pinSpec.getLocalizedName(); + } } else { - log.debug("show unblock pin dialog"); - TITLE = TITLE_UNBLOCK_PIN; - MESSAGE_MGMT = MESSAGE_UNBLOCK_PIN; + log.debug("show retry pin dialog"); + TITLE = TITLE_RETRY; + MESSAGE_MGMT = (retries < 2) ? + MESSAGE_LAST_RETRY : MESSAGE_RETRIES; + MESSAGE_MGMT_PARAM = String.valueOf(retries); } mainPanel.removeAll(); @@ -280,24 +345,67 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac helpListener.setHelpTopic(HELP_TOPIC); JLabel mgmtLabel = new JLabel(); - mgmtLabel.setFont(mgmtLabel.getFont().deriveFont(mgmtLabel.getFont().getStyle() & ~Font.BOLD)); + if (retries < 0) { + mgmtLabel.setFont(mgmtLabel.getFont().deriveFont(mgmtLabel.getFont().getStyle() & ~Font.BOLD)); + } else { + mgmtLabel.setFont(mgmtLabel.getFont().deriveFont(mgmtLabel.getFont().getStyle() | Font.BOLD)); + mgmtLabel.setForeground(ERROR_COLOR); + helpListener.setHelpTopic(HELP_RETRY); + } if (renderHeaderPanel) { titleLabel.setText(getMessage(TITLE)); String mgmtPattern = getMessage(MESSAGE_MGMT); - if (shortText) { - mgmtLabel.setText(MessageFormat.format(mgmtPattern, "PIN")); - } else { - mgmtLabel.setText(MessageFormat.format(mgmtPattern, pinSpec.getLocalizedName())); - } + mgmtLabel.setText(MessageFormat.format(mgmtPattern, MESSAGE_MGMT_PARAM)); } else { mgmtLabel.setText(getMessage(TITLE)); } + String pinSize = String.valueOf(pinSpec.getMinLength()); + if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { + pinSize += "-" + pinSpec.getMaxLength(); + } + + //////////////////////////////////////////////////////////////// + // COMMON LAYOUT SECTION + //////////////////////////////////////////////////////////////// + + GroupLayout mainPanelLayout = new GroupLayout(mainPanel); + mainPanel.setLayout(mainPanelLayout); + + GroupLayout.SequentialGroup infoHorizontal = mainPanelLayout.createSequentialGroup() + .addComponent(mgmtLabel); + GroupLayout.ParallelGroup infoVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(mgmtLabel); + + if (!renderHeaderPanel) { + infoHorizontal + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) + .addComponent(helpLabel); + infoVertical + .addComponent(helpLabel); + } + + GroupLayout.ParallelGroup pinHorizontal; + GroupLayout.SequentialGroup pinVertical; + + if (pinpad) { + JLabel pinpadLabel = new JLabel(); + pinpadLabel.setFont(mgmtLabel.getFont().deriveFont(mgmtLabel.getFont().getStyle() & ~Font.BOLD)); + String pinpadPattern = getMessage(MESSAGE_PINPAD); + pinpadLabel.setText(MessageFormat.format(pinpadPattern, + new Object[] { pinSpec.getLocalizedName(), pinSize })); + + pinHorizontal = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(pinpadLabel); + pinVertical = mainPanelLayout.createSequentialGroup() + .addComponent(pinpadLabel); + } else { + JButton okButton = new JButton(); okButton.setFont(okButton.getFont().deriveFont(okButton.getFont().getStyle() & ~Font.BOLD)); okButton.setText(getMessage(BUTTON_OK)); - okButton.setEnabled(type == DIALOG.VERIFY && pinSpec.getMinLength() == 0); + okButton.setEnabled(pinSpec.getMinLength() <= 0); okButton.setActionCommand(okCommand); okButton.addActionListener(okListener); @@ -334,7 +442,7 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac repeatPinLabel.setText(MessageFormat.format(repeatPinLabelPattern, new Object[]{pinSpec.getLocalizedName()})); repeatPinField.setText(""); - repeatPinField.setDocument(new PINDocument(pinSpec, okButton, pinField.getDocument())); +// repeatPinField.setDocument(new PINDocument(pinSpec, okButton, pinField.getDocument())); repeatPinField.setActionCommand(okCommand); repeatPinField.addActionListener(new ActionListener() { @@ -365,7 +473,15 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac } } }); - } // else -> ACTIVATE (not verify, not change) + + repeatPinField.setDocument(new PINDocument( + pinSpec, okButton, + pinField.getDocument(), oldPinField.getDocument())); + } else { + // else -> ACTIVATE (not verify, not change) + repeatPinField.setDocument(new PINDocument( + pinSpec, okButton, pinField.getDocument())); + } } else { pinField.setDocument(new PINDocument(pinSpec, okButton)); } @@ -373,30 +489,14 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac JLabel pinsizeLabel = new JLabel(); pinsizeLabel.setFont(pinsizeLabel.getFont().deriveFont(pinsizeLabel.getFont().getStyle() & ~Font.BOLD, pinsizeLabel.getFont().getSize()-2)); String pinsizePattern = getMessage(LABEL_PINSIZE); - String pinSize = String.valueOf(pinSpec.getMinLength()); - if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { - pinSize += "-" + pinSpec.getMaxLength(); - } pinsizeLabel.setText(MessageFormat.format(pinsizePattern, new Object[]{pinSize})); - GroupLayout mainPanelLayout = new GroupLayout(mainPanel); - mainPanel.setLayout(mainPanelLayout); - - GroupLayout.SequentialGroup infoHorizontal = mainPanelLayout.createSequentialGroup() - .addComponent(mgmtLabel); - GroupLayout.ParallelGroup infoVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(mgmtLabel); - - if (!renderHeaderPanel) { - infoHorizontal - .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) - .addComponent(helpLabel); - infoVertical - .addComponent(helpLabel); - } + //////////////////////////////////////////////////////////////// + // NON-PINPAD SPECIFIC LAYOUT SECTION + //////////////////////////////////////////////////////////////// - GroupLayout.ParallelGroup pinHorizontal = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING); - GroupLayout.SequentialGroup pinVertical = mainPanelLayout.createSequentialGroup(); + pinHorizontal = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING); + pinVertical = mainPanelLayout.createSequentialGroup(); // if (pinLabelPos == PinLabelPosition.ABOVE) { // if (changePin) { @@ -495,7 +595,38 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac .addComponent(pinsizeLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)); pinVertical .addComponent(pinsizeLabel); -// } + + GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); + buttonPanel.setLayout(buttonPanelLayout); + + GroupLayout.SequentialGroup buttonHorizontal = buttonPanelLayout.createSequentialGroup() + .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(okButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE); + GroupLayout.Group buttonVertical; + + JButton cancelButton = new JButton(); + cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD)); + cancelButton.setText(getMessage(BUTTON_CANCEL)); + cancelButton.setActionCommand(cancelCommand); + cancelButton.addActionListener(cancelListener); + + buttonHorizontal + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE); + buttonVertical = buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) + .addComponent(okButton) + .addComponent(cancelButton); + + buttonPanelLayout.setHorizontalGroup(buttonHorizontal); + buttonPanelLayout.setVerticalGroup(buttonVertical); + + if (oldPinField != null) { + oldPinField.requestFocusInWindow(); + } else { + pinField.requestFocusInWindow(); + } + + } // END NON-PINPAD SECTION mainPanelLayout.setHorizontalGroup( mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) @@ -508,35 +639,6 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) .addGroup(pinVertical)); - GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); - buttonPanel.setLayout(buttonPanelLayout); - - GroupLayout.SequentialGroup buttonHorizontal = buttonPanelLayout.createSequentialGroup() - .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(okButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE); - GroupLayout.Group buttonVertical; - - JButton cancelButton = new JButton(); - cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD)); - cancelButton.setText(getMessage(BUTTON_CANCEL)); - cancelButton.setActionCommand(cancelCommand); - cancelButton.addActionListener(cancelListener); - - buttonHorizontal - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE); - buttonVertical = buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) - .addComponent(okButton) - .addComponent(cancelButton); - - buttonPanelLayout.setHorizontalGroup(buttonHorizontal); - buttonPanelLayout.setVerticalGroup(buttonVertical); - - if (oldPinField != null) { - oldPinField.requestFocusInWindow(); - } else { - pinField.requestFocusInWindow(); - } contentPanel.validate(); } @@ -544,97 +646,6 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac } @Override - public void showChangePINDialog(final PINSpec pin, - final ActionListener okListener, final String okCommand, - final ActionListener cancelListener, final String cancelCommand) { - - log.debug("scheduling change pin dialog"); - showPINDialog(DIALOG.CHANGE, pin, okListener, okCommand, cancelListener, cancelCommand); - } - - @Override - public void showUnblockPINDialog(final PINSpec pin, - final ActionListener okListener, final String okCommand, - final ActionListener cancelListener, final String cancelCommand) { - - log.debug("scheduling unblock PIN dialog"); - - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - - log.debug("show unblock PIN dialog"); - - log.error("unblock pin not supported"); - - mainPanel.removeAll(); - buttonPanel.removeAll(); - - if (renderHeaderPanel) { - titleLabel.setText(getMessage(TITLE_ERROR)); - } - - helpListener.setHelpTopic(HELP_PINMGMT); - - String errorMsgPattern = getMessage(ERR_UNBLOCK); - String errorMsg = MessageFormat.format(errorMsgPattern, pin.getLocalizedName()); - - JLabel errorMsgLabel = new JLabel(); - errorMsgLabel.setFont(errorMsgLabel.getFont().deriveFont(errorMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); - errorMsgLabel.setText(errorMsg); - - GroupLayout mainPanelLayout = new GroupLayout(mainPanel); - mainPanel.setLayout(mainPanelLayout); - - GroupLayout.ParallelGroup mainHorizontal = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING); - GroupLayout.SequentialGroup mainVertical = mainPanelLayout.createSequentialGroup(); - - if (!renderHeaderPanel) { - JLabel errorTitleLabel = new JLabel(); - errorTitleLabel.setFont(errorTitleLabel.getFont().deriveFont(errorTitleLabel.getFont().getStyle() | java.awt.Font.BOLD)); - errorTitleLabel.setText(getMessage(TITLE_ERROR)); - errorTitleLabel.setForeground(ERROR_COLOR); - - mainHorizontal - .addGroup(mainPanelLayout.createSequentialGroup() - .addComponent(errorTitleLabel) - .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) - .addComponent(helpLabel)); - mainVertical - .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(errorTitleLabel) - .addComponent(helpLabel)); - } - - mainPanelLayout.setHorizontalGroup(mainHorizontal - .addComponent(errorMsgLabel)); - mainPanelLayout.setVerticalGroup(mainVertical - .addComponent(errorMsgLabel)); - - JButton okButton = new JButton(); - okButton.setFont(okButton.getFont().deriveFont(okButton.getFont().getStyle() & ~java.awt.Font.BOLD)); - okButton.setText(getMessage(BUTTON_OK)); - okButton.setActionCommand(cancelCommand); - okButton.addActionListener(cancelListener); - - GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); - buttonPanel.setLayout(buttonPanelLayout); - - buttonPanelLayout.setHorizontalGroup( - buttonPanelLayout.createSequentialGroup() - .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(okButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)); - buttonPanelLayout.setVerticalGroup( - buttonPanelLayout.createSequentialGroup() - .addComponent(okButton)); - - contentPanel.validate(); - } - }); - } - - @Override protected int initButtonSize() { int bs = super.initButtonSize(); @@ -659,8 +670,4 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac return bs; } - @Override - public void showVerifyPINDialog(PINSpec pin, ActionListener okListener, String okCmd, ActionListener cancelListener, String cancelCmd) { - showPINDialog(DIALOG.VERIFY, pin, okListener, okCmd, cancelListener, cancelCmd); - } } 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 9c630431..45313f42 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 @@ -35,13 +35,18 @@ public interface PINManagementGUIFacade extends BKUGUIFacade { public static final String TITLE_UNBLOCK_PIN = "title.unblock.pin"; public static final String TITLE_ACTIVATE_SUCCESS = "title.activate.success"; public static final String TITLE_CHANGE_SUCCESS = "title.change.success"; - public static final String MESSAGE_ACTIVATE_SUCCESS = "message.activate.success"; - public static final String MESSAGE_CHANGE_SUCCESS = "message.change.success"; - public static final String MESSAGE_PINMGMT = "message.pin.mgmt"; - public static final String MESSAGE_ACTIVATE_PIN = "message.activate.pin"; - public static final String MESSAGE_CHANGE_PIN = "message.change.pin"; - public static final String MESSAGE_VERIFY_PIN = "message.verify.pin"; - public static final String MESSAGE_UNBLOCK_PIN = "message.unblock.pin"; + + // removed message.* prefix to reuse keys as help keys + public static final String MESSAGE_ACTIVATE_SUCCESS = "activate.success"; + public static final String MESSAGE_CHANGE_SUCCESS = "change.success"; + public static final String MESSAGE_PINMGMT = "pin.mgmt"; + public static final String MESSAGE_PINPAD = "pinpad"; + public static final String MESSAGE_CHANGEPIN_PINPAD = "pinpad.change"; + public static final String MESSAGE_ACTIVATE_PIN = "activate.pin"; + public static final String MESSAGE_CHANGE_PIN = "change.pin"; + public static final String MESSAGE_VERIFY_PIN = "verify.pin"; + public static final String MESSAGE_UNBLOCK_PIN = "unblock.pin"; + public static final String LABEL_OLD_PIN = "label.old.pin"; public static final String LABEL_NEW_PIN = "label.new.pin"; public static final String LABEL_REPEAT_PIN = "label.repeat.pin"; @@ -66,26 +71,37 @@ public interface PINManagementGUIFacade extends BKUGUIFacade { public static final String STATUS_UNKNOWN = "status.unknown"; public enum STATUS { ACTIV, NOT_ACTIV, BLOCKED, UNKNOWN }; + public enum DIALOG { VERIFY, ACTIVATE, CHANGE, UNBLOCK }; public void showPINManagementDialog(Map<PINSpec, STATUS> pins, ActionListener activateListener, String activateCmd, String changeCmd, String unblockCmd, String verifyCmd, ActionListener cancelListener, String cancelCmd); - public void showActivatePINDialog(PINSpec pin, + public void showPINDialog(DIALOG type, PINSpec pin, ActionListener okListener, String okCmd, ActionListener cancelListener, String cancelCmd); - public void showChangePINDialog(PINSpec pin, + public void showPINDialog(DIALOG type, PINSpec pin, int retries, ActionListener okListener, String okCmd, ActionListener cancelListener, String cancelCmd); - public void showUnblockPINDialog(PINSpec pin, - ActionListener okListener, String okCmd, - ActionListener cancelListener, String cancelCmd); + public void showPinpadPINDialog(DIALOG type, PINSpec pin, int retries); - public void showVerifyPINDialog(PINSpec pin, - ActionListener okListener, String okCmd, - ActionListener cancelListener, String cancelCmd); +// public void showActivatePINDialog(PINSpec pin, +// ActionListener okListener, String okCmd, +// ActionListener cancelListener, String cancelCmd); +// +// public void showChangePINDialog(PINSpec pin, +// ActionListener okListener, String okCmd, +// ActionListener cancelListener, String cancelCmd); +// +// public void showUnblockPINDialog(PINSpec pin, +// ActionListener okListener, String okCmd, +// ActionListener cancelListener, String cancelCmd); +// +// public void showVerifyPINDialog(PINSpec pin, +// ActionListener okListener, String okCmd, +// ActionListener cancelListener, String cancelCmd); public char[] getOldPin(); diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/PINManagementBKUWorker.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/PINManagementBKUWorker.java index 85892026..81b635f8 100644 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/PINManagementBKUWorker.java +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/PINManagementBKUWorker.java @@ -42,7 +42,8 @@ public class PINManagementBKUWorker extends AppletBKUWorker { @Override public void run() { - gui.showWelcomeDialog(); + gui.showMessageDialog(BKUGUIFacade.TITLE_WELCOME, + BKUGUIFacade.MESSAGE_WELCOME); try { List<STALResponse> responses = handleRequest(Collections.singletonList(new PINManagementRequest())); @@ -53,7 +54,6 @@ public class PINManagementBKUWorker extends AppletBKUWorker { log.debug("PIN management dialog terminated"); } else if (response instanceof ErrorResponse) { log.debug("PIN management dialog terminated with error"); - showErrorDialog(BKUGUIFacade.ERR_UNKNOWN, null); } else { throw new RuntimeException("Invalid STAL response: " + response.getClass().getName()); } @@ -62,7 +62,11 @@ public class PINManagementBKUWorker extends AppletBKUWorker { } } catch (RuntimeException ex) { - log.error("unexpected error: " + ex.getMessage(), ex); + log.error(ex.getMessage()); + Throwable cause = ex.getCause(); + if (cause != null) { // && cause instanceof InterruptedException) { + log.info(cause.getMessage()); + } showErrorDialog(BKUGUIFacade.ERR_UNKNOWN, null); } catch (Exception ex) { log.error(ex.getMessage(), ex); 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 new file mode 100644 index 00000000..b0dd8766 --- /dev/null +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/ManagementPINProviderFactory.java @@ -0,0 +1,53 @@ +/* + * 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.PINManagementGUIFacade; +import at.gv.egiz.smcc.PINProvider; +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 { + + PINManagementGUIFacade gui; + + public static ManagementPINProviderFactory getInstance(SignatureCard forCard, + PINManagementGUIFacade gui) { +// if (forCard.ifdSupportsFeature(SignatureCard.FEATURE_VERIFY_PIN_DIRECT)) { +//// forCard.ifdSupportsFeature(SignatureCard.FEATURE_MODIFY_PIN_DIRECT) +// return new PinpadPINProviderFactory(gui); +// +// } else { + return new SoftwarePINProviderFactory(gui); +// } + } + + public abstract PINProvider getVerifyPINProvider(); + + public abstract PINProvider getActivatePINProvider(); + + public abstract ChangePINProvider getChangePINProvider(); + + public abstract PINProvider getUnblockPINProvider(); + +} 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 66db0484..6b565b26 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 @@ -18,13 +18,19 @@ package at.gv.egiz.bku.smccstal.ext; 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.gui.PINManagementGUIFacade.STATUS; import at.gv.egiz.bku.smccstal.AbstractRequestHandler; +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.PINProvider; import at.gv.egiz.smcc.PINSpec; import at.gv.egiz.smcc.STARCOSCard; +import at.gv.egiz.smcc.SignatureCard; import at.gv.egiz.smcc.SignatureCardException; +import at.gv.egiz.smcc.TimeoutException; import at.gv.egiz.smcc.VerificationFailedException; import at.gv.egiz.smcc.util.SMCCHelper; import at.gv.egiz.stal.ErrorResponse; @@ -35,8 +41,6 @@ import at.gv.egiz.stal.ext.PINManagementResponse; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; import javax.smartcardio.Card; import javax.smartcardio.CardChannel; import javax.smartcardio.CardException; @@ -53,7 +57,8 @@ public class PINManagementRequestHandler extends AbstractRequestHandler { protected static final Log log = LogFactory.getLog(PINManagementRequestHandler.class); - Map<PINSpec, STATUS> pinStatuses; + protected Map<PINSpec, STATUS> pinStatuses; + private ManagementPINProviderFactory pinProviderFactory; @Override public STALResponse handleRequest(STALRequest request) throws InterruptedException { @@ -61,9 +66,12 @@ public class PINManagementRequestHandler extends AbstractRequestHandler { PINManagementGUIFacade gui = (PINManagementGUIFacade) this.gui; + PINSpec selectedPIN = null; + try { - pinStatuses = getPINStatuses(); + pinStatuses = getPINStatuses(); + gui.showPINManagementDialog(pinStatuses, this, "activate_enterpin", "change_enterpin", "unblock_enterpuk", "verify_enterpin", this, "cancel"); @@ -74,175 +82,100 @@ public class PINManagementRequestHandler extends AbstractRequestHandler { if ("cancel".equals(actionCommand)) { return new PINManagementResponse(); - } else if ("back".equals(actionCommand)) { - gui.showPINManagementDialog(pinStatuses, - this, "activate_enterpin", "change_enterpin", "unblock_enterpuk", "verify_enterpin", - this, "cancel"); } else { - PINSpec selectedPIN = gui.getSelectedPINSpec(); + selectedPIN = gui.getSelectedPINSpec(); if (selectedPIN == null) { - throw new RuntimeException("no PIN selected for activation/change"); + throw new NullPointerException("no PIN selected for activation/change"); } - if ("activate_enterpin".equals(actionCommand)) { - gui.showActivatePINDialog(selectedPIN, - this, "activate", this, "back"); - } else if ("change_enterpin".equals(actionCommand)) { - gui.showChangePINDialog(selectedPIN, - this, "change", this, "back"); - } else if ("unblock_enterpuk".equals(actionCommand)) { - gui.showUnblockPINDialog(selectedPIN, - this, "unblock", this, "back"); - } else if ("verify_enterpin".equals(actionCommand)) { - gui.showVerifyPINDialog(selectedPIN, - this, "verify", this, "back"); - } else if ("activate".equals(actionCommand)) { - try { - log.debug("activate " + selectedPIN.getLocalizedName()); - card.activatePIN(selectedPIN, - String.valueOf(gui.getPin())); + if (pinProviderFactory == null) { + pinProviderFactory = + ManagementPINProviderFactory.getInstance(card, gui); + } + + try { + if ("activate_enterpin".equals(actionCommand)) { + log.info("activate " + selectedPIN.getLocalizedName()); + card.activatePIN(selectedPIN, + pinProviderFactory.getActivatePINProvider()); updatePINStatus(selectedPIN, STATUS.ACTIV); gui.showMessageDialog(PINManagementGUIFacade.TITLE_ACTIVATE_SUCCESS, PINManagementGUIFacade.MESSAGE_ACTIVATE_SUCCESS, new Object[] {selectedPIN.getLocalizedName()}, - this, "ok"); + BKUGUIFacade.BUTTON_OK, this, "ok"); waitForAction(); - gui.showPINManagementDialog(pinStatuses, - this, "activate_enterpin", "change_enterpin", "unblock_enterpuk", "verify_enterpin", - this, "cancel"); - } catch (GetPINStatusException ex) { - log.error("failed to get " + selectedPIN.getLocalizedName() + - " status: " + ex.getMessage()); - gui.showErrorDialog(PINManagementGUIFacade.ERR_STATUS, null, - this, "cancel"); - } catch (SignatureCardException ex) { - log.error("failed to activate " + selectedPIN.getLocalizedName() + - ": " + ex.getMessage()); - gui.showErrorDialog(PINManagementGUIFacade.ERR_ACTIVATE, - new Object[] {selectedPIN.getLocalizedName()}, - this, "cancel"); - } - } else if ("change".equals(actionCommand)) { - log.info("change " + selectedPIN.getLocalizedName()); - try { - card.changePIN(selectedPIN, - String.valueOf(gui.getOldPin()), - String.valueOf(gui.getPin())); + } else if ("change_enterpin".equals(actionCommand)) { + log.info("change " + selectedPIN.getLocalizedName()); + card.changePIN(selectedPIN, + pinProviderFactory.getChangePINProvider()); updatePINStatus(selectedPIN, STATUS.ACTIV); gui.showMessageDialog(PINManagementGUIFacade.TITLE_CHANGE_SUCCESS, PINManagementGUIFacade.MESSAGE_CHANGE_SUCCESS, new Object[] {selectedPIN.getLocalizedName()}, - this, "ok"); - waitForAction(); - gui.showPINManagementDialog(pinStatuses, - this, "activate_enterpin", "change_enterpin", "unblock_enterpuk", "verify_enterpin", - this, "cancel"); - } catch (GetPINStatusException ex) { - log.error("failed to get " + selectedPIN.getLocalizedName() + - " status: " + ex.getMessage()); - gui.showErrorDialog(PINManagementGUIFacade.ERR_STATUS, null, - this, "cancel"); - } catch (LockedException ex) { - log.error("failed to change " + selectedPIN.getLocalizedName() + - ": PIN locked"); - updatePINStatus(selectedPIN, STATUS.BLOCKED); - gui.showErrorDialog(PINManagementGUIFacade.ERR_LOCKED, - new Object[] {selectedPIN.getLocalizedName()}, - this, "ok"); - waitForAction(); - gui.showPINManagementDialog(pinStatuses, - this, "activate_enterpin", "change_enterpin", "unblock_enterpuk", "verify_enterpin", - this, "cancel"); - } catch (VerificationFailedException ex) { - log.error("failed to change " + selectedPIN.getLocalizedName() + - ": " + ex.getMessage()); - gui.showErrorDialog(PINManagementGUIFacade.ERR_RETRIES, - new Object[] {selectedPIN.getLocalizedName(), ex.getRetries()}, - this, "change_enterpin"); - } catch (NotActivatedException ex) { - log.error("failed to change " + selectedPIN.getLocalizedName() + - ": PIN not active"); - updatePINStatus(selectedPIN, STATUS.NOT_ACTIV); - gui.showErrorDialog(PINManagementGUIFacade.ERR_NOT_ACTIVE, - new Object[] {selectedPIN.getLocalizedName()}, - this, "ok"); + BKUGUIFacade.BUTTON_OK, this, "ok"); waitForAction(); - gui.showPINManagementDialog(pinStatuses, - this, "activate_enterpin", "change_enterpin", "unblock_enterpuk", "verify_enterpin", - this, "cancel"); - } catch (SignatureCardException ex) { - log.error("failed to change " + selectedPIN.getLocalizedName() + - ": " + ex.getMessage()); - gui.showErrorDialog(PINManagementGUIFacade.ERR_CHANGE, - new Object[] {selectedPIN.getLocalizedName()}, - this, "cancel"); - } - } else if ("unblock".equals(actionCommand)) { - log.info("unblock " + selectedPIN.getLocalizedName()); - log.error("unblock PIN not implemented"); - gui.showErrorDialog(PINManagementGUIFacade.ERR_UNBLOCK, null, this, "cancel"); - } else if ("verify".equals(actionCommand)) { - try { + + } else if ("unblock_enterpuk".equals(actionCommand)) { + log.info("unblock " + selectedPIN.getLocalizedName()); + card.unblockPIN(selectedPIN, + pinProviderFactory.getUnblockPINProvider()); + } else if ("verify_enterpin".equals(actionCommand)) { log.info("verify " + selectedPIN.getLocalizedName()); - int retries = card.verifyPIN(selectedPIN, String.valueOf(gui.getPin())); - log.trace(retries + " retries"); - if (retries < 0) { - updatePINStatus(selectedPIN, STATUS.ACTIV); - gui.showPINManagementDialog(pinStatuses, - this, "activate_enterpin", "change_enterpin", "unblock_enterpuk", "verify_enterpin", - this, "cancel"); - } else { - log.error("failed to verify " + selectedPIN.getLocalizedName() + - ": " + retries + " retries left"); - gui.showErrorDialog(PINManagementGUIFacade.ERR_RETRIES, - new Object[] {selectedPIN.getLocalizedName(), retries}, - this, "verify_enterpin"); - } - } catch (GetPINStatusException ex) { - log.error("failed to get " + selectedPIN.getLocalizedName() + - " status: " + ex.getMessage()); - gui.showErrorDialog(PINManagementGUIFacade.ERR_STATUS, null, - this, "cancel"); - } catch (LockedException ex) { - log.error("failed to verify " + selectedPIN.getLocalizedName() + - ": PIN locked"); - updatePINStatus(selectedPIN, STATUS.BLOCKED); - gui.showPINManagementDialog(pinStatuses, - this, "activate_enterpin", "change_enterpin", "unblock_enterpuk", "verify_enterpin", - this, "cancel"); - } catch (NotActivatedException ex) { - log.error("failed to verify " + selectedPIN.getLocalizedName() + - ": PIN not active"); - updatePINStatus(selectedPIN, STATUS.NOT_ACTIV); - gui.showPINManagementDialog(pinStatuses, - this, "activate_enterpin", "change_enterpin", "unblock_enterpuk", "verify_enterpin", - this, "cancel"); - } catch (SignatureCardException ex) { - log.error("failed to verify " + selectedPIN.getLocalizedName() + - ": " + ex.getMessage()); - gui.showErrorDialog(PINManagementGUIFacade.ERR_STATUS, - new Object[] {selectedPIN.getLocalizedName()}, - this, "cancel"); + card.verifyPIN(selectedPIN, + pinProviderFactory.getVerifyPINProvider()); + updatePINStatus(selectedPIN, STATUS.ACTIV); } - - } else { - throw new RuntimeException("unsupported action " + actionCommand); + } catch (CancelledException ex) { + log.trace("cancelled"); + } catch (TimeoutException ex) { + log.error("Timeout during pin entry"); + gui.showMessageDialog(BKUGUIFacade.TITLE_ENTRY_TIMEOUT, + BKUGUIFacade.ERR_PIN_TIMEOUT, + new Object[] {selectedPIN.getLocalizedName()}, + BKUGUIFacade.BUTTON_OK, this, null); + waitForAction(); + } catch (LockedException ex) { + log.error(selectedPIN.getLocalizedName() + " locked"); + updatePINStatus(selectedPIN, STATUS.BLOCKED); + gui.showErrorDialog(PINManagementGUIFacade.ERR_LOCKED, + new Object[] {selectedPIN.getLocalizedName()}, + this, null); + waitForAction(); + } catch (NotActivatedException ex) { + log.error(selectedPIN.getLocalizedName() + " not active"); + updatePINStatus(selectedPIN, STATUS.NOT_ACTIV); + gui.showErrorDialog(PINManagementGUIFacade.ERR_NOT_ACTIVE, + new Object[] {selectedPIN.getLocalizedName()}, + this, null); + waitForAction(); } - } - } + } // end if + + selectedPIN = null; + gui.showPINManagementDialog(pinStatuses, + this, "activate_enterpin", "change_enterpin", "unblock_enterpuk", "verify_enterpin", + this, "cancel"); + } // end while + } catch (GetPINStatusException ex) { - log.error("Failed to get PIN statuses: " + ex.getMessage()); + String pin = (selectedPIN != null) ? selectedPIN.getLocalizedName() : "pin"; + log.error("failed to get " + pin + " status: " + ex.getMessage()); gui.showErrorDialog(PINManagementGUIFacade.ERR_STATUS, null, this, "ok"); waitForAction(); return new ErrorResponse(1000); + } catch (SignatureCardException ex) { + log.error(ex.getMessage(), ex); + gui.showErrorDialog(PINManagementGUIFacade.ERR_UNKNOWN, null, + this, "ok"); + waitForAction(); + return new ErrorResponse(1000); } } else { log.error("Got unexpected STAL request: " + request); return new ErrorResponse(1000); } - } @Override @@ -375,4 +308,100 @@ public class PINManagementRequestHandler extends AbstractRequestHandler { pinStatuses.put(pinSpec, status); } } + +// /** +// * provides oldPin and newPin from one dialog, +// * and don't know whether providePIN() or provideOldPIN() is called first. +// */ +// class SoftwarePinProvider implements PINProvider { +// +// private PINManagementGUIFacade.DIALOG type; +// private boolean retry = false; +// +// private char[] newPin; +// private char[] oldPin; +// +// public SoftwarePinProvider(DIALOG type) { +// this.type = type; +// } +// +// @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 = +// (PINManagementGUIFacade) PINManagementRequestHandler.this.gui; +// +// if (retry) { +// gui.showPINDialog(type, spec, retries, +// PINManagementRequestHandler.this, "exec", +// PINManagementRequestHandler.this, "back"); +// } else { +// gui.showPINDialog(type, spec, +// PINManagementRequestHandler.this, "exec", +// PINManagementRequestHandler.this, "back"); +// } +// waitForAction(); +// +// if (actionCommand.equals("exec")) { +// gui.showWaitDialog(null); +// retry = true; +// oldPin = gui.getOldPin(); +// newPin = gui.getPin(); +// } else if (actionCommand.equals("back")) { +// throw new CancelledException(); +// } else { +// log.error("unsupported command " + actionCommand); +// throw new CancelledException(); +// } +// } +// } +// +// +// class PinpadPinProvider implements PINProvider { +// +// private PINManagementGUIFacade.DIALOG type; +// private boolean retry = false; +// +// public PinpadPinProvider(DIALOG type) { +// this.type = type; +// } +// +// @Override +// public char[] providePIN(PINSpec spec, int retries) { +// log.debug("provide pin for " + type); +// if (retry) { +// ((PINManagementGUIFacade) gui).showPinpadPINDialog(type, spec, retries); +// } else { +// ((PINManagementGUIFacade) gui).showPinpadPINDialog(type, spec, -1); +// retry = true; +// } +// return null; +// } +// +// @Override +// public char[] provideOldPIN(PINSpec spec, int retries) { +// return null; +// } +// } } 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 new file mode 100644 index 00000000..4176e0a9 --- /dev/null +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PinpadPINProviderFactory.java @@ -0,0 +1,126 @@ +/* + * 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; + +// gui.showPINDialog(type, spec, (retry) ? retries : -1, +// this, "exec", +// this, "back"); +// +// waitForAction(); +// +// if ("exec".equals(action)) { +// gui.showWaitDialog(null); +// retry = true; +// return gui.getPin(); +// } else if ("back".equals(action)) { +// throw new CancelledException(); +// } else { +// log.error("unsupported command " + action); +// throw new CancelledException(); +// } + } + + /** + * 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 { + title = BKUGUIFacade.TITLE_SIGN; + 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/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 new file mode 100644 index 00000000..e87512d0 --- /dev/null +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/SoftwarePINProviderFactory.java @@ -0,0 +1,148 @@ +/* + * 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 69d231f7..4ceacb21 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 @@ -22,13 +22,16 @@ title.verify.pin=<html>PIN Eingeben</html> title.activate.success=<html>Erfolg</html> title.change.success=<html>Erfolg</html> -message.pin.mgmt=<html>Die Karte verf\u00FCgt \u00FCber {0} PINs</html> -message.activate.pin=<html>{0} eingeben und best\u00E4tigen</html> -message.change.pin=<html>{0} eingeben und best\u00E4tigen</html> -message.unblock.pin=<html>PUK zu {0} eingeben</html> -message.verify.pin=<html>{0} eingeben (TODO: Warning not activated)</html> -message.activate.success=<html>{0} wurde erfolgreich aktiviert.</html> -message.change.success=<html>{0} wurde erfolgreich ge\u00E4ndert.</html> +# removed message.* prefix to reuse keys as help keys +pin.mgmt=<html>Die Karte verf\u00FCgt \u00FCber {0} PINs</html> +pinpad=<html>{0} ({1} stellig) am Kartenleser eingeben und best\u00E4tigen.</html> +pinpad.change=<html>{0} ({1} stellig) am Kartenleser eingeben und best\u00E4tigen.</html> +activate.pin=<html>{0} eingeben und best\u00E4tigen</html> +change.pin=<html>{0} eingeben und best\u00E4tigen</html> +unblock.pin=<html>PUK zu {0} eingeben</html> +verify.pin=<html>{0} eingeben (TODO: Warning not activated)</html> +activate.success=<html>{0} wurde erfolgreich aktiviert.</html> +change.success=<html>{0} wurde erfolgreich ge\u00E4ndert.</html> label.activation=<html>e-card Aktivierungsprozess</html> label.activation.step=<html>Schritt {0}</html> 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 920f7d5b..9178d65c 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 @@ -21,12 +21,15 @@ title.unblock.pin=<html>Unblock PIN</html> title.activate.success=<html>Success</html> title.change.success=<html>Success</html> -message.pin.mgmt=<html>The smartcard has {0} PINs</html> -message.activate.pin=<html>Enter and confirm {0}</html> -message.change.pin=<html>Enter and confirm {0}</html> -message.unblock.pin=<html>Enter PUK for {0}</html> -message.activate.success=<html>{0} successfully activated</html> -message.change.success=<html>{0} successfully changed</html> +# removed message.* prefix to reuse keys as help keys +pin.mgmt=<html>The smartcard has {0} PINs</html> +pinpad=<html>Enter {0} ({1} digits) on pinpad and confirm.</html> +pinpad.change=<html>Enter {0} ({1} digits) on pinpad and confirm.</html> +activate.pin=<html>Enter and confirm {0}</html> +change.pin=<html>Enter and confirm {0}</html> +unblock.pin=<html>Enter PUK for {0}</html> +activate.success=<html>{0} successfully activated</html> +change.success=<html>{0} successfully changed</html> label.activation=<html>e-card activation process</html> label.activation.step=<html>Step {0}</html> diff --git a/BKUAppletExt/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java b/BKUAppletExt/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java index ef8c87e4..b01abe72 100644 --- a/BKUAppletExt/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java +++ b/BKUAppletExt/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java @@ -74,7 +74,7 @@ public class BKUGUIWorker implements Runnable { @Override public void actionPerformed(ActionEvent e) { - gui.showSignaturePINDialog(signPinSpec, signListener, "sign", cancelListener, "cancel", null, "hashdata"); + gui.showSignaturePINDialog(signPinSpec, -1, signListener, "sign", cancelListener, "cancel", null, "hashdata"); } }; HashDataInput signedRef1 = new ByteArrayHashDataInput( @@ -112,7 +112,7 @@ public class BKUGUIWorker implements Runnable { // signedRefs.add(signedRef4); // signedRefs.add(signedRef4); // signedRefs = Collections.singletonList(signedRef1); - gui.showHashDataInputDialog(signedRefs, returnListener, "return"); + gui.showSecureViewer(signedRefs, returnListener, "return"); } }; diff --git a/BKUAppletExt/src/test/java/at/gv/egiz/bku/smccstal/ext/FileSystemTest.java b/BKUAppletExt/src/test/java/at/gv/egiz/bku/smccstal/ext/FileSystemTest.java deleted file mode 100644 index 5fa3cbd7..00000000 --- a/BKUAppletExt/src/test/java/at/gv/egiz/bku/smccstal/ext/FileSystemTest.java +++ /dev/null @@ -1,435 +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.FileNotFoundException; -import at.gv.egiz.smcc.LockedException; -import at.gv.egiz.smcc.NotActivatedException; -import at.gv.egiz.smcc.PINProvider; -import at.gv.egiz.smcc.PINSpec; -import at.gv.egiz.smcc.SignatureCard; -import at.gv.egiz.smcc.SignatureCardException; -import at.gv.egiz.smcc.util.SMCCHelper; -import at.gv.egiz.smcc.util.SmartCardIO; -import java.math.BigInteger; -import java.nio.ByteBuffer; -import java.util.Arrays; -import java.util.Locale; -import java.util.Map; -import javax.smartcardio.Card; -import javax.smartcardio.CardChannel; -import javax.smartcardio.CardException; -import javax.smartcardio.CardTerminal; -import javax.smartcardio.CommandAPDU; -import javax.smartcardio.ResponseAPDU; -import org.junit.Ignore; -import org.junit.Test; -import static org.junit.Assert.*; - -/** - * - * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at> - */ -@Ignore -public class FileSystemTest { - - /** asign premium */ - public static final byte[] AID_DEC = new byte[] { (byte) 0xA0, (byte) 0x00, - (byte) 0x00, (byte) 0x01, (byte) 0x18, (byte) 0x45, (byte) 0x4E }; - - @Test -// @Ignore - public void testCard() throws CardException, SignatureCardException, InterruptedException { - - SMCCHelper smccHelper = new SMCCHelper(); - switch (smccHelper.getResultCode()) { - case SMCCHelper.CARD_FOUND: - System.out.println("card found "); - } - SignatureCard signatureCard = smccHelper.getSignatureCard(new Locale("de")); - Card card = signatureCard.getCard(); - -// SmartCardIO scIO = new SmartCardIO(); -// Map<CardTerminal, Card> terminalCardMap = scIO.getCards(); -// -// for (CardTerminal ct : terminalCardMap.keySet()) { -// Card card = terminalCardMap.get(ct); -// System.out.println("found card (" + ct.getName() + "): " + Formatter.byteArrayToHexString(card.getATR().getBytes())); - - System.out.println("found card " + Formatter.byteArrayToHexString(card.getATR().getBytes())); - - CardChannel cardchannel; - - //RESET - System.out.println("RESET"); - signatureCard.reset(); - card = signatureCard.getCard(); -// card.disconnect(true); -// card = ct.connect("*"); - - System.out.println("begin exclusive"); - card.beginExclusive(); - System.out.println("get cardchannel"); - cardchannel = card.getBasicChannel(); - - testECard(cardchannel, signatureCard, card); -// testASignPremium(cardchannel, signatureCard, card); - -// } - - } - - public static class TestCard { - - protected CardChannel channel; - protected int ifs_ = 254; - - public TestCard(CardChannel channel) { - this.channel = channel; - } - - protected byte[] readTLVFile(byte[] aid, byte[] ef, String pin, byte kid, int maxLength) - throws SignatureCardException, InterruptedException, CardException { - - - // SELECT FILE (AID) - selectFileAID(aid); - - // SELECT FILE (EF) - ResponseAPDU resp = selectFileFID(ef); - if (resp.getSW() == 0x6a82) { - // EF not found - throw new FileNotFoundException("EF " + toString(ef) + " not found."); - } else if (resp.getSW() != 0x9000) { - throw new SignatureCardException("SELECT FILE with " + "FID=" + toString(ef) + " failed (" + "SW=" + Integer.toHexString(resp.getSW()) + ")."); - } - - // VERIFY - if (pin != null) { - int retries = verifyPIN(pin, kid); - if (retries != -1) { - throw new at.gv.egiz.smcc.VerificationFailedException(retries); - } - } - - return readBinaryTLV(maxLength, (byte) 0x30); - } - - protected byte[] readBinary(CardChannel channel, int offset, int len) - throws CardException, SignatureCardException { - - //transmit(channel,apdu) - ResponseAPDU resp = channel.transmit(new CommandAPDU(0x00, 0xB0, - 0x7F & (offset >> 8), offset & 0xFF, len)); - if (resp.getSW() == 0x9000) { - return resp.getData(); - } else if (resp.getSW() == 0x6982) { - throw new at.gv.egiz.smcc.SecurityStatusNotSatisfiedException(); - } else { - throw new SignatureCardException("Failed to read bytes (" + offset + "+" + len + "): SW=" + Integer.toHexString(resp.getSW())); - } - - } - - protected byte[] readBinaryTLV(int maxSize, byte expectedType) throws CardException, - SignatureCardException { - -// CardChannel channel = getCardChannel(); - - // read first chunk - int len = Math.min(maxSize, ifs_); - byte[] chunk = readBinary(channel, 0, len); - if (chunk.length > 0 && chunk[0] != expectedType) { - return null; - } - int offset = chunk.length; - int actualSize = maxSize; - if (chunk.length > 3) { - if ((chunk[1] & 0x80) > 0) { - int octets = (0x0F & chunk[1]); - actualSize = 2 + octets; - for (int i = 1; i <= octets; i++) { - actualSize += (0xFF & chunk[i + 1]) << ((octets - i) * 8); - } - } else { - actualSize = 2 + chunk[1]; - } - } - ByteBuffer buffer = ByteBuffer.allocate(actualSize); - buffer.put(chunk, 0, Math.min(actualSize, chunk.length)); - while (offset < actualSize) { - len = Math.min(ifs_, actualSize - offset); - chunk = readBinary(channel, offset, len); - buffer.put(chunk); - offset += chunk.length; - } - return buffer.array(); - - } - - protected byte[] selectFileAID(byte[] dfName) throws CardException, SignatureCardException { -// CardChannel channel = getCardChannel(); - ResponseAPDU resp = channel.transmit(new CommandAPDU(0x00, 0xA4, 0x04, - 0x00, dfName, 256)); - if (resp.getSW() != 0x9000) { - throw new SignatureCardException("Failed to select application AID=" + toString(dfName) + ": SW=" + Integer.toHexString(resp.getSW()) + "."); - } else { - return resp.getBytes(); - } - } - - protected ResponseAPDU selectFileFID(byte[] fid) throws CardException, SignatureCardException { -// CardChannel channel = getCardChannel(); - return channel.transmit(new CommandAPDU(0x00, 0xA4, 0x02, - 0x04, fid, 256)); - } - - protected String toString(byte[] b) { - StringBuffer sb = new StringBuffer(); - if (b != null && b.length > 0) { - sb.append(Integer.toHexString((b[0] & 240) >> 4)); - sb.append(Integer.toHexString(b[0] & 15)); - } - for (int i = 1; i < b.length; i++) { - sb.append(':'); - sb.append(Integer.toHexString((b[i] & 240) >> 4)); - sb.append(Integer.toHexString(b[i] & 15)); - } - return sb.toString(); - } - - protected int verifyPIN(String pin, byte kid) throws CardException, SignatureCardException { - -// CardChannel channel = getCardChannel(); - - ResponseAPDU resp; - if (pin == null) { - // - resp = channel.transmit(new CommandAPDU(0x00, 0x20, 0x00, kid)); - } else { - // PIN length in bytes - int len = (int) Math.ceil(pin.length() / 2); - - // BCD encode PIN and marshal PIN block - byte[] pinBytes = new BigInteger(pin, 16).toByteArray(); - byte[] pinBlock = new byte[8]; - if (len < pinBytes.length) { - System.arraycopy(pinBytes, pinBytes.length - len, pinBlock, 1, len); - } else { - System.arraycopy(pinBytes, 0, pinBlock, len - pinBytes.length + 1, - pinBytes.length); - } - pinBlock[0] = (byte) (0x20 + len * 2); - Arrays.fill(pinBlock, len + 1, 8, (byte) 0xff); - - resp = channel.transmit(new CommandAPDU(0x00, 0x20, 0x00, kid, pinBlock));//, false); - - } - - if (resp.getSW() == 0x63c0) { - throw new LockedException("PIN locked."); - } else if (resp.getSW1() == 0x63 && resp.getSW2() >> 4 == 0xc) { - // return number of possible retries - return resp.getSW2() & 0x0f; - } else if (resp.getSW() == 0x6983) { - throw new LockedException(); - } else if (resp.getSW() == 0x6984) { - // PIN LCS = "Initialized" (-> not activated) - throw new NotActivatedException("PIN not set."); - } else if (resp.getSW() == 0x9000) { - return -1; // success - } else { - throw new SignatureCardException("Failed to verify pin: SW=" + Integer.toHexString(resp.getSW())); - } - } - } - - public static class Formatter { - - private static String[] alphabet = {"0", "1", "2", - "3", "4", "5", "6", "7", "8", - "9", "A", "B", "C", "D", "E", - "F"}; - - public static String byteArrayToHexString(byte[] bytes) { - - if (bytes == null || bytes.length <= 0) { - return null; - } - - StringBuffer buf = new StringBuffer(2 * bytes.length); - - byte c = 0x00; - - for (int i = 0; i < bytes.length; i++) { - - // high nibble - c = (byte) (bytes[i] & 0xf0); - - // shift down - c = (byte) (c >>> 4); - - // cut high order bits - c = (byte) (c & 0x0f); - - buf.append(alphabet[(int) c]); - - // low nibble - c = (byte) (bytes[i] & 0x0f); - - buf.append(alphabet[(int) c]); - if (i < bytes.length - 1) { - buf.append(':'); - } - } - - return buf.toString(); - - } - } - - protected void testASignPremium(CardChannel cardchannel, SignatureCard signatureCard, Card card) throws CardException { - byte[] selectMF = new byte[]{(byte) 0x00, (byte) 0xA4, (byte) 0x00, (byte) 0x0C, (byte) 0x02, (byte) 0x3F, (byte) 0x00}; - byte[] selectDF_DEC = new byte[] { (byte) 0x00, (byte) 0xA4, (byte) 0x00, (byte) 0x0C, (byte) 0x02, (byte) 0xdf, (byte) 0x71 }; - byte[] selectAID_DEC = new byte[] { (byte) 0x00, (byte) 0xA4, (byte) 0x04, (byte) 0x00, (byte) 0x07, (byte) 0xA0, (byte) 0x00, - (byte) 0x00, (byte) 0x01, (byte) 0x18, (byte) 0x45, (byte) 0x4E }; - - CommandAPDU cAPDU; - ResponseAPDU rAPDU; - byte[] sw; - - cAPDU = new CommandAPDU(selectMF); - rAPDU = cardchannel.transmit(cAPDU); - sw = new byte[]{(byte) (0xFF & rAPDU.getSW1()), (byte) (0xFF & rAPDU.getSW2())}; - System.out.println("cAPDU: " + Formatter.byteArrayToHexString(cAPDU.getBytes())); - System.out.println("rAPDU (sw=" + Formatter.byteArrayToHexString(sw) + "): " + Formatter.byteArrayToHexString(rAPDU.getData())); - - cAPDU = new CommandAPDU(selectAID_DEC); - rAPDU = cardchannel.transmit(cAPDU); - sw = new byte[]{(byte) (0xFF & rAPDU.getSW1()), (byte) (0xFF & rAPDU.getSW2())}; - System.out.println("cAPDU: " + Formatter.byteArrayToHexString(cAPDU.getBytes())); - System.out.println("rAPDU (sw=" + Formatter.byteArrayToHexString(sw) + "): " + Formatter.byteArrayToHexString(rAPDU.getData())); - - cAPDU = new CommandAPDU(selectDF_DEC); - rAPDU = cardchannel.transmit(cAPDU); - sw = new byte[]{(byte) (0xFF & rAPDU.getSW1()), (byte) (0xFF & rAPDU.getSW2())}; - System.out.println("cAPDU: " + Formatter.byteArrayToHexString(cAPDU.getBytes())); - System.out.println("rAPDU (sw=" + Formatter.byteArrayToHexString(sw) + "): " + Formatter.byteArrayToHexString(rAPDU.getData())); - - - } - - protected void testECard(CardChannel cardchannel, SignatureCard signatureCard, Card card) throws CardException, InterruptedException, SignatureCardException { -// if (cardTerminal != null) { -// card_ = cardTerminal.connect("*"); -// } - byte[] selectMF = new byte[]{(byte) 0x00, (byte) 0xA4, (byte) 0x00, (byte) 0x0C, (byte) 0x02, (byte) 0x3F, (byte) 0x00}; - byte[] readEF_GDO = new byte[]{(byte) 0x00, (byte) 0xB0, (byte) 0x82, (byte) 0x00, (byte) 0x00}; - CommandAPDU cAPDU; - ResponseAPDU rAPDU; - byte[] sw; - cAPDU = new CommandAPDU(selectMF); - rAPDU = cardchannel.transmit(cAPDU); - sw = new byte[]{(byte) (0xFF & rAPDU.getSW1()), (byte) (0xFF & rAPDU.getSW2())}; - System.out.println("cAPDU: " + Formatter.byteArrayToHexString(cAPDU.getBytes())); - System.out.println("rAPDU (sw=" + Formatter.byteArrayToHexString(sw) + "): " + Formatter.byteArrayToHexString(rAPDU.getData())); - cAPDU = new CommandAPDU(readEF_GDO); - rAPDU = cardchannel.transmit(cAPDU); - sw = new byte[]{(byte) (0xFF & rAPDU.getSW1()), (byte) (0xFF & rAPDU.getSW2())}; - System.out.println("cAPDU: " + Formatter.byteArrayToHexString(cAPDU.getBytes())); - System.out.println("rAPDU (sw=" + Formatter.byteArrayToHexString(sw) + "): " + Formatter.byteArrayToHexString(rAPDU.getData())); - byte[] EF_GDO = rAPDU.getData(); - //RESET - System.out.println("RESET"); - signatureCard.reset(); - card = signatureCard.getCard(); -// card.disconnect(true); -// card = ct.connect("*"); - System.out.println("begin exclusive"); - card.beginExclusive(); - System.out.println("get cardchannel"); - cardchannel = card.getBasicChannel(); - byte[] getCLC = new byte[]{(byte) 0x00, (byte) 0xCA, (byte) 0xDF, (byte) 0x20, (byte) 0x00}; - byte[] verifyKartenPIN = new byte[]{(byte) 0x00, (byte) 0x20, (byte) 0x00, (byte) 0x01}; - byte[] selectDF_SichereSignatur = new byte[]{(byte) 0x00, (byte) 0xA4, (byte) 0x04, (byte) 0x00, (byte) 0x08, (byte) 0xD0, (byte) 0x40, (byte) 0x00, (byte) 0x00, (byte) 0x17, (byte) 0x00, (byte) 0x12, (byte) 0x01, (byte) 0x00}; - byte[] verifySignaturPIN = new byte[]{(byte) 0x00, (byte) 0x20, (byte) 0x00, (byte) 0x81}; - cAPDU = new CommandAPDU(getCLC); - rAPDU = cardchannel.transmit(cAPDU); - sw = new byte[]{(byte) (0xFF & rAPDU.getSW1()), (byte) (0xFF & rAPDU.getSW2())}; - System.out.println("cAPDU: " + Formatter.byteArrayToHexString(cAPDU.getBytes())); - System.out.println("rAPDU (sw=" + Formatter.byteArrayToHexString(sw) + "): " + Formatter.byteArrayToHexString(rAPDU.getData())); - byte[] clc = rAPDU.getData(); - cAPDU = new CommandAPDU(verifyKartenPIN); - rAPDU = cardchannel.transmit(cAPDU); - sw = new byte[]{(byte) (0xFF & rAPDU.getSW1()), (byte) (0xFF & rAPDU.getSW2())}; - System.out.println("cAPDU: " + Formatter.byteArrayToHexString(cAPDU.getBytes())); - System.out.println("rAPDU (sw=" + Formatter.byteArrayToHexString(sw) + "): " + Formatter.byteArrayToHexString(rAPDU.getData())); - cAPDU = new CommandAPDU(selectDF_SichereSignatur); - rAPDU = cardchannel.transmit(cAPDU); - sw = new byte[]{(byte) (0xFF & rAPDU.getSW1()), (byte) (0xFF & rAPDU.getSW2())}; - System.out.println("cAPDU: " + Formatter.byteArrayToHexString(cAPDU.getBytes())); - System.out.println("rAPDU (sw=" + Formatter.byteArrayToHexString(sw) + "): " + Formatter.byteArrayToHexString(rAPDU.getData())); - cAPDU = new CommandAPDU(verifySignaturPIN); - rAPDU = cardchannel.transmit(cAPDU); - sw = new byte[]{(byte) (0xFF & rAPDU.getSW1()), (byte) (0xFF & rAPDU.getSW2())}; - System.out.println("cAPDU: " + Formatter.byteArrayToHexString(cAPDU.getBytes())); - System.out.println("rAPDU (sw=" + Formatter.byteArrayToHexString(sw) + "): " + Formatter.byteArrayToHexString(rAPDU.getData())); - //RESET - System.out.println("RESET"); - signatureCard.reset(); - card = signatureCard.getCard(); - System.out.println("InfoboxReadRequests..."); - PINProvider pinProvider = new PINProvider() { - - @Override - public String providePIN(PINSpec spec, int retries) throws InterruptedException { - if (retries >= 3) { - return "2540"; - } else { - throw new InterruptedException("TOO FEW PIN RETRIES LEFT, ABORTING"); - } - } - }; - byte[] ehic = signatureCard.getInfobox("EHIC", pinProvider, null); - System.out.println("EHIC: " + Formatter.byteArrayToHexString(ehic)); - byte[] grunddaten = signatureCard.getInfobox("Grunddaten", pinProvider, null); - System.out.println("Grunddaten: " + Formatter.byteArrayToHexString(grunddaten)); - //RESET - System.out.println("RESET"); - signatureCard.reset(); - card = signatureCard.getCard(); -// card.disconnect(true); -// card = ct.connect("*"); - System.out.println("begin exclusive"); - card.beginExclusive(); - System.out.println("get cardchannel"); - cardchannel = card.getBasicChannel(); - cAPDU = new CommandAPDU(getCLC); - rAPDU = cardchannel.transmit(cAPDU); - sw = new byte[]{(byte) (0xFF & rAPDU.getSW1()), (byte) (0xFF & rAPDU.getSW2())}; - System.out.println("cAPDU: " + Formatter.byteArrayToHexString(cAPDU.getBytes())); - System.out.println("rAPDU (sw=" + Formatter.byteArrayToHexString(sw) + "): " + Formatter.byteArrayToHexString(rAPDU.getData())); - assertTrue(Arrays.equals(clc, rAPDU.getData())); - cAPDU = new CommandAPDU(readEF_GDO); - rAPDU = cardchannel.transmit(cAPDU); - sw = new byte[]{(byte) (0xFF & rAPDU.getSW1()), (byte) (0xFF & rAPDU.getSW2())}; - System.out.println("cAPDU: " + Formatter.byteArrayToHexString(cAPDU.getBytes())); - System.out.println("rAPDU (sw=" + Formatter.byteArrayToHexString(sw) + "): " + Formatter.byteArrayToHexString(rAPDU.getData())); - assertTrue(Arrays.equals(EF_GDO, rAPDU.getData())); -// } - } -} diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java index be5e3fc8..1043b6a1 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java @@ -36,6 +36,7 @@ public interface BKUGUIFacade { public static final String ERR_INVALID_HASH = "error.invalid.hash"; public static final String ERR_CARD_LOCKED = "error.card.locked"; public static final String ERR_CARD_NOTACTIVATED = "error.card.notactivated"; + public static final String ERR_PIN_TIMEOUT = "error.pin.timeout"; public static final String ERR_VIEWER = "error.viewer"; public static final String ERR_EXTERNAL_LINK = "error.external.link"; public static final String ERR_CONFIG = "error.config"; @@ -52,6 +53,7 @@ public interface BKUGUIFacade { public static final String TITLE_CARDPIN = "title.cardpin"; public static final String TITLE_SIGN = "title.sign"; public static final String TITLE_ERROR = "title.error"; + public static final String TITLE_ENTRY_TIMEOUT = "title.entry.timeout"; public static final String TITLE_RETRY = "title.retry"; public static final String TITLE_WAIT = "title.wait"; public static final String TITLE_HASHDATA = "title.hashdata"; @@ -60,17 +62,22 @@ public interface BKUGUIFacade { public static final String WINDOWTITLE_OVERWRITE = "windowtitle.overwrite"; public static final String WINDOWTITLE_VIEWER = "windowtitle.viewer"; public static final String WINDOWTITLE_HELP = "windowtitle.help"; - public static final String MESSAGE_WAIT = "message.wait"; - public static final String MESSAGE_INSERTCARD = "message.insertcard"; - public static final String MESSAGE_ENTERPIN = "message.enterpin"; - public static final String MESSAGE_HASHDATALINK = "message.hashdatalink"; - public static final String MESSAGE_HASHDATALINK_TINY = "message.hashdatalink.tiny"; -// public static final String MESSAGE_HASHDATA = "message.hashdata"; - public static final String MESSAGE_HASHDATALIST = "message.hashdatalist"; - public static final String MESSAGE_RETRIES = "message.retries"; - public static final String MESSAGE_LAST_RETRY = "message.retries.last"; - public static final String MESSAGE_OVERWRITE = "message.overwrite"; - public static final String MESSAGE_HELP = "message.help"; + + // removed message.* prefix to reuse keys as help keys + public static final String MESSAGE_WELCOME = "welcome"; + public static final String MESSAGE_WAIT = "wait"; + public static final String MESSAGE_INSERTCARD = "insertcard"; + public static final String MESSAGE_CARD_NOT_SUPPORTED = "cardnotsupported"; + public static final String MESSAGE_ENTERPIN = "enterpin"; + public static final String MESSAGE_ENTERPIN_PINPAD = "enterpin.pinpad"; + public static final String MESSAGE_HASHDATALINK = "hashdatalink"; + public static final String MESSAGE_HASHDATALINK_TINY = "hashdatalink.tiny"; + public static final String MESSAGE_HASHDATALIST = "hashdatalist"; + public static final String MESSAGE_RETRIES = "retries"; + public static final String MESSAGE_LAST_RETRY = "retries.last"; + public static final String MESSAGE_OVERWRITE = "overwrite"; + public static final String MESSAGE_HELP = "help"; + public static final String WARNING_XHTML = "warning.xhtml"; public static final String LABEL_PIN = "label.pin"; public static final String LABEL_PINSIZE = "label.pinsize"; @@ -103,33 +110,48 @@ public interface BKUGUIFacade { */ public Locale getLocale(); - public void showWelcomeDialog(); +// public void showWelcomeDialog(); /** * * @param waitMessage if null, a simple 'please wait' text is displayed */ - public void showWaitDialog(String waitMessage); +// public void showWaitDialog(String waitMessage); + +// public void showInsertCardDialog(ActionListener cancelListener, String actionCommand); - public void showInsertCardDialog(ActionListener cancelListener, String actionCommand); +// public void showCardNotSupportedDialog(ActionListener cancelListener, String actionCommand); - public void showCardNotSupportedDialog(ActionListener cancelListener, String actionCommand); + public void showCardPINDialog(PINSpec pinSpec, int numRetries, + ActionListener okListener, String okCommand, + ActionListener cancelListener, String cancelCommand); - public void showCardPINDialog(PINSpec pinSpec, ActionListener okListener, String okCommand, ActionListener cancelListener, String cancelCommand); +// public void showCardPINRetryDialog(PINSpec pinSpec, int numRetries, ActionListener okListener, String okCommand, ActionListener cancelListener, String cancelCommand); - public void showCardPINRetryDialog(PINSpec pinSpec, int numRetries, ActionListener okListener, String okCommand, ActionListener cancelListener, String cancelCommand); + public void showSignaturePINDialog(PINSpec pinSpec, int numRetries, ActionListener signListener, String signCommand, ActionListener cancelListener, String cancelCommand, ActionListener hashdataListener, String hashdataCommand); - public void showSignaturePINDialog(PINSpec pinSpec, ActionListener signListener, String signCommand, ActionListener cancelListener, String cancelCommand, ActionListener hashdataListener, String hashdataCommand); +// public void showSignaturePINRetryDialog(PINSpec pinSpec, int numRetries, ActionListener okListener, String okCommand, ActionListener cancelListener, String cancelCommand, ActionListener hashdataListener, String hashdataCommand); - public void showSignaturePINRetryDialog(PINSpec pinSpec, int numRetries, ActionListener okListener, String okCommand, ActionListener cancelListener, String cancelCommand, ActionListener hashdataListener, String hashdataCommand); +// public void showPinpadSignaturePINDialog(PINSpec pinSpec, int retries); public char[] getPin(); - public void showHashDataInputDialog(List<HashDataInput> signedReferences, ActionListener okListener, String okCommand); + public void showSecureViewer(List<HashDataInput> signedReferences, + ActionListener okListener, String okCommand); - public void showErrorDialog(String errorMsgKey, Object[] errorMsgParams, ActionListener okListener, String okCommand); + public void showErrorDialog(String errorMsgKey, Object[] errorMsgParams, + ActionListener okListener, String okCommand); public void showErrorDialog(String errorMsgKey, Object[] errorMsgParams); - public void showMessageDialog(String titleKey, String msgKey, Object[] msgParams, ActionListener okListener, String okCommand); + public void showMessageDialog(String titleKey, + String msgKey, Object[] msgParams, + String buttonKey, + ActionListener okListener, String okCommand); + + public void showMessageDialog(String titleKey, + String msgKey, Object[] msgParams); + + public void showMessageDialog(String titleKey, + String msgKey); } diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java index 76b1d795..928be249 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java @@ -315,200 +315,204 @@ public class BKUGUIImpl implements BKUGUIFacade { return messages.containsKey(key); } - @Override - public void showWelcomeDialog() { - - log.debug("scheduling welcome dialog"); - - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - - log.debug("show welcome dialog"); - - mainPanel.removeAll(); - buttonPanel.removeAll(); - - helpListener.setHelpTopic(HELP_WELCOME); - - JLabel welcomeMsgLabel = new JLabel(); - welcomeMsgLabel.setFont(welcomeMsgLabel.getFont().deriveFont(welcomeMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); - - if (renderHeaderPanel) { - titleLabel.setText(getMessage(TITLE_WELCOME)); - welcomeMsgLabel.setText(getMessage(MESSAGE_WAIT)); - } else { - welcomeMsgLabel.setText(getMessage(TITLE_WELCOME)); - } - - GroupLayout mainPanelLayout = new GroupLayout(mainPanel); - mainPanel.setLayout(mainPanelLayout); - - GroupLayout.SequentialGroup messageHorizontal = mainPanelLayout.createSequentialGroup() - .addComponent(welcomeMsgLabel); - GroupLayout.Group messageVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(welcomeMsgLabel); - if (!renderHeaderPanel) { - messageHorizontal - .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) - .addComponent(helpLabel); - messageVertical - .addComponent(helpLabel); - } - - mainPanelLayout.setHorizontalGroup(messageHorizontal); - mainPanelLayout.setVerticalGroup(messageVertical); - - contentPanel.validate(); - - } - }); - } - - @Override - public void showInsertCardDialog(final ActionListener cancelListener, final String cancelCommand) { - - log.debug("scheduling insert card dialog"); - - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - - log.debug("show insert card dialog"); - - mainPanel.removeAll(); - buttonPanel.removeAll(); - - if (renderHeaderPanel) { - titleLabel.setText(getMessage(TITLE_INSERTCARD)); - } - - helpListener.setHelpTopic(HELP_INSERTCARD); - - JLabel insertCardMsgLabel = new JLabel(); - insertCardMsgLabel.setFont(insertCardMsgLabel.getFont().deriveFont(insertCardMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); - insertCardMsgLabel.setText(getMessage(MESSAGE_INSERTCARD)); - - GroupLayout mainPanelLayout = new GroupLayout(mainPanel); - mainPanel.setLayout(mainPanelLayout); - - GroupLayout.SequentialGroup messageHorizontal = mainPanelLayout.createSequentialGroup() - .addComponent(insertCardMsgLabel); - GroupLayout.ParallelGroup messageVertical = mainPanelLayout.createParallelGroup() - .addComponent(insertCardMsgLabel); - - if (!renderHeaderPanel) { - messageHorizontal - .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) - .addComponent(helpLabel); - messageVertical - .addComponent(helpLabel); - } - - mainPanelLayout.setHorizontalGroup(messageHorizontal); - mainPanelLayout.setVerticalGroup(messageVertical); - - if (renderCancelButton) { - JButton cancelButton = new JButton(); - cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD)); - cancelButton.setText(getMessage(BUTTON_CANCEL)); - cancelButton.addActionListener(cancelListener); - cancelButton.setActionCommand(cancelCommand); - - GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); - buttonPanel.setLayout(buttonPanelLayout); - - buttonPanelLayout.setHorizontalGroup( - buttonPanelLayout.createSequentialGroup() - .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)); - buttonPanelLayout.setVerticalGroup( - buttonPanelLayout.createSequentialGroup() - .addComponent(cancelButton)); - } - - contentPanel.validate(); - } - }); - } +// @Override +// public void showWelcomeDialog() { +// +// log.debug("scheduling welcome dialog"); +// +// SwingUtilities.invokeLater(new Runnable() { +// +// @Override +// public void run() { +// +// log.debug("show welcome dialog"); +// +// mainPanel.removeAll(); +// buttonPanel.removeAll(); +// +// helpListener.setHelpTopic(HELP_WELCOME); +// +// JLabel welcomeMsgLabel = new JLabel(); +// welcomeMsgLabel.setFont(welcomeMsgLabel.getFont().deriveFont(welcomeMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); +// +// if (renderHeaderPanel) { +// titleLabel.setText(getMessage(TITLE_WELCOME)); +// welcomeMsgLabel.setText(getMessage(MESSAGE_WAIT)); +// } else { +// welcomeMsgLabel.setText(getMessage(TITLE_WELCOME)); +// } +// +// GroupLayout mainPanelLayout = new GroupLayout(mainPanel); +// mainPanel.setLayout(mainPanelLayout); +// +// GroupLayout.SequentialGroup messageHorizontal = mainPanelLayout.createSequentialGroup() +// .addComponent(welcomeMsgLabel); +// GroupLayout.Group messageVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) +// .addComponent(welcomeMsgLabel); +// if (!renderHeaderPanel) { +// messageHorizontal +// .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) +// .addComponent(helpLabel); +// messageVertical +// .addComponent(helpLabel); +// } +// +// mainPanelLayout.setHorizontalGroup(messageHorizontal); +// mainPanelLayout.setVerticalGroup(messageVertical); +// +// contentPanel.validate(); +// +// } +// }); +// } + +// @Override +// public void showInsertCardDialog( +// final ActionListener cancelListener, final String cancelCommand) { +// +// log.debug("scheduling insert card dialog"); +// +// SwingUtilities.invokeLater(new Runnable() { +// +// @Override +// public void run() { +// +// log.debug("show insert card dialog"); +// +// mainPanel.removeAll(); +// buttonPanel.removeAll(); +// +// if (renderHeaderPanel) { +// titleLabel.setText(getMessage(TITLE_INSERTCARD)); +// } +// +// helpListener.setHelpTopic(HELP_INSERTCARD); +// +// JLabel insertCardMsgLabel = new JLabel(); +// insertCardMsgLabel.setFont(insertCardMsgLabel.getFont().deriveFont(insertCardMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); +// insertCardMsgLabel.setText(getMessage(MESSAGE_INSERTCARD)); +// +// GroupLayout mainPanelLayout = new GroupLayout(mainPanel); +// mainPanel.setLayout(mainPanelLayout); +// +// GroupLayout.SequentialGroup messageHorizontal = mainPanelLayout.createSequentialGroup() +// .addComponent(insertCardMsgLabel); +// GroupLayout.ParallelGroup messageVertical = mainPanelLayout.createParallelGroup() +// .addComponent(insertCardMsgLabel); +// +// if (!renderHeaderPanel) { +// messageHorizontal +// .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) +// .addComponent(helpLabel); +// messageVertical +// .addComponent(helpLabel); +// } +// +// mainPanelLayout.setHorizontalGroup(messageHorizontal); +// mainPanelLayout.setVerticalGroup(messageVertical); +// +// if (renderCancelButton) { +// JButton cancelButton = new JButton(); +// cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD)); +// cancelButton.setText(getMessage(BUTTON_CANCEL)); +// cancelButton.addActionListener(cancelListener); +// cancelButton.setActionCommand(cancelCommand); +// +// GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); +// buttonPanel.setLayout(buttonPanelLayout); +// +// buttonPanelLayout.setHorizontalGroup( +// buttonPanelLayout.createSequentialGroup() +// .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) +// .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)); +// buttonPanelLayout.setVerticalGroup( +// buttonPanelLayout.createSequentialGroup() +// .addComponent(cancelButton)); +// } +// +// contentPanel.validate(); +// } +// }); +// } /** * only difference to showInsertCard: title text: card not supported * @param cancelListener * @param cancelCommand */ - @Override - public void showCardNotSupportedDialog(final ActionListener cancelListener, final String cancelCommand) { - - log.debug("scheduling card not supported dialog"); - - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - - log.debug("show card not supported dialog"); - - mainPanel.removeAll(); - buttonPanel.removeAll(); - - JLabel insertCardMsgLabel = new JLabel(); - insertCardMsgLabel.setFont(insertCardMsgLabel.getFont().deriveFont(insertCardMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); - - if (renderHeaderPanel) { - titleLabel.setText(getMessage(TITLE_CARD_NOT_SUPPORTED)); - insertCardMsgLabel.setText(getMessage(MESSAGE_INSERTCARD)); - } else { - insertCardMsgLabel.setText(getMessage(TITLE_CARD_NOT_SUPPORTED)); - } - - helpListener.setHelpTopic(HELP_CARDNOTSUPPORTED); - - GroupLayout mainPanelLayout = new GroupLayout(mainPanel); - mainPanel.setLayout(mainPanelLayout); - - GroupLayout.SequentialGroup messageHorizontal = mainPanelLayout.createSequentialGroup() - .addComponent(insertCardMsgLabel); - GroupLayout.Group messageVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(insertCardMsgLabel); - if (!renderHeaderPanel) { - messageHorizontal - .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) - .addComponent(helpLabel); - messageVertical - .addComponent(helpLabel); - } - - mainPanelLayout.setHorizontalGroup(messageHorizontal); - mainPanelLayout.setVerticalGroup(messageVertical); - - if (renderCancelButton) { - JButton cancelButton = new JButton(); - cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD)); - cancelButton.setText(getMessage(BUTTON_CANCEL)); - cancelButton.addActionListener(cancelListener); - cancelButton.setActionCommand(cancelCommand); - - GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); - buttonPanel.setLayout(buttonPanelLayout); - - buttonPanelLayout.setHorizontalGroup( - buttonPanelLayout.createSequentialGroup() - .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)); - buttonPanelLayout.setVerticalGroup( - buttonPanelLayout.createSequentialGroup() - .addComponent(cancelButton)); - } - - contentPanel.validate(); - } - }); - } - - private void showCardPINDialog(final PINSpec pinSpec, final int numRetries, final ActionListener okListener, final String okCommand, final ActionListener cancelListener, final String cancelCommand) { +// @Override +// public void showCardNotSupportedDialog(final ActionListener cancelListener, final String cancelCommand) { +// +// log.debug("scheduling card not supported dialog"); +// +// SwingUtilities.invokeLater(new Runnable() { +// +// @Override +// public void run() { +// +// log.debug("show card not supported dialog"); +// +// mainPanel.removeAll(); +// buttonPanel.removeAll(); +// +// JLabel insertCardMsgLabel = new JLabel(); +// insertCardMsgLabel.setFont(insertCardMsgLabel.getFont().deriveFont(insertCardMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); +// +// if (renderHeaderPanel) { +// titleLabel.setText(getMessage(TITLE_CARD_NOT_SUPPORTED)); +// insertCardMsgLabel.setText(getMessage(MESSAGE_INSERTCARD)); +// } else { +// insertCardMsgLabel.setText(getMessage(TITLE_CARD_NOT_SUPPORTED)); +// } +// +// helpListener.setHelpTopic(HELP_CARDNOTSUPPORTED); +// +// GroupLayout mainPanelLayout = new GroupLayout(mainPanel); +// mainPanel.setLayout(mainPanelLayout); +// +// GroupLayout.SequentialGroup messageHorizontal = mainPanelLayout.createSequentialGroup() +// .addComponent(insertCardMsgLabel); +// GroupLayout.Group messageVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) +// .addComponent(insertCardMsgLabel); +// if (!renderHeaderPanel) { +// messageHorizontal +// .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) +// .addComponent(helpLabel); +// messageVertical +// .addComponent(helpLabel); +// } +// +// mainPanelLayout.setHorizontalGroup(messageHorizontal); +// mainPanelLayout.setVerticalGroup(messageVertical); +// +// if (renderCancelButton) { +// JButton cancelButton = new JButton(); +// cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD)); +// cancelButton.setText(getMessage(BUTTON_CANCEL)); +// cancelButton.addActionListener(cancelListener); +// cancelButton.setActionCommand(cancelCommand); +// +// GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); +// buttonPanel.setLayout(buttonPanelLayout); +// +// buttonPanelLayout.setHorizontalGroup( +// buttonPanelLayout.createSequentialGroup() +// .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) +// .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)); +// buttonPanelLayout.setVerticalGroup( +// buttonPanelLayout.createSequentialGroup() +// .addComponent(cancelButton)); +// } +// +// contentPanel.validate(); +// } +// }); +// } + + @Override + public void showCardPINDialog(final PINSpec pinSpec, final int numRetries, + final ActionListener okListener, final String okCommand, + final ActionListener cancelListener, final String cancelCommand) { log.debug("scheduling card-pin dialog"); @@ -534,7 +538,7 @@ public class BKUGUIImpl implements BKUGUIFacade { JButton okButton = new JButton(); okButton.setFont(okButton.getFont().deriveFont(okButton.getFont().getStyle() & ~java.awt.Font.BOLD)); okButton.setText(getMessage(BUTTON_OK)); - okButton.setEnabled(false); + okButton.setEnabled(pinSpec.getMinLength() <= 0); okButton.setActionCommand(okCommand); okButton.addActionListener(okListener); @@ -681,27 +685,30 @@ public class BKUGUIImpl implements BKUGUIFacade { }); } - @Override - public void showCardPINDialog(PINSpec pinSpec, ActionListener okListener, String okCommand, ActionListener cancelListener, String cancelCommand) { - showCardPINDialog(pinSpec, -1, okListener, okCommand, cancelListener, cancelCommand); - } - - @Override - public void showCardPINRetryDialog(PINSpec pinSpec, int numRetries, ActionListener okListener, String okCommand, ActionListener cancelListener, String cancelCommand) { - showCardPINDialog(pinSpec, numRetries, okListener, okCommand, cancelListener, cancelCommand); - } - - @Override - public void showSignaturePINDialog(PINSpec pinSpec, ActionListener signListener, String signCommand, ActionListener cancelListener, String cancelCommand, ActionListener hashdataListener, String hashdataCommand) { - showSignaturePINDialog(pinSpec, -1, signListener, signCommand, cancelListener, cancelCommand, hashdataListener, hashdataCommand); - } +// @Override +// public void showCardPINDialog(PINSpec pinSpec, ActionListener okListener, String okCommand, ActionListener cancelListener, String cancelCommand) { +// showCardPINDialog(pinSpec, -1, okListener, okCommand, cancelListener, cancelCommand); +// } +// +// @Override +// public void showCardPINRetryDialog(PINSpec pinSpec, int numRetries, ActionListener okListener, String okCommand, ActionListener cancelListener, String cancelCommand) { +// showCardPINDialog(pinSpec, numRetries, okListener, okCommand, cancelListener, cancelCommand); +// } + +// @Override +// public void showSignaturePINDialog(PINSpec pinSpec, ActionListener signListener, String signCommand, ActionListener cancelListener, String cancelCommand, ActionListener hashdataListener, String hashdataCommand) { +// showSignaturePINDialog(pinSpec, -1, signListener, signCommand, cancelListener, cancelCommand, hashdataListener, hashdataCommand); +// } @Override - public void showSignaturePINRetryDialog(PINSpec pinSpec, int numRetries, ActionListener okListener, String okCommand, ActionListener cancelListener, String cancelCommand, ActionListener hashdataListener, String hashdataCommand) { - showSignaturePINDialog(pinSpec, numRetries, okListener, okCommand, cancelListener, cancelCommand, hashdataListener, hashdataCommand); - } - - private void showSignaturePINDialog(final PINSpec pinSpec, final int numRetries, final ActionListener signListener, final String signCommand, final ActionListener cancelListener, final String cancelCommand, final ActionListener hashdataListener, final String hashdataCommand) { + public void showSignaturePINDialog(final PINSpec pinSpec, final int numRetries, + final ActionListener signListener, final String signCommand, + final ActionListener cancelListener, final String cancelCommand, + final ActionListener hashdataListener, final String hashdataCommand) { +// showSignaturePINDialog(pinSpec, numRetries, okListener, okCommand, cancelListener, cancelCommand, hashdataListener, hashdataCommand); +// } +// +// private void showSignaturePINDialog(final PINSpec pinSpec, final int numRetries, final ActionListener signListener, final String signCommand, final ActionListener cancelListener, final String cancelCommand, final ActionListener hashdataListener, final String hashdataCommand) { log.debug("scheduling signature-pin dialog"); @@ -726,7 +733,7 @@ public class BKUGUIImpl implements BKUGUIFacade { JButton signButton = new JButton(); signButton.setFont(signButton.getFont().deriveFont(signButton.getFont().getStyle() & ~java.awt.Font.BOLD)); signButton.setText(getMessage(BUTTON_SIGN)); - signButton.setEnabled(false); + signButton.setEnabled(pinSpec.getMinLength() <= 0); signButton.setActionCommand(signCommand); signButton.addActionListener(signListener); @@ -888,7 +895,7 @@ public class BKUGUIImpl implements BKUGUIFacade { final ActionListener okListener, final String okCommand) { showMessageDialog(TITLE_ERROR, ERROR_COLOR, - errorMsgKey, errorMsgParams, okListener, okCommand); + errorMsgKey, errorMsgParams, BUTTON_OK, okListener, okCommand); } @Override @@ -896,22 +903,45 @@ public class BKUGUIImpl implements BKUGUIFacade { final String errorMsgKey, final Object[] errorMsgParams) { showMessageDialog(TITLE_ERROR, ERROR_COLOR, - errorMsgKey, errorMsgParams, null, null); + errorMsgKey, errorMsgParams, null, null, null); } @Override public void showMessageDialog( final String titleKey, final String msgKey, final Object[] msgParams, + final String buttonKey, final ActionListener okListener, final String okCommand) { showMessageDialog(titleKey, null, - msgKey, msgParams, okListener, okCommand); + msgKey, msgParams, buttonKey, okListener, okCommand); + } + + @Override + public void showMessageDialog( + final String titleKey, + final String msgKey, final Object[] msgParams) { + + showMessageDialog(titleKey, null, + msgKey, msgParams, null, null, null); + } + + @Override + public void showMessageDialog( + final String titleKey, final String msgKey) { + + showMessageDialog(titleKey, null, + msgKey, null, null, null, null); } + /** + * + * @param buttonKey if null defaults to BUTTON_OK + */ private void showMessageDialog( final String titleKey, final Color titleColor, final String msgKey, final Object[] msgParams, + final String buttonKey, final ActionListener okListener, final String okCommand) { log.debug("scheduling message dialog"); @@ -972,7 +1002,7 @@ public class BKUGUIImpl implements BKUGUIFacade { if (okListener != null) { JButton okButton = new JButton(); okButton.setFont(okButton.getFont().deriveFont(okButton.getFont().getStyle() & ~java.awt.Font.BOLD)); - okButton.setText(getMessage(BUTTON_OK)); + okButton.setText(getMessage((buttonKey != null) ? buttonKey : BUTTON_OK)); okButton.setActionCommand(okCommand); okButton.addActionListener(okListener); @@ -993,57 +1023,57 @@ public class BKUGUIImpl implements BKUGUIFacade { }); } - @Override - public void showWaitDialog(final String waitMessage) { - - log.debug("scheduling wait dialog"); - - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - - log.debug("show wait dialog"); - - mainPanel.removeAll(); - buttonPanel.removeAll(); - - if (renderHeaderPanel) { - titleLabel.setText(getMessage(TITLE_WAIT)); - } - - helpListener.setHelpTopic(HELP_WAIT); - - JLabel waitMsgLabel = new JLabel(); - waitMsgLabel.setFont(waitMsgLabel.getFont().deriveFont(waitMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); - if (waitMessage != null) { - waitMsgLabel.setText("<html>" + waitMessage + "</html>"); - } else { - waitMsgLabel.setText(getMessage(MESSAGE_WAIT)); - } - - GroupLayout mainPanelLayout = new GroupLayout(mainPanel); - mainPanel.setLayout(mainPanelLayout); - - GroupLayout.SequentialGroup messageHorizontal = mainPanelLayout.createSequentialGroup() - .addComponent(waitMsgLabel); - GroupLayout.ParallelGroup messageVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(waitMsgLabel); - - if (!renderHeaderPanel) { - messageHorizontal - .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) - .addComponent(helpLabel); - messageVertical - .addComponent(helpLabel); - } - mainPanelLayout.setHorizontalGroup(messageHorizontal); - mainPanelLayout.setVerticalGroup(messageVertical); - - contentPanel.validate(); - } - }); - } +// @Override +// public void showWaitDialog(final String waitMessage) { +// +// log.debug("scheduling wait dialog"); +// +// SwingUtilities.invokeLater(new Runnable() { +// +// @Override +// public void run() { +// +// log.debug("show wait dialog"); +// +// mainPanel.removeAll(); +// buttonPanel.removeAll(); +// +// if (renderHeaderPanel) { +// titleLabel.setText(getMessage(TITLE_WAIT)); +// } +// +// helpListener.setHelpTopic(HELP_WAIT); +// +// JLabel waitMsgLabel = new JLabel(); +// waitMsgLabel.setFont(waitMsgLabel.getFont().deriveFont(waitMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); +// if (waitMessage != null) { +// waitMsgLabel.setText("<html>" + waitMessage + "</html>"); +// } else { +// waitMsgLabel.setText(getMessage(MESSAGE_WAIT)); +// } +// +// GroupLayout mainPanelLayout = new GroupLayout(mainPanel); +// mainPanel.setLayout(mainPanelLayout); +// +// GroupLayout.SequentialGroup messageHorizontal = mainPanelLayout.createSequentialGroup() +// .addComponent(waitMsgLabel); +// GroupLayout.ParallelGroup messageVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) +// .addComponent(waitMsgLabel); +// +// if (!renderHeaderPanel) { +// messageHorizontal +// .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) +// .addComponent(helpLabel); +// messageVertical +// .addComponent(helpLabel); +// } +// mainPanelLayout.setHorizontalGroup(messageHorizontal); +// mainPanelLayout.setVerticalGroup(messageVertical); +// +// contentPanel.validate(); +// } +// }); +// } @Override public char[] getPin() { @@ -1062,7 +1092,7 @@ public class BKUGUIImpl implements BKUGUIFacade { * @param okCommand */ @Override - public void showHashDataInputDialog(final List<HashDataInput> signedReferences, + public void showSecureViewer(final List<HashDataInput> signedReferences, final ActionListener okListener, final String okCommand) { diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/PinDocument.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/PinDocument.java index 87b636f0..13aaf870 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/PinDocument.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/PinDocument.java @@ -35,6 +35,7 @@ class PINDocument extends PlainDocument { protected Pattern pinPattern; protected JButton enterButton; protected Document compareTo; + protected Document oldPin; public PINDocument(PINSpec pinSpec, JButton enterButton) { this.pinSpec = pinSpec; @@ -46,11 +47,30 @@ class PINDocument extends PlainDocument { this.enterButton = enterButton; } + /** + * + * @param pinSpec + * @param enterButton + * @param compareTo enable enterButton iff this pinDocument's pin equals to compareTo's pin. may be null + */ public PINDocument(PINSpec pinSpec, JButton enterButton, Document compareTo) { this(pinSpec, enterButton); this.compareTo = compareTo; } + /** + * + * @param pinSpec + * @param enterButton may be null + * @param compareTo enable enterButton iff this pinDocument's pin equals to compareTo's pin. may be null + * @param oldPin enable enterButton iff oldPin meets the pinSpec pin length requirements, may be null + */ + public PINDocument(PINSpec pinSpec, JButton enterButton, Document compareTo, Document oldPin) { + this(pinSpec, enterButton); + this.compareTo = compareTo; + this.oldPin = oldPin; + } + @Override public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { if (pinSpec.getMaxLength() < 0 || pinSpec.getMaxLength() >= (getLength() + str.length())) { @@ -66,7 +86,10 @@ class PINDocument extends PlainDocument { } } if (enterButton != null) { - enterButton.setEnabled(getLength() >= pinSpec.getMinLength() && compare()); + enterButton.setEnabled( + (oldPin == null || oldPin.getLength() >= pinSpec.getMinLength()) && + getLength() >= pinSpec.getMinLength() && + compare()); } } @@ -74,7 +97,10 @@ class PINDocument extends PlainDocument { public void remove(int offs, int len) throws BadLocationException { super.remove(offs, len); if (enterButton != null) { - enterButton.setEnabled(getLength() >= pinSpec.getMinLength() && compare()); + enterButton.setEnabled( + (oldPin == null || oldPin.getLength() >= pinSpec.getMinLength()) && + getLength() >= pinSpec.getMinLength() && + compare()); } } diff --git a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties index 1e0bc9f5..6d651b2d 100644 --- a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties +++ b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties @@ -20,6 +20,7 @@ title.cardnotsupported=<html>Die Karte wird nicht unterst\u00FCtzt</html> title.cardpin=<html>Karte wird gelesen</html> title.sign=<html>Signatur erstellen</html> title.error=<html>Fehler</html> +title.entry.timeout=<html>Zeit\u00FCberschreitung</html> title.retry=<html>Falsche PIN</html> title.wait=<html>Bitte warten</html> title.hashdata=<html>Signaturdaten</html> @@ -28,19 +29,25 @@ windowtitle.savedir=Signaturdaten in Verzeichnis speichern windowtitle.overwrite=Datei \u00FCberschreiben? windowtitle.viewer=Signaturdaten windowtitle.help=Hilfe zur B\u00FCrgerkarte -message.wait=<html>Bitte warten...</html> -message.insertcard=<html>Bitte die B\u00FCrgerkarte in den Kartenleser stecken</html> -message.enterpin=<html>{0} eingeben</html> -message.hashdatalink=<html><a href=\"anzeige\">Signaturdaten anzeigen</a></html> -message.hashdatalink.tiny=<html><a href=\"anzeige\">Signaturdaten</a></html> + +# removed message.* prefix to reuse keys as help keys +welcome=<html>Bitte warten...</html> +wait=<html>Bitte warten...</html> +cardnotsupported=<html>Bitte die B\u00FCrgerkarte in den Kartenleser stecken</html> +insertcard=<html>Bitte die B\u00FCrgerkarte in den Kartenleser stecken</html> +enterpin=<html>{0} eingeben</html> +enterpin.pinpad=<html>{0} ({1} stellig) am Kartenleser eingeben</html> +hashdatalink=<html><a href=\"anzeige\">Signaturdaten anzeigen</a></html> +hashdatalink.tiny=<html><a href=\"anzeige\">Signaturdaten</a></html> #message.hashdata=<html>Hinweis: Dies ist eine Voransicht des zu signierenden Inhalts. F\u00FCr eine standardkonforme Darstellung siehe Hilfe (i).</html> #message.hashdata=<html>Dies ist eine Voransicht des zu signierenden Inhaltes. F\u00FCr Details siehe Hilfe (i).</html> #verwenden sie bitte die von ihrem System zur Verf\u00FCgung gestellte {0} Anwendung. -message.hashdatalist=<html>{0} Signaturdaten:</html> -message.retries.last=<html>Letzter Versuch!</html> -message.retries=<html>Noch {0} Versuche</html> -message.overwrite=<html>M\u00F6chten Sie das existierende Dokument {0} \u00FCberschreiben?</html> -message.help=<html>Hilfe zu {0}</html> +hashdatalist=<html>{0} Signaturdaten:</html> +retries.last=<html>Letzter Versuch!</html> +retries=<html>Noch {0} Versuche</html> +overwrite=<html>M\u00F6chten Sie das existierende Dokument {0} \u00FCberschreiben?</html> +help=<html>Hilfe zu {0}</html> + warning.xhtml=<html>Hinweis: Dies ist eine Voransicht des zu signierenden Inhalts. F\u00FCr eine standardkonforme Darstellung siehe Hilfe (i).</html> label.pin=<html>{0}:</html> label.pinsize=<html>({0} stellig)</html> @@ -73,6 +80,7 @@ error.unknown=<html>Ein Fehler trat auf</html> error.test=<html>Fehler1 {0} - Fehler2 {1}</html> error.card.locked=<html>B\u00FCrgerkarte ist gesperrt</html> error.card.notactivated=<html>B\u00FCrgerkartenfunktion ist nicht aktiviert</html> +error.pin.timeout=<html>Zeit\u00FCberschreitung bei Eingabe der PIN</html> error.viewer=Der Inhalt kann nicht dargestellt werden: {0} error.external.link=<html>Externer Link {0} wird nicht ge\u00F6ffnet</html> error.config=<html>Fehlerhafte Konfiguration des Systems: {0}</html> diff --git a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_en.properties b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_en.properties index 4fbccd5b..2fb66969 100644 --- a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_en.properties +++ b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_en.properties @@ -20,6 +20,7 @@ title.cardnotsupported=<html>This card is not supported</html> title.cardpin=<html>Reading card</html> title.sign=<html>Create signature</html> title.error=<html>Error</html> +title.entry.timeout=<html>Timeout</html> title.retry=<html>Wrong PIN</html> title.wait=<html>Please wait</html> title.hashdata=<html>Signature data</html> @@ -28,17 +29,23 @@ windowtitle.savedir=Save signature data to directory windowtitle.overwrite=Overwrite file? windowtitle.viewer=Signature data windowtitle.help=Citizen card help -message.wait=<html>Please wait...</html> -message.insertcard=<html>Please insert your citizen card into the reader</html> -message.enterpin=<html>Enter {0}</html> -message.hashdatalink=<html><a href=\"anzeige\">Display signature data</a></html> -message.hashdatalink.tiny=<html><a href=\"anzeige\">signature data</a></html> + +# removed message.* prefix to reuse keys as help keys +welcome=<html>Please wait...</html> +wait=<html>Please wait...</html> +insertcard=<html>Please insert your citizen card into the reader</html> +cardnotsupported=<html>Please insert your citizen card into the reader</html> +enterpin=<html>Enter {0}</html> +enterpin.pinpad=<html>Enter {0} ({1} digits) on card reader pinpad</html> +hashdatalink=<html><a href=\"anzeige\">Display signature data</a></html> +hashdatalink.tiny=<html><a href=\"anzeige\">signature data</a></html> #message.hashdata=<html>Remark: This is a preview of the data to-be signed. For standards compliant display see help.</html> -message.hashdatalist=<html>{0} signature data objects:</html> -message.retries.last=<html>Last try!</html> -message.retries=<html>{0} tries left</html> -message.overwrite=<html>Overwrite {0}?</html> -message.help=<html>Help topic {0}</html> +hashdatalist=<html>{0} signature data objects:</html> +retries.last=<html>Last try!</html> +retries=<html>{0} tries left</html> +overwrite=<html>Overwrite {0}?</html> +help=<html>Help topic {0}</html> + warning.xhtml=<html>Remark: This is a preview of the data to-be signed. For standards compliant display see help.</html> label.pin=<html>{0}:</html> label.pinsize=<html>({0} digits)</html> @@ -71,6 +78,7 @@ error.unknown=<html>An error occured</html> error.test=<html>Error1 {0} - Error2 {1}</html> error.card.locked=<html>Citizen card is locked</html> error.card.notactivated=<html>Citizen card not activated</html> +error.pin.timeout=<html>Timeout during PIN entry</html> error.viewer=Failed to display contents: {0} error.external.link=<html>Cannot open external link {0}</html> error.config=<html>Incorrect system configuration: {0}</html> diff --git a/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java index ef64ac59..194e18b0 100644 --- a/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java +++ b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java @@ -78,7 +78,7 @@ public class BKUGUIWorker implements Runnable { @Override public void actionPerformed(ActionEvent e) { - gui.showSignaturePINDialog(signPinSpec, signListener, "sign", cancelListener, "cancel", null, "hashdata"); + gui.showSignaturePINDialog(signPinSpec, -1, signListener, "sign", cancelListener, "cancel", null, "hashdata"); } }; HashDataInput signedRef1 = new ByteArrayHashDataInput( @@ -116,7 +116,7 @@ public class BKUGUIWorker implements Runnable { // signedRefs.add(signedRef4); // signedRefs.add(signedRef4); // signedRefs = Collections.singletonList(signedRef1); - gui.showHashDataInputDialog(signedRefs, returnListener, "return"); + gui.showSecureViewer(signedRefs, returnListener, "return"); } }; @@ -149,7 +149,7 @@ public class BKUGUIWorker implements Runnable { // // Thread.sleep(2000); // - gui.showSignaturePINDialog(signPinSpec, signListener, "sign", cancelListener, "cancel", hashdataListener, "hashdata"); + gui.showSignaturePINDialog(signPinSpec, -1, signListener, "sign", cancelListener, "cancel", hashdataListener, "hashdata"); // // Thread.sleep(4000); // diff --git a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/BKUGuiProxy.java b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/BKUGuiProxy.java index 1714017e..5a0ba84a 100644 --- a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/BKUGuiProxy.java +++ b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/BKUGuiProxy.java @@ -40,27 +40,27 @@ public class BKUGuiProxy implements BKUGUIFacade { return delegate.getLocale();
}
+// @Override
+// public void showCardNotSupportedDialog(ActionListener cancelListener,
+// String actionCommand) {
+// showDialog();
+// delegate.showCardNotSupportedDialog(cancelListener, actionCommand);
+// }
+//
+// @Override
+// public void showCardPINDialog(PINSpec pinSpec, ActionListener okListener,
+// String okCommand, ActionListener cancelListener, String cancelCommand) {
+// showDialog();
+// delegate.showCardPINDialog(pinSpec, okListener, okCommand, cancelListener,
+// cancelCommand);
+// }
+//
@Override
- public void showCardNotSupportedDialog(ActionListener cancelListener,
- String actionCommand) {
- showDialog();
- delegate.showCardNotSupportedDialog(cancelListener, actionCommand);
- }
-
- @Override
- public void showCardPINDialog(PINSpec pinSpec, ActionListener okListener,
- String okCommand, ActionListener cancelListener, String cancelCommand) {
- showDialog();
- delegate.showCardPINDialog(pinSpec, okListener, okCommand, cancelListener,
- cancelCommand);
- }
-
- @Override
- public void showCardPINRetryDialog(PINSpec pinSpec, int numRetries,
+ public void showCardPINDialog(PINSpec pinSpec, int numRetries,
ActionListener okListener, String okCommand,
ActionListener cancelListener, String cancelCommand) {
showDialog();
- delegate.showCardPINRetryDialog(pinSpec, numRetries, okListener, okCommand,
+ delegate.showCardPINDialog(pinSpec, numRetries, okListener, okCommand,
cancelListener, cancelCommand);
}
@@ -77,57 +77,71 @@ public class BKUGuiProxy implements BKUGUIFacade { delegate.showErrorDialog(errorMsgKey, errorMsgParams);
}
+// @Override
+// public void showInsertCardDialog(ActionListener cancelListener,
+// String actionCommand) {
+// showDialog();
+// delegate.showInsertCardDialog(cancelListener, actionCommand);
+// }
+//
+// @Override
+// public void showSignaturePINDialog(PINSpec pinSpec,
+// ActionListener signListener, String signCommand,
+// ActionListener cancelListener, String cancelCommand,
+// ActionListener hashdataListener, String hashdataCommand) {
+// showDialog();
+// delegate.showSignaturePINDialog(pinSpec, signListener, signCommand,
+// cancelListener, cancelCommand, hashdataListener, hashdataCommand);
+// }
+//
@Override
- public void showInsertCardDialog(ActionListener cancelListener,
- String actionCommand) {
- showDialog();
- delegate.showInsertCardDialog(cancelListener, actionCommand);
- }
-
- @Override
- public void showSignaturePINDialog(PINSpec pinSpec,
- ActionListener signListener, String signCommand,
- ActionListener cancelListener, String cancelCommand,
- ActionListener hashdataListener, String hashdataCommand) {
- showDialog();
- delegate.showSignaturePINDialog(pinSpec, signListener, signCommand,
- cancelListener, cancelCommand, hashdataListener, hashdataCommand);
- }
-
- @Override
- public void showSignaturePINRetryDialog(PINSpec pinSpec, int numRetries,
+ public void showSignaturePINDialog(PINSpec pinSpec, int numRetries,
ActionListener okListener, String okCommand,
ActionListener cancelListener, String cancelCommand,
ActionListener hashdataListener, String hashdataCommand) {
showDialog();
- delegate.showSignaturePINRetryDialog(pinSpec, numRetries, okListener,
+ delegate.showSignaturePINDialog(pinSpec, numRetries, okListener,
okCommand, cancelListener, cancelCommand, hashdataListener,
hashdataCommand);
}
+//
+// @Override
+// public void showWaitDialog(String waitMessage) {
+// showDialog();
+// delegate.showWaitDialog(waitMessage);
+// }
+//
+// @Override
+// public void showWelcomeDialog() {
+// showDialog();
+// delegate.showWelcomeDialog();
+// }
@Override
- public void showWaitDialog(String waitMessage) {
+ public void showSecureViewer(List<HashDataInput> signedReferences,
+ ActionListener okListener,
+ String okCommand) {
showDialog();
- delegate.showWaitDialog(waitMessage);
+ delegate.showSecureViewer(signedReferences, okListener, okCommand);
}
@Override
- public void showWelcomeDialog() {
+ public void showMessageDialog(String titleKey,
+ String msgKey, Object[] msgParams,
+ String buttonKey, ActionListener okListener, String okCommand) {
showDialog();
- delegate.showWelcomeDialog();
+ delegate.showMessageDialog(titleKey, msgKey, msgParams, buttonKey, okListener, okCommand);
}
@Override
- public void showHashDataInputDialog(List<HashDataInput> signedReferences,
- ActionListener okListener,
- String okCommand) {
+ public void showMessageDialog(String titleKey, String msgKey, Object[] msgParams) {
showDialog();
- delegate.showHashDataInputDialog(signedReferences, okListener, okCommand);
+ delegate.showMessageDialog(titleKey, msgKey, msgParams);
}
@Override
- public void showMessageDialog(String titleKey, String msgKey, Object[] msgParams, ActionListener okListener, String okCommand) {
+ public void showMessageDialog(String titleKey, String msgKey) {
showDialog();
- delegate.showMessageDialog(titleKey, msgKey, msgParams, okListener, okCommand);
+ delegate.showMessageDialog(titleKey, msgKey);
}
}
diff --git a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSignRequestHandler.java b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSignRequestHandler.java index 46f915a9..531e6591 100644 --- a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSignRequestHandler.java +++ b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSignRequestHandler.java @@ -67,7 +67,7 @@ public class LocalSignRequestHandler extends SignRequestHandler { * @throws java.lang.Exception */ @Override - public void displayHashDataInputs(List<ReferenceType> dsigReferences) throws Exception { + public void displayDataToBeSigned(List<ReferenceType> dsigReferences) throws Exception { if (dsigReferences == null || dsigReferences.size() < 1) { log.error("No hashdata input selected to be displayed: null"); throw new Exception("No HashData Input selected to be displayed"); @@ -109,7 +109,7 @@ public class LocalSignRequestHandler extends SignRequestHandler { log.error("dsig:SignedInfo does not contain a data reference"); throw new Exception("dsig:SignedInfo does not contain a data reference"); } - gui.showHashDataInputDialog(selectedHashDataInputs, this, "hashDataDone"); + gui.showSecureViewer(selectedHashDataInputs, this, "hashDataDone"); } private ByteArrayHashDataInput getByteArrayHashDataInput(HashDataInput hashDataInput) throws IOException { diff --git a/BKULocalApp/src/main/java/at/gv/egiz/bku/local/app/Container.java b/BKULocalApp/src/main/java/at/gv/egiz/bku/local/app/Container.java index d15d2c1b..833dbf4d 100644 --- a/BKULocalApp/src/main/java/at/gv/egiz/bku/local/app/Container.java +++ b/BKULocalApp/src/main/java/at/gv/egiz/bku/local/app/Container.java @@ -1,10 +1,5 @@ package at.gv.egiz.bku.local.app;
-import java.io.File;
-import java.io.IOException;
-import java.net.URL;
-import java.net.URLClassLoader;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.mortbay.jetty.Connector;
diff --git a/BKUOnline/src/main/webapp/helpfiles/de/help.cardnotsupported.html b/BKUOnline/src/main/webapp/helpfiles/de/cardnotsupported.html index c647bf72..021ddfa7 100644 --- a/BKUOnline/src/main/webapp/helpfiles/de/help.cardnotsupported.html +++ b/BKUOnline/src/main/webapp/helpfiles/de/cardnotsupported.html @@ -21,7 +21,7 @@ <h1>Online-Hilfe</h1> <!-- end #header --></div> <div id="sidebar1"> - <p><img src="../../helpfiles/de/help.cardnotsupported.png" alt="Bildschirmfoto des Applets" width="190" height="130"/></p> + <p><img src="../../helpfiles/de/cardnotsupported.png" alt="Bildschirmfoto des Applets" width="190" height="130"/></p> <p><strong>Hinweis:</strong> Das Bildschirmfoto oben kann von der Darstellung in der Webseite abweichen.</p> <!-- end #sidebar1 --></div> <div id="mainContent"> diff --git a/BKUOnline/src/main/webapp/helpfiles/de/help.cardnotsupported.png b/BKUOnline/src/main/webapp/helpfiles/de/cardnotsupported.png Binary files differindex c3b7ce6b..c3b7ce6b 100644 --- a/BKUOnline/src/main/webapp/helpfiles/de/help.cardnotsupported.png +++ b/BKUOnline/src/main/webapp/helpfiles/de/cardnotsupported.png diff --git a/BKUOnline/src/main/webapp/helpfiles/de/help.insertcard.html b/BKUOnline/src/main/webapp/helpfiles/de/insertcard.html index 0bfc6230..f7f1a28a 100644 --- a/BKUOnline/src/main/webapp/helpfiles/de/help.insertcard.html +++ b/BKUOnline/src/main/webapp/helpfiles/de/insertcard.html @@ -21,7 +21,7 @@ <h1>Online-Hilfe</h1> <!-- end #header --></div> <div id="sidebar1"> - <p><img src="../../helpfiles/de/help.insertcard.png" alt="Bildschirmfoto des Applets" width="190" height="130"/></p> + <p><img src="../../helpfiles/de/insertcard.png" alt="Bildschirmfoto des Applets" width="190" height="130"/></p> <p><strong>Hinweis:</strong> Das Bildschirmfoto oben kann von der Darstellung in der Webseite abweichen.</p> <!-- end #sidebar1 --></div> <div id="mainContent"> diff --git a/BKUOnline/src/main/webapp/helpfiles/de/help.insertcard.png b/BKUOnline/src/main/webapp/helpfiles/de/insertcard.png Binary files differindex 62a22975..62a22975 100644 --- a/BKUOnline/src/main/webapp/helpfiles/de/help.insertcard.png +++ b/BKUOnline/src/main/webapp/helpfiles/de/insertcard.png diff --git a/BKUOnline/src/main/webapp/helpfiles/de/help.wait.html b/BKUOnline/src/main/webapp/helpfiles/de/wait.html index ed3db1b8..8561ff35 100644 --- a/BKUOnline/src/main/webapp/helpfiles/de/help.wait.html +++ b/BKUOnline/src/main/webapp/helpfiles/de/wait.html @@ -21,7 +21,7 @@ <h1>Online-Hilfe</h1> <!-- end #header --></div> <div id="sidebar1"> - <p><img src="../../helpfiles/de/help.wait.png" alt="Bildschirmfoto des Applets" width="190" height="130"/></p> + <p><img src="../../helpfiles/de/wait.png" alt="Bildschirmfoto des Applets" width="190" height="130"/></p> <p><strong>Hinweis:</strong> Das Bildschirmfoto oben kann von der Darstellung in der Webseite abweichen.</p> <!-- end #sidebar1 --></div> <div id="mainContent"> diff --git a/BKUOnline/src/main/webapp/helpfiles/de/help.wait.png b/BKUOnline/src/main/webapp/helpfiles/de/wait.png Binary files differindex 63a38fbf..63a38fbf 100644 --- a/BKUOnline/src/main/webapp/helpfiles/de/help.wait.png +++ b/BKUOnline/src/main/webapp/helpfiles/de/wait.png diff --git a/BKUOnline/src/main/webapp/helpfiles/de/help.welcome.html b/BKUOnline/src/main/webapp/helpfiles/de/welcome.html index 9796a206..6c5463e5 100644 --- a/BKUOnline/src/main/webapp/helpfiles/de/help.welcome.html +++ b/BKUOnline/src/main/webapp/helpfiles/de/welcome.html @@ -21,7 +21,7 @@ <h1>Online-Hilfe</h1> <!-- end #header --></div> <div id="sidebar1"> - <p><img src="../../helpfiles/de/help.welcome.png" alt="Bildschirmfoto des Applets" width="190" height="130"/></p> + <p><img src="../../helpfiles/de/welcome.png" alt="Bildschirmfoto des Applets" width="190" height="130"/></p> <p><strong>Hinweis:</strong> Das Bildschirmfoto oben kann von der Darstellung in der Webseite abweichen.</p> <!-- end #sidebar1 --></div> <div id="mainContent"> diff --git a/BKUOnline/src/main/webapp/helpfiles/de/help.welcome.png b/BKUOnline/src/main/webapp/helpfiles/de/welcome.png Binary files differindex 78133b4d..78133b4d 100644 --- a/BKUOnline/src/main/webapp/helpfiles/de/help.welcome.png +++ b/BKUOnline/src/main/webapp/helpfiles/de/welcome.png diff --git a/smcc/src/main/java/at/gv/egiz/smcc/ACOS04Card.java b/smcc/src/main/java/at/gv/egiz/smcc/ACOS04Card.java new file mode 100644 index 00000000..9fca6ab9 --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/ACOS04Card.java @@ -0,0 +1,30 @@ +/* + * 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; + +/** + * + * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at> + */ +public class ACOS04Card extends ACOSCard { + + public ACOS04Card() { + pinSpecs.remove(PINSPEC_INF); + } + +} 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 c2c62fd8..01b9155b 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java @@ -29,9 +29,10 @@ package at.gv.egiz.smcc; import at.gv.egiz.smcc.util.SMCCHelper; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; import java.nio.charset.Charset; -import javax.smartcardio.Card; import javax.smartcardio.CardChannel; import javax.smartcardio.CardException; import javax.smartcardio.CommandAPDU; @@ -100,9 +101,9 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { (byte) 0x01 // RSA // TODO: Not verified yet }; - private static final int PINSPEC_INF = 0; - private static final int PINSPEC_DEC = 1; - private static final int PINSPEC_SIG = 2; + protected static final int PINSPEC_INF = 0; + protected static final int PINSPEC_DEC = 1; + protected static final int PINSPEC_SIG = 2; public ACOSCard() { super("at/gv/egiz/smcc/ACOSCard"); @@ -179,15 +180,12 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { //new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("inf.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(); @@ -234,20 +232,17 @@ public class ACOSCard 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 { pin = provider.providePIN(spec, retries); - if (pin == null) { - throw new CancelledException(); - } try { getCard().beginExclusive(); // SELECT DF selectFileFID(DF_SIG); // VERIFY - retries = verifyPIN(pin, KID_PIN_SIG); + retries = verifyPIN(KID_PIN_SIG, pin); if (retries != -1) { throw new VerificationFailedException(retries); } @@ -259,7 +254,7 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { return psoComputDigitalSiganture(); } catch (SecurityStatusNotSatisfiedException e) { - retries = verifyPIN(null, KID_PIN_SIG); + retries = verifyPIN(KID_PIN_SIG); } catch (VerificationFailedException e) { retries = e.getRetries(); } finally { @@ -276,15 +271,12 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { //new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("dec.pin.name")); int retries = -1; - String pin = null; - boolean pinRequiered = false; + char[] pin = null; + boolean pinRequired = false; do { - if (pinRequiered) { + if (pinRequired) { pin = provider.providePIN(spec, retries); - if (pin == null) { - throw new CancelledException(); - } } try { getCard().beginExclusive(); @@ -292,7 +284,7 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { // SELECT DF selectFileFID(DF_DEC); // VERIFY - retries = verifyPIN(pin, KID_PIN_DEC); + retries = verifyPIN(KID_PIN_DEC, pin); if (retries != -1) { throw new VerificationFailedException(retries); } @@ -304,10 +296,10 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { } catch (FileNotFoundException e) { throw new NotActivatedException(); } catch (SecurityStatusNotSatisfiedException e) { - pinRequiered = true; - retries = verifyPIN(null, KID_PIN_DEC); + pinRequired = true; + retries = verifyPIN(KID_PIN_DEC); } catch (VerificationFailedException e) { - pinRequiered = true; + pinRequired = true; retries = e.getRetries(); } finally { getCard().endExclusive(); @@ -328,48 +320,16 @@ public class ACOSCard 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, 0x00, 0x00, fid, 256)); } - @Override - protected int verifyPIN(String pin, byte kid) throws LockedException, NotActivatedException, SignatureCardException { - - CardChannel channel = getCardChannel(); - - ResponseAPDU resp; - try { - if (pin != null) { - resp = transmit(channel, new CommandAPDU(0x00, 0x20, 0x00, kid, encodePINBlock(pin)), false); - } else { - //TODO this is not supported - resp = transmit(channel, new CommandAPDU(0x00, 0x20, 0x00, kid), false); - } - } catch (CardException ex) { - log.error("smart card communication failed: " + ex.getMessage()); - throw new SignatureCardException("smart card communication failed: " + ex.getMessage(), ex); - } - - //6A 00 (falshe P1/P2) nicht in contextAID - //69 85 (nutzungsbedingungen nicht erfüllt) in DF_Sig und nicht sigpin - - if (resp.getSW() == 0x63c0) { - throw new LockedException("PIN locked."); - } else if (resp.getSW1() == 0x63 && resp.getSW2() >> 4 == 0xc) { - // return number of possible retries - return resp.getSW2() & 0x0f; - } else if (resp.getSW() == 0x6983) { - throw new NotActivatedException(); - } else if (resp.getSW() == 0x9000) { - return -1; - } else { - throw new SignatureCardException("Failed to verify pin: SW=" - + Integer.toHexString(resp.getSW()) + "."); - } - } - private void mseSetDST(int p1, int p2, byte[] dst) throws CardException, SignatureCardException { CardChannel channel = getCardChannel(); ResponseAPDU resp = transmit(channel, new CommandAPDU(0x00, 0x22, p1, @@ -426,92 +386,294 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { } } - @Override - public String toString() { - return "a-sign premium"; - } - /** - * ASCII encoded pin, padded with 0x00 - * @param pin - * @return a 8 byte pin block + * + * @param kid + * @return -1 */ - private byte[] encodePINBlock(String pin) { - byte[] asciiPIN = pin.getBytes(Charset.forName("ASCII")); - byte[] encodedPIN = new byte[8]; - System.arraycopy(asciiPIN, 0, encodedPIN, 0, Math.min(asciiPIN.length, - encodedPIN.length)); -// System.out.println("ASCII encoded PIN block: " + SMCCHelper.toString(encodedPIN)); - return encodedPIN; + @Override + protected int verifyPIN(byte kid) { + log.debug("VERIFY PIN without PIN BLOCK not supported by ACOS"); + return -1; } @Override - public void activatePIN(PINSpec pinSpec, String pin) throws SignatureCardException { - throw new SignatureCardException("PIN activation not supported by this card"); + protected int verifyPIN(byte kid, char[] pin) + throws LockedException, NotActivatedException, CancelledException, TimeoutException, SignatureCardException { + try { + 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 { + byte[] pinBlock = encodePINBlock(pin); + 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(); + } + + //6A 00 (falshe P1/P2) nicht in contextAID + //69 85 (nutzungsbedingungen nicht erfüllt) in DF_Sig und nicht sigpin + + 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 NotActivatedException("[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); + } } /** * SCARD_E_NOT_TRANSACTED inf/dec PIN not active (pcsc crash) - * @param pinSpec - * @param oldPIN - * @param newPIN + * @param kid + * @param oldPin + * @param newPin + * @return * @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(); + protected int changePIN(byte kid, char[] oldPin, char[] newPin) + throws LockedException, NotActivatedException, CancelledException, TimeoutException, 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); + 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); - ResponseAPDU responseAPDU = transmit(channel, - new CommandAPDU(0x00, 0x24, 0x00, pinSpec.getKID(), cmd), false); + CardChannel channel = getCardChannel(); - icc.endExclusive(); + ResponseAPDU resp = transmit(channel, + new CommandAPDU(0x00, 0x24, 0x00, kid, cmd), false); - log.debug("change pin returned SW=" + Integer.toHexString(responseAPDU.getSW())); + sw = new byte[2]; + sw[0] = (byte) resp.getSW1(); + sw[1] = (byte) resp.getSW2(); + } - 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) { + // 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 // sig-pin only (card not transacted for inf/dec pin) - log.error(pinSpec.getLocalizedName() + " not activated"); - throw new NotActivatedException(); - } else if (responseAPDU.getSW() != 0x9000) { - String msg = "Failed to change " + pinSpec.getLocalizedName() + - ": SW=" + Integer.toHexString(responseAPDU.getSW()); - log.error(msg); - throw new SignatureCardException(msg); + throw new NotActivatedException("[69:83]"); + } 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 change " + pinSpec.getLocalizedName() + - ": " + ex.getMessage()); - throw new SignatureCardException(ex.getMessage(), ex); + log.error("smart card communication failed: " + ex.getMessage()); + throw new SignatureCardException("smart card communication failed: " + ex.getMessage(), ex); } } + + /** + * throws SignatureCardException (PIN activation not supported by ACOS) + * @throws at.gv.egiz.smcc.SignatureCardException + */ + @Override + public void activatePIN(byte kid, char[] pin) + throws SignatureCardException { + log.error("ACTIVATE PIN not supported by ACOS"); + throw new SignatureCardException("PIN activation not supported by this card"); + } + + /** + * ASCII encoded pin, padded with 0x00 + * @param pin + * @return a 8 byte pin block + */ + @Override + protected byte[] encodePINBlock(char[] pin) { +// byte[] asciiPIN = new String(pin).getBytes(Charset.forName("ASCII")); + CharBuffer chars = CharBuffer.wrap(pin); + ByteBuffer bytes = Charset.forName("ASCII").encode(chars); + byte[] asciiPIN = bytes.array(); + byte[] encodedPIN = new byte[8]; + System.arraycopy(asciiPIN, 0, encodedPIN, 0, Math.min(asciiPIN.length, + encodedPIN.length)); +// System.out.println("ASCII encoded PIN block: " + SMCCHelper.toString(encodedPIN)); + return encodedPIN; + } + + private byte[] getPINVerifyStructure(byte kid) { + + byte bTimeOut = (byte) 00; // Default time out + byte bTimeOut2 = (byte) 00; // Default time out + byte bmFormatString = (byte) 0x82; // 1 0001 0 01 + // ^------------ System unit = byte + // ^^^^------- PIN position in the frame = 1 byte + // ^----- PIN justification left + // ^^-- BCD format + // 1 0000 0 10 + // ^^-- ASCII format + byte bmPINBlockString = (byte) 0x08; // 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) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, // Data + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 // Data + }; + + 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); + + return pinVerifyStructure; + } + + public byte[] getPINModifyStructure(byte kid) { + + byte bTimeOut = (byte) 00; // Default time out + byte bTimeOut2 = (byte) 00; // Default time out + byte bmFormatString = (byte) 0x82; // 1 0001 0 01 + // ^------------ System unit = byte + // ^^^^------- PIN position in the frame = 1 byte + // ^----- PIN justification left + // ^^-- BCD format + // 1 0000 0 10 + // ^^-- ASCII format + byte bmPINBlockString = (byte) 0x08; // 0100 0111 + // ^^^^--------- PIN length size: 4 bits + // ^^^^---- Length PIN = 7 bytes + byte bmPINLengthFormat = (byte) 0x00; // 000 0 0100 + // ^-------- System bit units is bit + // ^^^^--- PIN length is at the 4th position bit + byte bInsertionOffsetOld = (byte) 0x00; // insertion position offset in bytes + byte bInsertionOffsetNew = (byte) 0x00; // 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); + + return pinModifyStructure; + } + + @Override + public String toString() { + return "a-sign premium"; + } } 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 39952bb9..6587aaf9 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java @@ -33,12 +33,12 @@ 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; @@ -54,6 +54,14 @@ public abstract class AbstractSignatureCard implements SignatureCard { private static Log log = LogFactory.getLog(AbstractSignatureCard.class); + static final short GET_FEATURE_REQUEST = 3400; + + private static int getCtrlCode(short function) { + return 0x310000 | ((0xFFFF & function) << 2); + } + + protected Map<Byte, Long> ifdCtrlCmds; + protected List<PINSpec> pinSpecs = new ArrayList<PINSpec>(); private ResourceBundle i18n; @@ -106,11 +114,14 @@ public abstract class AbstractSignatureCard implements SignatureCard { */ protected byte[] selectFileAID(byte[] dfName) throws CardException, SignatureCardException { CardChannel channel = getCardChannel(); - ResponseAPDU resp = transmit(channel, new CommandAPDU(0x00, 0xA4, 0x04, - 0x00, dfName, 256)); + ResponseAPDU resp = transmit(channel, + new CommandAPDU(0x00, 0xA4, 0x04, 0x00, dfName, 256)); +// new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, dfName)); if (resp.getSW() != 0x9000) { - throw new SignatureCardException("Failed to select application AID=" - + toString(dfName) + ": SW=" + Integer.toHexString(resp.getSW()) + "."); + String msg = "Failed to select application AID=" + SMCCHelper.toString(dfName) + + ": SW=" + Integer.toHexString(resp.getSW()); + log.error(msg); + throw new SignatureCardException(msg); } else { return resp.getBytes(); } @@ -119,10 +130,63 @@ public abstract class AbstractSignatureCard implements SignatureCard { protected abstract ResponseAPDU selectFileFID(byte[] fid) throws CardException, SignatureCardException; - protected abstract int verifyPIN(String pin, byte kid) + /** + * VERIFY APDU without PIN BLOCK + * Not supported by ACOS cards (and GemPC Pinpad?) + * @param kid + * @return the number of possible tries until card is blocked or -1 if unknown + * (ACOS does not support this VERIFY APDU type) + * @throws at.gv.egiz.smcc.LockedException + * @throws at.gv.egiz.smcc.NotActivatedException + * @throws at.gv.egiz.smcc.SignatureCardException + */ + protected abstract int verifyPIN(byte kid) throws LockedException, NotActivatedException, SignatureCardException; - + /** + * VERIFY APDU with PIN BLOCK + * If IFD supports VERIFY_PIN on pinpad, parameter pin may be empty. + * @param kid + * @param pin to be encoded in the PIN BLOCK + * @return -1 if VERIFY PIN was successful, or the number of possible retries + * @throws at.gv.egiz.smcc.LockedException + * @throws at.gv.egiz.smcc.NotActivatedException + * @throws at.gv.egiz.smcc.SignatureCardException + */ + protected abstract int verifyPIN(byte kid, char[] pin) + throws LockedException, NotActivatedException, CancelledException, TimeoutException, SignatureCardException; + + /** + * CHANGE(?) APDU + * If IFD supports VERIFY_PIN on pinpad, parameter pin may be empty. + * @param kid + * @param pin + * @throws at.gv.egiz.smcc.SignatureCardException if activation fails + */ + protected abstract void activatePIN(byte kid, char[] pin) + throws CancelledException, TimeoutException, SignatureCardException; + + /** + * CHANGE(?) APDU + * If IFD supports VERIFY_PIN on pinpad, parameter pin may be empty. + * @param kid + * @param pin + * @return -1 if CHANGE PIN was successful, or the number of possible retries + * @throws at.gv.egiz.smcc.SignatureCardException if change fails + */ + protected abstract int changePIN(byte kid, char[] oldPin, char[] newPin) + throws CancelledException, TimeoutException, SignatureCardException; + + /** + * encode the pin as needed in VERIFY/CHANGE APDUs + * @param pin + * @return + * @throws at.gv.egiz.smcc.SignatureCardException if the provided pin does + * not meet the restrictions imposed by the encoding (not the pinSpec!), + * such as maximum Length + */ + protected abstract byte[] encodePINBlock(char[] pin) throws SignatureCardException; + protected byte[] readRecord(int recordNumber) throws SignatureCardException, CardException { return readRecord(getCardChannel(), recordNumber); } @@ -295,7 +359,7 @@ public abstract class AbstractSignatureCard implements SignatureCard { * @throws SignatureCardException * @throws CardException */ - protected byte[] readTLVFile(byte[] aid, byte[] ef, String pin, byte kid, int maxLength) + protected byte[] readTLVFile(byte[] aid, byte[] ef, char[] pin, byte kid, int maxLength) throws SignatureCardException, InterruptedException, CardException { @@ -318,7 +382,7 @@ public abstract class AbstractSignatureCard implements SignatureCard { // VERIFY if (pin != null) { - int retries = verifyPIN(pin, kid); + int retries = verifyPIN(kid, pin); if (retries != -1) { throw new VerificationFailedException(retries); } @@ -388,6 +452,7 @@ public abstract class AbstractSignatureCard implements SignatureCard { ifs_ = 0xFF & atr.getBytes()[6]; log.trace("Setting IFS (information field size) to " + ifs_); } + ifdCtrlCmds = queryIFDFeatures(); } @Override @@ -446,39 +511,266 @@ public abstract class AbstractSignatureCard implements SignatureCard { } @Override - public int verifyPIN(PINSpec pinSpec, String pin) throws LockedException, NotActivatedException, SignatureCardException { - - Card icc = getCard(); + public void verifyPIN(PINSpec pinSpec, PINProvider pinProvider) + throws LockedException, NotActivatedException, CancelledException, TimeoutException, SignatureCardException, InterruptedException { try { - icc.beginExclusive(); - CardChannel channel = icc.getBasicChannel(); + getCard().beginExclusive(); if (pinSpec.getContextAID() != null) { - ResponseAPDU responseAPDU = transmit(channel, - new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, pinSpec.getContextAID())); - if (responseAPDU.getSW() != 0x9000) { - icc.endExclusive(); - String msg = "Failed to verify PIN " + - SMCCHelper.toString(new byte[]{pinSpec.getKID()}) + - ": Failed to verify AID " + - SMCCHelper.toString(pinSpec.getContextAID()) + - ": " + SMCCHelper.toString(responseAPDU.getBytes()); - log.error(msg); - throw new SignatureCardException(msg); - } + selectFileAID(pinSpec.getContextAID()); } - return verifyPIN(pin, pinSpec.getKID()); + + int retries = verifyPIN(pinSpec.getKID()); + do { + char[] pin = pinProvider.providePIN(pinSpec, retries); + retries = verifyPIN(pinSpec.getKID(), pin); + } while (retries > 0); + //return on -1, 0 never reached: verifyPIN throws LockedEx } catch (CardException ex) { - log.error("failed to verify pinspec: " + ex.getMessage(), ex); + log.error("failed to verify " + pinSpec.getLocalizedName() + + ": " + ex.getMessage(), ex); throw new SignatureCardException(ex); } finally { try { - icc.endExclusive(); + getCard().endExclusive(); + } catch (CardException ex) { + log.trace("failed to end exclusive card access: " + ex.getMessage()); + } + } + } + + @Override + public void activatePIN(PINSpec pinSpec, PINProvider pinProvider) + throws CancelledException, SignatureCardException, CancelledException, TimeoutException, InterruptedException { + try { + getCard().beginExclusive(); + + if (pinSpec.getContextAID() != null) { + selectFileAID(pinSpec.getContextAID()); + } + char[] pin = pinProvider.providePIN(pinSpec, -1); + activatePIN(pinSpec.getKID(), pin); + + } catch (CardException ex) { + log.error("Failed to activate " + pinSpec.getLocalizedName() + + ": " + ex.getMessage()); + throw new SignatureCardException(ex.getMessage(), ex); + } finally { + try { + getCard().endExclusive(); } catch (CardException ex) { log.trace("failed to end exclusive card access: " + ex.getMessage()); } + } + } + + /** + * 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, ChangePINProvider pinProvider) + throws LockedException, NotActivatedException, CancelledException, TimeoutException, SignatureCardException, InterruptedException { + try { + getCard().beginExclusive(); + + if (pinSpec.getContextAID() != null) { + selectFileAID(pinSpec.getContextAID()); + } + + int retries = verifyPIN(pinSpec.getKID()); + do { + char[] newPin = pinProvider.providePIN(pinSpec, retries); + char[] oldPin = pinProvider.provideOldPIN(pinSpec, retries); + retries = changePIN(pinSpec.getKID(), oldPin, newPin); + } while (retries > 0); + //return on -1, 0 never reached: verifyPIN throws LockedEx + } catch (CardException ex) { + log.error("Failed to change " + pinSpec.getLocalizedName() + + ": " + ex.getMessage()); + throw new SignatureCardException(ex.getMessage(), ex); + } finally { + try { + getCard().endExclusive(); + } catch (CardException ex) { + log.trace("failed to end exclusive card access: " + ex.getMessage()); + } } } + + @Override + public void unblockPIN(PINSpec pinSpec, PINProvider pinProvider) + throws CancelledException, SignatureCardException, InterruptedException { + throw new SignatureCardException("Unblock not supported yet"); + } + + ///////////////////////////////////////////////////////////////////////////// + // IFD related code + ///////////////////////////////////////////////////////////////////////////// + + /** + * TODO implement VERIFY_PIN_START/FINISH (feature 0x01/0x02) + * @return + */ + @Override + public boolean ifdSupportsFeature(byte feature) { + if (ifdCtrlCmds != null) { + return ifdCtrlCmds.containsKey(feature); + } + return false; + } + + protected Map<Byte, Long> queryIFDFeatures() { + + if (card_ == null) { + throw new NullPointerException("Need connected smart card to query IFD features"); + } + + Map<Byte, Long> ifdFeatures = new HashMap<Byte, Long>(); + + try { + if (log.isTraceEnabled()) { + log.trace("GET_FEATURE_REQUEST CtrlCode " + Integer.toHexString(getCtrlCode(GET_FEATURE_REQUEST))); + } + byte[] resp = card_.transmitControlCommand(getCtrlCode(GET_FEATURE_REQUEST), new byte[]{}); + + if (log.isTraceEnabled()) { + log.trace("GET_FEATURE_REQUEST Response " + SMCCHelper.toString(resp)); + } + + for (int i = 0; i + 5 < resp.length; i += 6) { + Byte feature = new Byte(resp[i]); + Long ctrlCode = new Long( + ((0xFF & resp[i + 2]) << 24) | + ((0xFF & resp[i + 3]) << 16) | + ((0xFF & resp[i + 4]) << 8) | + (0xFF & resp[i + 5])); + if (log.isInfoEnabled()) { + log.info("IFD supports feature " + Integer.toHexString(feature.byteValue()) + + ": " + Long.toHexString(ctrlCode.longValue())); + } + ifdFeatures.put(feature, ctrlCode); + } + + } catch (CardException ex) { + log.debug("Failed to query IFD features: " + ex.getMessage()); + log.trace(ex); + log.info("IFD does not support PINPad"); + return null; + } + return ifdFeatures; + } + + + protected byte ifdGetKeyPressed() throws CardException { + if (ifdSupportsFeature(FEATURE_VERIFY_PIN_DIRECT)) { + + Long controlCode = (Long) ifdCtrlCmds.get(new Byte((byte) 0x05)); + + byte key = 0x00; + while (key == 0x00) { + + byte[] resp = card_.transmitControlCommand(controlCode.intValue(), new byte[] {}); + + if (resp != null && resp.length > 0) { + key = resp[0]; + } + } + + System.out.println("Key: " + key); + + } + + return 0x00; + } + + protected byte[] ifdVerifyPINFinish() throws CardException { + if (ifdSupportsFeature(FEATURE_VERIFY_PIN_DIRECT)) { + + Long controlCode = (Long) ifdCtrlCmds.get(new Byte((byte) 0x02)); + + byte[] resp = card_.transmitControlCommand(controlCode.intValue(), new byte[] {}); + + System.out.println("CommandResp: " + toString(resp)); + + return resp; + + } + + return null; + } + + + /** + * assumes ifdSupportsVerifyPIN() == true + * @param pinVerifyStructure + * @return + * @throws javax.smartcardio.CardException + */ +// protected byte[] ifdVerifyPIN(byte[] pinVerifyStructure) throws CardException { +// +//// Long ctrlCode = (Long) ifdFeatures.get(FEATURE_IFD_PIN_PROPERTIES); +//// if (ctrlCode != null) { +//// if (log.isTraceEnabled()) { +//// log.trace("PIN_PROPERTIES CtrlCode " + Integer.toHexString(ctrlCode.intValue())); +//// } +//// byte[] resp = card_.transmitControlCommand(ctrlCode.intValue(), new byte[] {}); +//// +//// if (log.isTraceEnabled()) { +//// log.trace("PIN_PROPERTIES Response " + SMCCHelper.toString(resp)); +//// } +//// } +// +// +// Long ctrlCode = (Long) ifdFeatures.get(FEATURE_VERIFY_PIN_DIRECT); +// if (ctrlCode == null) { +// throw new NullPointerException("no CtrlCode for FEATURE_VERIFY_PIN_DIRECT"); +// } +// +// if (log.isTraceEnabled()) { +// log.trace("VERIFY_PIN_DIRECT CtrlCode " + Integer.toHexString(ctrlCode.intValue()) + +// ", PIN_VERIFY_STRUCTURE " + SMCCHelper.toString(pinVerifyStructure)); +// } +// byte[] resp = card_.transmitControlCommand(ctrlCode.intValue(), pinVerifyStructure); +// +// if (log.isTraceEnabled()) { +// log.trace("VERIFY_PIN_DIRECT Response " + SMCCHelper.toString(resp)); +// } +// return resp; +// } + +// protected Long getControlCode(Byte feature) { +// if (ifdFeatures != null) { +// return ifdFeatures.get(feature); +// } +// return null; +// } + + protected byte[] transmitControlCommand(Long ctrlCode, byte[] ctrlCommand) + throws CardException { +// Long ctrlCode = (Long) ifdFeatures.get(feature); + if (ctrlCode == null) { + throw new NullPointerException("ControlCode " + + Integer.toHexString(ctrlCode.intValue()) + " not supported"); + } + if (log.isTraceEnabled()) { + log.trace("CtrlCommand (" + Integer.toHexString(ctrlCode.intValue()) + + ") " + SMCCHelper.toString(ctrlCommand)); + } + byte[] resp = card_.transmitControlCommand(ctrlCode.intValue(), ctrlCommand); + + if (log.isTraceEnabled()) { + log.trace("CtrlCommand Response " + SMCCHelper.toString(resp)); + } + return resp; + } + } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/ChangePINProvider.java b/smcc/src/main/java/at/gv/egiz/smcc/ChangePINProvider.java new file mode 100644 index 00000000..d0622aa4 --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/ChangePINProvider.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; + +import at.gv.egiz.smcc.*; + +/** + * + * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at> + */ +public interface ChangePINProvider extends PINProvider { + + /** + * + * @param spec + * @param retries + * @return null if no old value for this pin + * @throws at.gv.egiz.smcc.CancelledException if cancelled by user + * @throws java.lang.InterruptedException + */ + public char[] provideOldPIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException; + +} diff --git a/smcc/src/main/java/at/gv/egiz/smcc/PINProvider.java b/smcc/src/main/java/at/gv/egiz/smcc/PINProvider.java index e0104618..8fa80dcb 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/PINProvider.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/PINProvider.java @@ -28,8 +28,30 @@ // package at.gv.egiz.smcc; +/** + * The number of retries is not fixed and there is no way (?) to obtain this value. + * A PINProvider should therefore maintain an internal retry counter or flag + * to decide whether or not to warn the user (num retries passed in providePIN). + * + * Therefore PINProvider objects should not be reused. + * + * (ACOS: reload counter: between 0 and 15, where 15 meens deactivated) + * + * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at> + */ public interface PINProvider { - - public String providePIN(PINSpec spec, int retries) throws InterruptedException; + + /** + * + * @param spec + * @param retries num of remaining retries or -1 if unknown + * (a positive value does <em>not</em> necessarily signify that there was + * already an unsuccessful PIN verification) + * @return pin != null + * @throws at.gv.egiz.smcc.CancelledException + * @throws java.lang.InterruptedException + */ + public char[] providePIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException; } 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 - * <p> - * If <code>pin</code> is <code>null</code> only the PIN status is checked and - * returned. - * </p> - * - * @param pin - * the PIN (may be <code>null</code>) - * @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"; + } } 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 d7763be0..293b9c71 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java @@ -77,11 +77,11 @@ public class SWCard implements SignatureCard { private KeyStore certifiedKeyStore; - private String certifiedKeyStorePassword; + private char[] certifiedKeyStorePassword; private KeyStore secureKeyStore; - private String secureKeyStorePassword; + private char[] secureKeyStorePassword; private Certificate certifiedCertificate; @@ -195,7 +195,7 @@ public class SWCard implements SignatureCard { } - private String loadKeyStorePassword(String passwordFileName) throws SignatureCardException { + private char[] loadKeyStorePassword(String passwordFileName) throws SignatureCardException { String fileName = getFileName(passwordFileName); FileInputStream keyStorePasswordFile; @@ -212,7 +212,7 @@ public class SWCard implements SignatureCard { for (int l; (l = reader.read(b)) != -1;) { sb.append(b, 0, l); } - return sb.toString(); + return sb.toString().toCharArray(); } catch (IOException e) { throw new SignatureCardException("Failed to read file '" + passwordFileName + "'."); } @@ -237,7 +237,7 @@ public class SWCard implements SignatureCard { } - private String getPassword(KeyboxName keyboxName) throws SignatureCardException { + private char[] getPassword(KeyboxName keyboxName) throws SignatureCardException { if (keyboxName == KeyboxName.CERITIFIED_KEYPAIR) { if (certifiedKeyStorePassword == null) { @@ -311,7 +311,7 @@ public class SWCard implements SignatureCard { public byte[] createSignature(byte[] hash, KeyboxName keyboxName, PINProvider provider) throws SignatureCardException, InterruptedException { // KeyStore password - String password = getPassword(keyboxName); + char[] password = getPassword(keyboxName); if (password == null) { @@ -325,7 +325,7 @@ public class SWCard implements SignatureCard { } - KeyStore keyStore = getKeyStore(keyboxName, password.toCharArray()); + KeyStore keyStore = getKeyStore(keyboxName, password); PrivateKey privateKey = null; @@ -338,7 +338,7 @@ public class SWCard implements SignatureCard { Key key = null; while (key == null) { try { - key = keyStore.getKey(alias, password.toCharArray()); + key = keyStore.getKey(alias, password); } catch (UnrecoverableKeyException e) { log.info("Failed to get Key from KeyStore. Wrong password?", e); } @@ -399,15 +399,27 @@ public class SWCard implements SignatureCard { } @Override - public int verifyPIN(PINSpec pinSpec, String pin) throws LockedException, NotActivatedException, SignatureCardException { - return -1; + public void verifyPIN(PINSpec pinSpec, PINProvider pinProvider) + throws LockedException, NotActivatedException, SignatureCardException { } @Override - public void changePIN(PINSpec pinSpec, String oldPIN, String newPIN) throws LockedException, VerificationFailedException, NotActivatedException, SignatureCardException { + public void activatePIN(PINSpec pinSpec, PINProvider pinProvider) throws SignatureCardException { + throw new UnsupportedOperationException("Not supported yet."); } @Override - public void activatePIN(PINSpec pinSpec, String pin) throws SignatureCardException { + public void unblockPIN(PINSpec pinSpec, PINProvider pukProvider) throws CancelledException, SignatureCardException, InterruptedException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void changePIN(PINSpec pinSpec, ChangePINProvider pinProvider) throws LockedException, NotActivatedException, CancelledException, SignatureCardException, InterruptedException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean ifdSupportsFeature(byte feature) { + return false; } } 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 3c2273b9..2097e6d3 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java @@ -36,6 +36,14 @@ import javax.smartcardio.CardTerminal; public interface SignatureCard { + /** + * IFD FEATURES + */ + static final Byte FEATURE_VERIFY_PIN_DIRECT = new Byte((byte) 0x06); + static final Byte FEATURE_MODIFY_PIN_DIRECT = new Byte((byte) 0x07); + static final Byte FEATURE_MCT_READER_DIRECT = new Byte((byte) 0x08); + static final Byte FEATURE_IFD_PIN_PROPERTIES = new Byte((byte) 0x0a); + public static class KeyboxName { public static KeyboxName SECURE_SIGNATURE_KEYPAIR = new KeyboxName( @@ -123,29 +131,29 @@ public interface SignatureCard { */ public List<PINSpec> getPINSpecs(); - /** - * - * @param pinSpec descriptor which pin to verify - * @param pin may be null to test the PIN status - * @return the number of remaining retries or -1 - * @throws at.gv.egiz.smcc.LockedException - * @throws at.gv.egiz.smcc.NotActivatedException - * @throws at.gv.egiz.smcc.SignatureCardException - */ - public int verifyPIN(PINSpec pinSpec, String pin) - throws LockedException, NotActivatedException, SignatureCardException; + public void verifyPIN(PINSpec pinSpec, PINProvider pinProvider) + throws LockedException, NotActivatedException, CancelledException, SignatureCardException, InterruptedException; - public void changePIN(PINSpec pinSpec, String oldPIN, String newPIN) - throws LockedException, VerificationFailedException, NotActivatedException, SignatureCardException; + public void changePIN(PINSpec pinSpec, ChangePINProvider pinProvider) + throws LockedException, NotActivatedException, CancelledException, SignatureCardException, InterruptedException; - public void activatePIN(PINSpec pinSpec, String pin) - throws SignatureCardException; + public void activatePIN(PINSpec pinSpec, PINProvider pinProvider) + throws CancelledException, SignatureCardException, InterruptedException; + + public void unblockPIN(PINSpec pinSpec, PINProvider pukProvider) + throws CancelledException, SignatureCardException, InterruptedException; + + /** + * TODO + * @return + */ + public boolean ifdSupportsFeature(byte feature); /** * Sets the local for evtl. required callbacks (e.g. PINSpec) * @param locale must not be null; */ public void setLocale(Locale locale); - - + + } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java index ab66e9a1..5146c275 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java @@ -196,7 +196,7 @@ public class SignatureCardFactory { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }, "at.gv.egiz.smcc.ACOSCard")); - + } /** diff --git a/smcc/src/main/java/at/gv/egiz/smcc/TimeoutException.java b/smcc/src/main/java/at/gv/egiz/smcc/TimeoutException.java new file mode 100644 index 00000000..d14a4c15 --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/TimeoutException.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; + +public class TimeoutException extends SignatureCardException { + + private static final long serialVersionUID = 1L; + + public TimeoutException() { + super(); + } + + public TimeoutException(String message, Throwable cause) { + super(message, cause); + } + + public TimeoutException(String message) { + super(message); + } + + public TimeoutException(Throwable cause) { + super(cause); + } + +} diff --git a/smcc/src/test/resources/log4j.properties b/smcc/src/test/resources/log4j.properties index 94662fd2..053eac17 100644 --- a/smcc/src/test/resources/log4j.properties +++ b/smcc/src/test/resources/log4j.properties @@ -1,5 +1,5 @@ # loglever DEBUG, appender STDOUT -log4j.rootLogger=DEBUG, STDOUT +log4j.rootLogger=TRACE, STDOUT #log4j.logger.at.gv.egiz.slbinding.RedirectEventFilter=DEBUG, STDOUT # STDOUT appender diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractBKUWorker.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractBKUWorker.java index 23b71690..14b36e28 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractBKUWorker.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractBKUWorker.java @@ -136,7 +136,9 @@ public abstract class AbstractBKUWorker extends AbstractSMCCSTAL implements Acti if (oldValue != SMCCHelper.CARD_NOT_SUPPORTED) { actionCommandList.clear(); actionCommandList.add("cancel"); - gui.showCardNotSupportedDialog(this, "cancel"); + gui.showMessageDialog(BKUGUIFacade.TITLE_CARD_NOT_SUPPORTED, + BKUGUIFacade.MESSAGE_CARD_NOT_SUPPORTED, null, + BKUGUIFacade.BUTTON_CANCEL, this, "cancel"); oldValue = SMCCHelper.CARD_NOT_SUPPORTED; } break; @@ -144,7 +146,9 @@ public abstract class AbstractBKUWorker extends AbstractSMCCSTAL implements Acti if (oldValue != SMCCHelper.NO_CARD) { actionCommandList.clear(); actionCommandList.add("cancel"); - gui.showInsertCardDialog(this, "cancel"); + gui.showMessageDialog(BKUGUIFacade.TITLE_INSERTCARD, + BKUGUIFacade.MESSAGE_INSERTCARD, null, + BKUGUIFacade.BUTTON_CANCEL, this, "cancel"); oldValue = SMCCHelper.NO_CARD; } break; diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractPINProvider.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractPINProvider.java new file mode 100644 index 00000000..e32f08d4 --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractPINProvider.java @@ -0,0 +1,67 @@ +/* + * 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.smcc.PINProvider; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * + * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at> + */ +public abstract class AbstractPINProvider implements PINProvider, ActionListener { + + protected static final Log log = LogFactory.getLog(AbstractPINProvider.class); + + protected boolean retry = false; + + protected String action; + + private boolean actionPerformed; + +// protected void waitForAction() throws InterruptedException { +// super.wait(); +// } + + protected synchronized void waitForAction() throws InterruptedException { + try { + while (!actionPerformed) { + this.wait(); + } + } catch (InterruptedException e) { + log.error("interrupt in waitForAction"); + throw e; + } + actionPerformed = false; + } + + private synchronized void actionPerformed() { + actionPerformed = true; + notify();//All(); + } + + @Override + public void actionPerformed(ActionEvent e) { + log.debug("command " + e.getActionCommand()); + action = e.getActionCommand(); + actionPerformed(); + } +} diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java index 1cf81e05..71f35181 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java @@ -121,6 +121,12 @@ public abstract class AbstractSMCCSTAL implements STAL { return new ErrorResponse(6000); } + /** + * + * @param requestList + * @return + * @throws RuntimeException with cause InterruptedException if interrupted + */ @Override public List<STALResponse> handleRequest(List<? extends STALRequest> requestList) { log.debug("Got request list containing " + requestList.size() 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 5a54e97f..94444922 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 @@ -33,23 +33,26 @@ import at.gv.egiz.stal.InfoboxReadResponse; import at.gv.egiz.stal.STALRequest; import at.gv.egiz.stal.STALResponse; -public class InfoBoxReadRequestHandler extends AbstractRequestHandler implements - PINProvider { +public class InfoBoxReadRequestHandler extends AbstractRequestHandler { private static Log log = LogFactory.getLog(InfoBoxReadRequestHandler.class); - private int retryCounter = 0; + 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(), this, - infoBox.getDomainIdentifier()); + byte[] resp = card.getInfobox(infoBox.getInfoboxIdentifier(), + pinProviderFactory.getCardPINProvider(), + infoBox.getDomainIdentifier()); if (resp == null) { log.info("Got null as result->user cancelled"); return new ErrorResponse(6001); @@ -94,8 +97,9 @@ public class InfoBoxReadRequestHandler extends AbstractRequestHandler implements newSTALMessage("Message.RequestCaption", "Message.InfoboxReadRequest"); log.warn("Unknown infobox identifier: " + infoBox.getInfoboxIdentifier() + " trying generic request"); - byte[] resp = card.getInfobox(infoBox.getInfoboxIdentifier(), this, - infoBox.getDomainIdentifier()); + byte[] resp = card.getInfobox(infoBox.getInfoboxIdentifier(), + pinProviderFactory.getCardPINProvider(), + infoBox.getDomainIdentifier()); if (resp == null) { return new ErrorResponse(6001); } @@ -110,13 +114,15 @@ public class InfoBoxReadRequestHandler extends AbstractRequestHandler implements log.info("Citizen card not activated.", e); gui.showErrorDialog(BKUGUIFacade.ERR_CARD_NOTACTIVATED, null, this, null); waitForAction(); - gui.showWaitDialog(null); + gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, + BKUGUIFacade.MESSAGE_WAIT); return new ErrorResponse(6001); } catch (LockedException e) { log.info("Citizen card locked.", e); gui.showErrorDialog(BKUGUIFacade.ERR_CARD_LOCKED, null, this, null); waitForAction(); - gui.showWaitDialog(null); + gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, + BKUGUIFacade.MESSAGE_WAIT); return new ErrorResponse(6001); } catch (CancelledException cx) { log.debug("User cancelled request", cx); @@ -135,20 +141,4 @@ public class InfoBoxReadRequestHandler extends AbstractRequestHandler implements public boolean requireCard() { return true; } - - @Override - public String providePIN(PINSpec spec, int retries) throws InterruptedException { - if (retryCounter++ > 0) { - log.info("PIN wrong retrying ..."); - gui.showCardPINRetryDialog(spec, retries, this, "ok", this, "cancel"); - } else { - gui.showCardPINDialog(spec, this, "ok", this, "cancel"); - } - waitForAction(); - gui.showWaitDialog(null); - if (actionCommand.equals("cancel")) { - return null; - } - return new String(gui.getPin()); - } } 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 new file mode 100644 index 00000000..670b71dc --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/PINProviderFactory.java @@ -0,0 +1,47 @@ +/* + * 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.PINProvider; +import at.gv.egiz.smcc.SignatureCard; +import at.gv.egiz.stal.signedinfo.SignedInfoType; + +/** + * + * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at> + */ +public abstract class PINProviderFactory { + + BKUGUIFacade gui; + + public static PINProviderFactory getInstance(SignatureCard forCard, + BKUGUIFacade gui) { + if (forCard.ifdSupportsFeature(SignatureCard.FEATURE_VERIFY_PIN_DIRECT)) { + return new PinpadPINProviderFactory(gui); + } else { + return new SoftwarePINProviderFactory(gui); + } + } + + public abstract PINProvider getSignaturePINProvider(SecureViewer viewer, + SignedInfoType signedInfo); + + public abstract PINProvider getCardPINProvider(); + +} 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 new file mode 100644 index 00000000..55321b72 --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/PinpadPINProviderFactory.java @@ -0,0 +1,155 @@ +/* + * 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.HashDataInput; +import at.gv.egiz.stal.signedinfo.SignedInfoType; +import java.util.List; + +/** + * + * @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 SignedInfoType signedInfo; + protected List<HashDataInput> hashDataInputs; + + private SignaturePinProvider(SecureViewer viewer, + SignedInfoType signedInfo) { + this.viewer = viewer; + this.signedInfo = signedInfo; + } + + @Override + public char[] providePIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException { + + showPinpadPINDialog(retries, spec); + retry = true; + return null; + +// do { +// waitForAction(); +// gui.showWaitDialog(null); +// +// if ("hashData".equals(action)) { +// // show pin dialog in background +// gui.showSignaturePINDialog(spec, (retry) ? retries : -1, +// this, "sign", +// this, "cancel", +// this, "hashData"); +// +// viewer.displayDataToBeSigned(signedInfo.getReference()); +// +// } else if ("sign".equals(action)) { +// retry = true; +// return gui.getPin(); +// } else if ("hashDataDone".equals(action)) { +// gui.showSignaturePINDialog(spec, (retry) ? retries : -1, +// this, "sign", +// this, "cancel", +// this, "hashData"); +// } else if ("cancel".equals(action) || +// "error".equals(action)) { +// throw new CancelledException(spec.getLocalizedName() + +// " entry cancelled"); +// } +// } while (true); + } + + 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_SIGN; + 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); + } + } + + 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/SecureViewer.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SecureViewer.java new file mode 100644 index 00000000..c395679a --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SecureViewer.java @@ -0,0 +1,44 @@ +/* + * 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.stal.signedinfo.ReferenceType; +import java.security.DigestException; +import java.util.List; + +/** + * + * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at> + */ +public interface SecureViewer { + + /** + * Displays the hashdata inputs for all provided dsig:SignedReferences. + * Implementations may verify the digest value if necessary. + * (LocalSignRequestHandler operates on DataObjectHashDataInput, + * other SignRequestHandlers should cache the HashDataInputs obtained by webservice calls, + * or simply forward to a HashDataInputServlet.) + * @param signedReferences The caller may select a subset of the references in SignedInfo to be displayed. + * @throws java.security.DigestException if digest values are verified and do not correspond + * (or any other digest computation error occurs) + * @throws java.lang.Exception + */ + void displayDataToBeSigned(List<ReferenceType> signedReferences) + throws DigestException, Exception; + +} 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 d041a8cb..ac510f38 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 @@ -17,7 +17,6 @@ package at.gv.egiz.bku.smccstal; import at.gv.egiz.bku.gui.BKUGUIFacade; -import java.awt.event.ActionEvent; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.security.MessageDigest; @@ -35,12 +34,11 @@ import at.gv.egiz.smcc.CancelledException; import at.gv.egiz.smcc.LockedException; import at.gv.egiz.smcc.NotActivatedException; import at.gv.egiz.smcc.PINProvider; -import at.gv.egiz.smcc.PINSpec; import at.gv.egiz.smcc.SignatureCard; import at.gv.egiz.smcc.SignatureCardException; import at.gv.egiz.smcc.SignatureCard.KeyboxName; +import at.gv.egiz.smcc.TimeoutException; import at.gv.egiz.stal.ErrorResponse; -import at.gv.egiz.stal.HashDataInput; import at.gv.egiz.stal.STALRequest; import at.gv.egiz.stal.STALResponse; import at.gv.egiz.stal.SignRequest; @@ -48,13 +46,12 @@ import at.gv.egiz.stal.SignResponse; import at.gv.egiz.stal.signedinfo.ObjectFactory; import at.gv.egiz.stal.signedinfo.SignedInfoType; import at.gv.egiz.stal.util.JCEAlgorithmNames; -import java.security.DigestException; -import java.util.List; -public abstract class SignRequestHandler extends AbstractRequestHandler implements HashDataInputDisplay { +public abstract class SignRequestHandler extends AbstractRequestHandler implements SecureViewer { private static Log log = LogFactory.getLog(SignRequestHandler.class); private static JAXBContext jaxbContext; + private PINProviderFactory pinProviderFactory; static { try { @@ -84,7 +81,14 @@ public abstract class SignRequestHandler extends AbstractRequestHandler implemen MessageDigest md = MessageDigest.getInstance(jceName); md.update(signReq.getSignedInfo()); KeyboxName kb = SignatureCard.KeyboxName.getKeyboxName(signReq.getKeyIdentifier()); - byte[] resp = card.createSignature(md.digest(), kb, new STALPinProvider(si.getValue())); + + if (pinProviderFactory == null) { + pinProviderFactory = PINProviderFactory.getInstance(card, gui); + } + PINProvider pinProvider = pinProviderFactory. + getSignaturePINProvider(this, si.getValue()); + + byte[] resp = card.createSignature(md.digest(), kb, pinProvider); if (resp == null) { return new ErrorResponse(6001); } @@ -95,17 +99,28 @@ public abstract class SignRequestHandler extends AbstractRequestHandler implemen log.info("Citizen card not activated.", e); gui.showErrorDialog(BKUGUIFacade.ERR_CARD_NOTACTIVATED, null, this, null); waitForAction(); - gui.showWaitDialog(null); + gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, + BKUGUIFacade.MESSAGE_WAIT); return new ErrorResponse(6001); } catch (LockedException e) { log.info("Citizen card locked.", e); gui.showErrorDialog(BKUGUIFacade.ERR_CARD_LOCKED, null, this, null); waitForAction(); - gui.showWaitDialog(null); + gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, + BKUGUIFacade.MESSAGE_WAIT); return new ErrorResponse(6001); } catch (CancelledException cx) { log.debug("User cancelled request"); return new ErrorResponse(6001); + } catch (TimeoutException ex) { + log.error("Timeout during pin entry"); + gui.showMessageDialog(BKUGUIFacade.TITLE_ENTRY_TIMEOUT, + BKUGUIFacade.ERR_PIN_TIMEOUT, null, + BKUGUIFacade.BUTTON_CANCEL, this, null); + waitForAction(); + gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, + BKUGUIFacade.MESSAGE_WAIT); + return new ErrorResponse(6001); } catch (SignatureCardException e) { log.error("Error while creating signature: " + e); return new ErrorResponse(4000); @@ -127,64 +142,64 @@ public abstract class SignRequestHandler extends AbstractRequestHandler implemen return true; } - class STALPinProvider implements PINProvider { - - protected SignedInfoType signedInfo; - protected List<HashDataInput> hashDataInputs; - private int retryCounter = 0; - - public STALPinProvider(SignedInfoType signedInfo) { - this.signedInfo = signedInfo; - } - - private void showSignaturePINDialog(PINSpec spec, int retries) { - if (retryCounter > 0) { - gui.showSignaturePINRetryDialog(spec, retries, SignRequestHandler.this, "sign", SignRequestHandler.this, - "cancel", SignRequestHandler.this, "hashData"); - } else { - gui.showSignaturePINDialog(spec, SignRequestHandler.this, "sign", SignRequestHandler.this, "cancel", SignRequestHandler.this, - "hashData"); - } - } - - @Override - public String providePIN(PINSpec spec, int retries) throws InterruptedException { - - showSignaturePINDialog(spec, retries); - - do { - waitForAction(); - gui.showWaitDialog(null); - if (actionCommand.equals("cancel")) { - return null; - } else if (actionCommand.equals("hashData")) { - - showSignaturePINDialog(spec, retries); - - try { - displayHashDataInputs(signedInfo.getReference()); - } catch (DigestException ex) { - log.error("Bad digest value: " + ex.getMessage()); - gui.showErrorDialog(BKUGUIFacade.ERR_INVALID_HASH, new Object[] {ex.getMessage()}, SignRequestHandler.this, "error"); - } catch (Exception ex) { - log.error("Could not display hashdata inputs: " + ex.getMessage()); - gui.showErrorDialog(BKUGUIFacade.ERR_DISPLAY_HASHDATA, new Object[] {ex.getMessage()}, SignRequestHandler.this, "error"); - } - - } else if (actionCommand.equals("sign")) { - retryCounter++; - return new String(gui.getPin()); - } else if (actionCommand.equals("hashDataDone")) { - showSignaturePINDialog(spec, retries); - } else if (actionCommand.equals("error")) { - return null; - } - } while (true); - } - +// class SoftwarePinProvider implements PINProvider { +// +// protected SignedInfoType signedInfo; +// protected List<HashDataInput> hashDataInputs; +// private boolean retry = false; +// +// public SoftwarePinProvider(SignedInfoType signedInfo) { +// this.signedInfo = signedInfo; +// } +// +// private void showSignaturePINDialog(PINSpec spec, int retries) { +// if (retry) { +// gui.showSignaturePINRetryDialog(spec, retries, SignRequestHandler.this, "sign", SignRequestHandler.this, +// "cancel", SignRequestHandler.this, "hashData"); +// } else { +// gui.showSignaturePINDialog(spec, SignRequestHandler.this, "sign", SignRequestHandler.this, "cancel", SignRequestHandler.this, +// "hashData"); +// } +// } +// // @Override -// public void actionPerformed(ActionEvent e) { -// throw new UnsupportedOperationException("Not supported yet."); +// public char[] providePIN(PINSpec spec, int retries) +// throws CancelledException, InterruptedException { +// showSignaturePINDialog(spec, retries); +// +// do { +// waitForAction(); +// gui.showWaitDialog(null); +// if (actionCommand.equals("hashData")) { +// +// showSignaturePINDialog(spec, retries); +// +// try { +// displayHashDataInputs(signedInfo.getReference()); +// +// } catch (DigestException ex) { +// log.error("Bad digest value: " + ex.getMessage()); +// gui.showErrorDialog(BKUGUIFacade.ERR_INVALID_HASH, +// new Object[] {ex.getMessage()}, +// SignRequestHandler.this, "error"); +// } catch (Exception ex) { +// log.error("Could not display hashdata inputs: " + +// ex.getMessage()); +// gui.showErrorDialog(BKUGUIFacade.ERR_DISPLAY_HASHDATA, +// new Object[] {ex.getMessage()}, +// SignRequestHandler.this, "error"); +// } +// } else if (actionCommand.equals("sign")) { +// retry = true; +// return gui.getPin(); +// } else if (actionCommand.equals("hashDataDone")) { +// showSignaturePINDialog(spec, retries); +// } else if (actionCommand.equals("cancel") || +// actionCommand.equals("error")) { +// throw new CancelledException(spec.getLocalizedName() + +// " entry cancelled"); +// } +// } while (true); // } - } +// } } 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 new file mode 100644 index 00000000..54a34280 --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SoftwarePINProviderFactory.java @@ -0,0 +1,140 @@ +/* + * 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; + protected List<HashDataInput> hashDataInputs; + + 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, "hashData"); + + do { + waitForAction(); + gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, + BKUGUIFacade.MESSAGE_WAIT); + + if ("hashData".equals(action)) { + // show pin dialog in background + gui.showSignaturePINDialog(spec, (retry) ? retries : -1, + this, "sign", + this, "cancel", + this, "hashData"); + + try { + viewer.displayDataToBeSigned(signedInfo.getReference()); + } 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)) { + retry = true; + return gui.getPin(); + } else if ("hashDataDone".equals(action)) { + gui.showSignaturePINDialog(spec, (retry) ? retries : -1, + this, "sign", + this, "cancel", + this, "hashData"); + } else if ("cancel".equals(action) || + "error".equals(action)) { + throw new CancelledException(spec.getLocalizedName() + + " entry cancelled"); + } + } 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(); + } + } +} diff --git a/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java b/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java index b2a91784..51dfe0da 100644 --- a/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java +++ b/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java @@ -93,16 +93,24 @@ public class AbstractSMCCSTALTest extends AbstractSMCCSTAL implements }
@Override
- public int verifyPIN(PINSpec pinSpec, String pin) throws LockedException, NotActivatedException, SignatureCardException {
- return -1;
+ public void verifyPIN(PINSpec pinSpec, PINProvider pinProvider) {
}
@Override
- public void changePIN(PINSpec pinSpec, String oldPIN, String newPIN) throws LockedException, VerificationFailedException, NotActivatedException, SignatureCardException {
+ public void changePIN(PINSpec pinSpec, ChangePINProvider pinProvider) {
}
@Override
- public void activatePIN(PINSpec pinSpec, String pin) throws SignatureCardException {
+ public void activatePIN(PINSpec pinSpec, PINProvider pinProvider) {
+ }
+
+ @Override
+ public void unblockPIN(PINSpec pinSpec, PINProvider pukProvider) {
+ }
+
+ @Override
+ public boolean ifdSupportsFeature(byte feature) {
+ return false;
}
};
|