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.pngBinary files differ index 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.pngBinary files differ index 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.pngBinary files differ index 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.pngBinary files differ index 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;
        }
     };
 | 
