diff options
79 files changed, 3880 insertions, 1964 deletions
| 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 91c91dcb..1e23c64c 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 @@ -16,7 +16,7 @@   */  package at.gv.egiz.bku.gui; -import at.gv.egiz.stal.HashDataInput; +  import at.gv.egiz.stal.HashDataInput;  import at.gv.egiz.smcc.PINSpec;  import java.awt.Color;  import java.awt.event.ActionListener; @@ -53,14 +53,15 @@ public interface BKUGUIFacade {    public static final String TITLE_WELCOME = "title.welcome";    public static final String TITLE_INSERTCARD = "title.insertcard";    public static final String TITLE_CARD_NOT_SUPPORTED = "title.cardnotsupported"; -  public static final String TITLE_CARDPIN = "title.cardpin"; +  public static final String TITLE_VERIFY_PIN = "title.verify.pin";    public static final String TITLE_SIGN = "title.sign"; +  public static final String TITLE_VERIFY_PINPAD = "title.verify.pinpad";    public static final String TITLE_ERROR = "title.error";    public static final String TITLE_WARNING = "title.warning";    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"; +  public static final String TITLE_SIGNATURE_DATA = "title.signature.data";    public static final String WINDOWTITLE_SAVE = "windowtitle.save";    public static final String WINDOWTITLE_ERROR = "windowtitle.error";    public static final String WINDOWTITLE_SAVEDIR = "windowtitle.savedir"; @@ -75,6 +76,7 @@ public interface BKUGUIFacade {    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_ENTERPIN_PINPAD_DIRECT = "enterpin.pinpad.direct";    public static final String MESSAGE_HASHDATALINK = "hashdatalink";    public static final String MESSAGE_HASHDATALINK_TINY = "hashdatalink.tiny";    public static final String MESSAGE_HASHDATALINK_FOCUS = "hashdatalink.focus"; @@ -96,8 +98,9 @@ public interface BKUGUIFacade {    public static final String HELP_WAIT = "help.wait";    public static final String HELP_CARDNOTSUPPORTED = "help.cardnotsupported";    public static final String HELP_INSERTCARD = "help.insertcard"; -  public static final String HELP_CARDPIN = "help.cardpin"; +  public static final String HELP_VERIFY_PIN = "help.cardpin";    public static final String HELP_SIGNPIN = "help.signpin"; +  public static final String HELP_PINPAD = "help.pinpad";    public static final String HELP_RETRY = "help.retry";    public static final String HELP_HASHDATA = "help.hashdata";    public static final String HELP_HASHDATALIST = "help.hashdatalist"; @@ -111,6 +114,18 @@ public interface BKUGUIFacade {    public static final String SAVE_HASHDATAINPUT_PREFIX = "save.hashdatainput.prefix";    public static final String ALT_HELP = "alt.help"; +  public void showEnterPINDirect(PINSpec spec, int retries); + +  public void showEnterPIN(PINSpec spec, int retries); + +  public void showSignatureDataDialog(PINSpec spec, ActionListener listener, String string, ActionListener aThis0, String string0, ActionListener aThis1, String string1); + +  public void correctionButtonPressed(); + +  public void allKeysCleared(); + +  public void validKeyPressed(); +    public enum Style { tiny, simple, advanced };    /** @@ -119,7 +134,7 @@ public interface BKUGUIFacade {     */    public Locale getLocale(); -  public void showCardPINDialog(PINSpec pinSpec, int numRetries, +  public void showVerifyPINDialog(PINSpec pinSpec, int numRetries,            ActionListener okListener, String okCommand,            ActionListener cancelListener, String cancelCommand); @@ -128,9 +143,6 @@ public interface BKUGUIFacade {            ActionListener cancelListener, String cancelCommand,            ActionListener viewerListener, String viewerCommand); -  public void showPinpadSignaturePINDialog(PINSpec pinSpec, int numRetries,  -          ActionListener viewerListener, String viewerCommand); -    public char[] getPin();    /** 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 baffb3fd..3fc631c3 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 @@ -93,6 +93,7 @@ public class BKUGUIImpl implements BKUGUIFacade {      protected JLabel switchFocusDummyLabel;       /** remember the pinfield to return to worker */      protected JPasswordField pinField; +    protected JPasswordField pinpadPINField;      protected int buttonSize; @@ -360,221 +361,27 @@ 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(); -//            } -//        }); -//    } - -    /** -     * 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(); -//            } -//        }); -//    } -    @Override -  public void showCardPINDialog(final PINSpec pinSpec, final int numRetries, +  public void showVerifyPINDialog(final PINSpec pinSpec, final int numRetries,            final ActionListener okListener, final String okCommand,            final ActionListener cancelListener, final String cancelCommand) { -      log.debug("scheduling card-pin dialog"); +      log.debug("scheduling verify pin dialog");        SwingUtilities.invokeLater(new Runnable() {              @Override              public void run() { -              log.debug("[" + Thread.currentThread().getName() + "] show card-pin dialog"); +              log.debug("[" + Thread.currentThread().getName() + "] show verify pin dialog");                  mainPanel.removeAll();                  buttonPanel.removeAll();                  if (renderHeaderPanel) {                    if (numRetries < 0) { -                      String cardpinTitle = getMessage(TITLE_CARDPIN); -                      titleLabel.setText(MessageFormat.format(cardpinTitle, new Object[]{pinSpec.getLocalizedName()})); +                      String verifyTitle = getMessage(TITLE_VERIFY_PIN); +                      titleLabel.setText(MessageFormat.format(verifyTitle, new Object[]{pinSpec.getLocalizedName()}));                    } else {                        titleLabel.setText(getMessage(TITLE_RETRY));                    } @@ -615,8 +422,8 @@ public class BKUGUIImpl implements BKUGUIFacade {                    } else {                      infoLabel.setText(MessageFormat.format(infoPattern, new Object[] {pinSpec.getLocalizedName()}));                    } -                  helpMouseListener.setHelpTopic(HELP_CARDPIN); -                  helpKeyListener.setHelpTopic(HELP_CARDPIN); +                  helpMouseListener.setHelpTopic(HELP_VERIFY_PIN); +                  helpKeyListener.setHelpTopic(HELP_VERIFY_PIN);                  } else {                    String retryPattern;                    if (numRetries < 2) { @@ -732,194 +539,346 @@ 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 showEnterPINDirect(PINSpec pinSpec, int retries) { +    if (retries < 0) { +      showMessageDialog(TITLE_VERIFY_PINPAD, MESSAGE_ENTERPIN_PINPAD_DIRECT, new Object[] { +                  pinSpec.getLocalizedName(), pinSpec.getLocalizedLength() }); +    } else { +      showMessageDialog(TITLE_RETRY, MESSAGE_RETRIES, new Object[]{String.valueOf(retries) }); +    } +  } -//    @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 showEnterPIN(final PINSpec pinSpec, final int retries) { +    showEnterPIN(pinSpec, retries, TITLE_VERIFY_PINPAD, MESSAGE_ENTERPIN_PINPAD, null); +  } -    @Override -    public void showPinpadSignaturePINDialog(final PINSpec pinSpec, final int numRetries, -//            final ActionListener cancelListener, final String cancelCommand, -            final ActionListener hashdataListener, final String hashdataCommand) { +  protected void showEnterPIN(final PINSpec pinSpec, final int retries, final String titleKey, final String messageKey, final Object[] messageParams) { +    log.debug("scheduling pinpad dialog"); -        log.debug("scheduling pinpad signature-pin dialog"); +    SwingUtilities.invokeLater(new Runnable() { -        SwingUtilities.invokeLater(new Runnable() { +      @Override +      public void run() { -            @Override -            public void run() { +        log.debug("[" + Thread.currentThread().getName() + "] show pinpad dialog"); -              log.debug("[" + Thread.currentThread().getName() + "] show pinpad signature-pin dialog"); +        mainPanel.removeAll(); +        buttonPanel.removeAll(); -                mainPanel.removeAll(); -                buttonPanel.removeAll(); +        if (renderHeaderPanel) { +          if (retries < 0) { +              titleLabel.setText(getMessage(titleKey)); +          } else { +              titleLabel.setText(getMessage(TITLE_RETRY)); +          } +        } -                if (renderHeaderPanel) { -                  if (numRetries < 0) { -                      titleLabel.setText(getMessage(TITLE_SIGN)); -                  } else { -                      titleLabel.setText(getMessage(TITLE_RETRY)); -                  } -                } +        final JLabel infoLabel = new JLabel(); +        if (retries < 0) { +          infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); +          infoLabel.setText(MessageFormat.format(getMessage(messageKey), messageParams)); +          helpMouseListener.setHelpTopic(HELP_PINPAD); +          helpKeyListener.setHelpTopic(HELP_PINPAD); +        } else { +          String retryPattern; +          if (retries == 1) { +            retryPattern = getMessage(MESSAGE_LAST_RETRY); +          } else { +            retryPattern = getMessage(MESSAGE_RETRIES); +          } +          infoLabel.setText(MessageFormat.format(retryPattern, new Object[]{String.valueOf(retries)})); +          infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() | java.awt.Font.BOLD)); +          infoLabel.setForeground(ERROR_COLOR); +          helpMouseListener.setHelpTopic(HELP_RETRY); +          helpKeyListener.setHelpTopic(HELP_RETRY); +        } + +        JLabel pinLabel = new JLabel(); +        pinLabel.setFont(pinLabel.getFont().deriveFont(pinLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); +        String pinName = getMessage(LABEL_PIN); +        pinLabel.setText(MessageFormat.format(pinName, new Object[]{pinSpec.getLocalizedName()})); + +        pinpadPINField = new JPasswordField(); +        pinpadPINField.setText(""); +        pinpadPINField.setEnabled(false); + +        JLabel pinsizeLabel = new JLabel(); +        pinsizeLabel.setFont(pinsizeLabel.getFont().deriveFont(pinsizeLabel.getFont().getStyle() & ~java.awt.Font.BOLD, pinsizeLabel.getFont().getSize()-2)); +        pinsizeLabel.setText(MessageFormat.format(getMessage(LABEL_PINSIZE), pinSpec.getLocalizedLength())); + +        GroupLayout mainPanelLayout = new GroupLayout(mainPanel); +        mainPanel.setLayout(mainPanelLayout); + +        GroupLayout.SequentialGroup infoHorizontal = mainPanelLayout.createSequentialGroup() +                .addComponent(infoLabel); +        GroupLayout.ParallelGroup infoVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) +                .addComponent(infoLabel); + +        if (!renderHeaderPanel) { +          infoHorizontal +                  .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) +                  .addComponent(switchFocusDummyLabel) +                  .addComponent(helpLabel) +                  ; +          infoVertical +                  .addComponent(switchFocusDummyLabel) +                  .addComponent(helpLabel) +                  ; +        } + +        // align pinfield and pinsize to the right +        GroupLayout.Group pinHorizontal = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.TRAILING); +        GroupLayout.SequentialGroup pinVertical = mainPanelLayout.createSequentialGroup(); + +        if (pinLabelPos == PinLabelPosition.ABOVE) { +          pinHorizontal +                  .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) +                    .addComponent(pinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) +                    .addComponent(pinpadPINField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) +                  .addComponent(pinsizeLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE); +          pinVertical +                  .addComponent(pinLabel) +                  .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) +                  .addComponent(pinpadPINField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) +                  .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) +                  .addComponent(pinsizeLabel); +        } else { // PinLabelPosition.LEFT +          pinHorizontal +                  .addGroup(mainPanelLayout.createSequentialGroup() +                    .addComponent(pinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) +                    .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) +                    .addComponent(pinpadPINField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) +                  .addComponent(pinsizeLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE); +          pinVertical +                  .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) +                    .addComponent(pinLabel) +                    .addComponent(pinpadPINField)) +                  .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) +                  .addComponent(pinsizeLabel); +        } + +        mainPanelLayout.setHorizontalGroup( +          mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) +            .addGroup(infoHorizontal) +            .addGroup(pinHorizontal)); + +        mainPanelLayout.setVerticalGroup( +          mainPanelLayout.createSequentialGroup() +            .addGroup(infoVertical) +            .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) +            .addGroup(pinVertical)); + +        contentPanel.validate(); +      } +    }); +  } + +  @Override +  public void showSignatureDataDialog(PINSpec spec, +          final ActionListener enterPINListener, final String enterPINCommand, +          final ActionListener cancelListener, final String cancelCommand, +          final ActionListener hashdataListener, final String hashdataCommand) { + +    log.debug("scheduling signature-data dialog"); + +    SwingUtilities.invokeLater(new Runnable() { + +        @Override +        public void run() { + +          log.debug("[" + Thread.currentThread().getName() + "] show signature-data dialog"); + +          mainPanel.removeAll(); +          buttonPanel.removeAll(); + +          if (renderHeaderPanel) { +            titleLabel.setText(getMessage(TITLE_SIGNATURE_DATA)); +          } + +          final JLabel infoLabel = new JLabel(); +          infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); +          if (shortText) { +            infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_TINY)); +          } else { +            infoLabel.setText(getMessage(MESSAGE_HASHDATALINK)); +          } +          infoLabel.setFocusable(true); +          infoLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); +          infoLabel.setForeground(HYPERLINK_COLOR); +          infoLabel.addMouseListener(new MouseAdapter() { + +              @Override +              public void mouseClicked(MouseEvent me) { +                  ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, hashdataCommand); +                  hashdataListener.actionPerformed(e); +              } +          }); + +          infoLabel.addKeyListener(new KeyAdapter() { + +             @Override +             public void keyPressed(KeyEvent e) { + +                 if(e.getKeyCode() == KeyEvent.VK_ENTER) { +                     ActionEvent e1 = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, hashdataCommand); +                      hashdataListener.actionPerformed(e1); +                 } +             } + +           }); + +          infoLabel.addFocusListener(new FocusAdapter() { + +              @Override +              public void focusGained(FocusEvent e) { -                final JLabel infoLabel = new JLabel(); -                if (numRetries < 0) { -                  infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() & ~java.awt.Font.BOLD));                    if (shortText) { -                    infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_TINY)); -                  } else { -                    infoLabel.setText(getMessage(MESSAGE_HASHDATALINK)); -                  } -                  infoLabel.setFocusable(true); -                  infoLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); -                  infoLabel.setForeground(HYPERLINK_COLOR); -                  infoLabel.addMouseListener(new MouseAdapter() { +                      infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_TINY_FOCUS)); +                    } else { +                      infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_FOCUS)); +                    } +              } -                      @Override -                      public void mouseClicked(MouseEvent me) { -                          ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, hashdataCommand); -                          hashdataListener.actionPerformed(e); -                      } -                  }); -                   -                  infoLabel.addKeyListener(new KeyAdapter() { -                	   -                 	 @Override -                 	 public void keyPressed(KeyEvent e) { -                 		  -                 		 if(e.getKeyCode() == KeyEvent.VK_ENTER) {                			  -                 			 ActionEvent e1 = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, hashdataCommand); -                              hashdataListener.actionPerformed(e1); -                 		 } -                 	 } -                 	   -                   });   -                   -                  infoLabel.addFocusListener(new FocusAdapter() { -                	   -                	  @Override -                	  public void focusGained(FocusEvent e) { -                		   -                          if (shortText) { -                              infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_TINY_FOCUS)); -                            } else { -                              infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_FOCUS)); -                            } -                	  } -                	   -                	  @Override -                	  public void focusLost(FocusEvent e) { -                		   -                          if (shortText) { -                              infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_TINY)); -                            } else { -                              infoLabel.setText(getMessage(MESSAGE_HASHDATALINK)); -                            } -                		   -                	  }                	   -                	   -                  });                   -                   -                  helpMouseListener.setHelpTopic(HELP_SIGNPIN); -                  helpKeyListener.setHelpTopic(HELP_SIGNPIN); -                } else { -                  String retryPattern; -                  if (numRetries < 2) { -                    retryPattern = getMessage(MESSAGE_LAST_RETRY); -                  } else { -                    retryPattern = getMessage(MESSAGE_RETRIES); -                  } -                  infoLabel.setFocusable(true); -                  infoLabel.setText(MessageFormat.format(retryPattern, new Object[]{String.valueOf(numRetries)})); -                  infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() | java.awt.Font.BOLD)); -                  infoLabel.setForeground(ERROR_COLOR); -                  helpMouseListener.setHelpTopic(HELP_RETRY); -                  helpKeyListener.setHelpTopic(HELP_RETRY); -                } +              @Override +              public void focusLost(FocusEvent e) { -                String msgPattern = getMessage(MESSAGE_ENTERPIN_PINPAD); -                String msg = MessageFormat.format(msgPattern, new Object[] { -                  pinSpec.getLocalizedName(), pinSpec.getLocalizedLength() }); +                  if (shortText) { +                      infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_TINY)); +                    } else { +                      infoLabel.setText(getMessage(MESSAGE_HASHDATALINK)); +                    } -                JLabel msgLabel = new JLabel(); -                msgLabel.setFont(msgLabel.getFont().deriveFont(msgLabel.getFont().getStyle() & ~Font.BOLD)); -                msgLabel.setText(msg); +              } -                GroupLayout mainPanelLayout = new GroupLayout(mainPanel); -                mainPanel.setLayout(mainPanelLayout); +          }); -                GroupLayout.SequentialGroup infoHorizontal = mainPanelLayout.createSequentialGroup() -                        .addComponent(infoLabel); -                GroupLayout.ParallelGroup infoVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) -                        .addComponent(infoLabel); +          helpMouseListener.setHelpTopic(HELP_SIGNPIN); +          helpKeyListener.setHelpTopic(HELP_SIGNPIN); -                if (!renderHeaderPanel) { -                  infoHorizontal -                          .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) -                          .addComponent(switchFocusDummyLabel) -                          .addComponent(helpLabel) -                          ; -                  infoVertical -                          .addComponent(switchFocusDummyLabel) -                          .addComponent(helpLabel) -                          ; -                } +          //TODO message panel -                mainPanelLayout.setHorizontalGroup( -                  mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) -                    .addGroup(infoHorizontal) -                    .addComponent(msgLabel)); +//              String msgPattern = getMessage(MESSAGE_ENTERPIN_PINPAD); +//              String msg = MessageFormat.format(msgPattern, new Object[] { +//                pinSpec.getLocalizedName(), pinSpec.getLocalizedLength() }); +// +//              JLabel msgLabel = new JLabel(); +//              msgLabel.setFont(msgLabel.getFont().deriveFont(msgLabel.getFont().getStyle() & ~Font.BOLD)); +//              msgLabel.setText(msg); -                mainPanelLayout.setVerticalGroup( -                  mainPanelLayout.createSequentialGroup() -                    .addGroup(infoVertical) +          GroupLayout mainPanelLayout = new GroupLayout(mainPanel); +          mainPanel.setLayout(mainPanelLayout); + +          GroupLayout.SequentialGroup infoHorizontal = mainPanelLayout.createSequentialGroup() +                  .addComponent(infoLabel); +          GroupLayout.ParallelGroup infoVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) +                  .addComponent(infoLabel); + +          if (!renderHeaderPanel) { +            infoHorizontal +                    .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) +                    .addComponent(switchFocusDummyLabel) +                    .addComponent(helpLabel) +                    ; +            infoVertical +                    .addComponent(switchFocusDummyLabel) +                    .addComponent(helpLabel) +                    ; +          } + +          mainPanelLayout.setHorizontalGroup( +                  infoHorizontal); +//              mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) +//                .addGroup(infoHorizontal) +//                .addComponent(msgLabel)); + +          mainPanelLayout.setVerticalGroup( +                  infoVertical); +//              mainPanelLayout.createSequentialGroup() +//                .addGroup(infoVertical) +//                .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) +//                .addComponent(msgLabel)); + + +          GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); +          buttonPanel.setLayout(buttonPanelLayout); + +          GroupLayout.SequentialGroup buttonHorizontal = buttonPanelLayout.createSequentialGroup(); +          GroupLayout.Group buttonVertical; + +          JButton enterPINButton = new JButton(); +          enterPINButton.setFont(enterPINButton.getFont().deriveFont(enterPINButton.getFont().getStyle() & ~java.awt.Font.BOLD)); +          enterPINButton.setText(getMessage(BUTTON_SIGN)); +          enterPINButton.setActionCommand(enterPINCommand); +          enterPINButton.addActionListener(enterPINListener); + +          if (renderCancelButton) { +            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 +                    .addComponent(enterPINButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)                      .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) -                    .addComponent(msgLabel)); - -                //no cancel button (cancel via pinpad) -//                if (renderCancelButton) { -//                    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); -// -//                    GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); -//                    buttonPanel.setLayout(buttonPanelLayout); -// -//                    GroupLayout.SequentialGroup buttonHorizontal = buttonPanelLayout.createSequentialGroup() -//                            .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE); -//                    GroupLayout.SequentialGroup buttonVertical = buttonPanelLayout.createSequentialGroup() -//                            .addComponent(cancelButton); -// -//                    buttonPanelLayout.setHorizontalGroup(buttonHorizontal); -//                    buttonPanelLayout.setVerticalGroup(buttonVertical); -//                } +                    .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE) +                    ; +            buttonVertical = buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) +                    .addComponent(enterPINButton) +                    .addComponent(cancelButton) +                    ; +          } else { +            buttonHorizontal +                    .addComponent(enterPINButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE) +                    ; +            buttonVertical = buttonPanelLayout.createSequentialGroup() +                    .addComponent(enterPINButton) +                    ; +          } -                contentPanel.validate(); -            } -        }); +          buttonPanelLayout.setHorizontalGroup(buttonHorizontal); +          buttonPanelLayout.setVerticalGroup(buttonVertical); + +          contentPanel.validate(); +        } +    }); +  } + +  @Override +  public void correctionButtonPressed() { +    log.debug("[" + Thread.currentThread().getName() + "] correction button pressed"); + +    if (pinpadPINField != null) { +      String maskedPIN = pinpadPINField.getText(); +      pinpadPINField.setText(maskedPIN.substring(0, maskedPIN.length() - 1)); +    } +  } + +  @Override +  public void allKeysCleared() { +    log.debug("[" + Thread.currentThread().getName() + "] all keys cleared"); + +    if (pinpadPINField != null) { +      pinpadPINField.setText(""); +    } +  } + +  @Override +  public void validKeyPressed() { +    log.debug("[" + Thread.currentThread().getName() + "] valid key pressed"); + +    if (pinpadPINField != null) { +      pinpadPINField.setText(pinpadPINField.getText() + '*');      } +  }      @Override      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"); @@ -1302,57 +1261,6 @@ 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 char[] getPin() { @@ -1395,7 +1303,7 @@ public class BKUGUIImpl implements BKUGUIFacade {                @Override                public void run() {                  try { -                  showMessageDialog(TITLE_HASHDATA, MESSAGE_HASHDATA_VIEWER); +                  showMessageDialog(TITLE_SIGNATURE_DATA, MESSAGE_HASHDATA_VIEWER);                    showSecureViewer(dataToBeSigned.get(0), backListener, backCommand);                  } catch (FontProviderException ex) {                    log.error("failed to display secure viewer", ex); @@ -1411,7 +1319,7 @@ public class BKUGUIImpl implements BKUGUIFacade {            }          } else {            log.debug("[" + Thread.currentThread().getName() + "] mime-type not supported by secure viewer, scheduling save dialog"); -          showMessageDialog(TITLE_HASHDATA, MESSAGE_UNSUPPORTED_MIMETYPE); +          showMessageDialog(TITLE_SIGNATURE_DATA, MESSAGE_UNSUPPORTED_MIMETYPE);            SecureViewerSaveDialog.showSaveDialog(dataToBeSigned.get(0), messages, backListener, backCommand);           }        } else { @@ -1421,28 +1329,7 @@ public class BKUGUIImpl implements BKUGUIFacade {      /**       * has to be called from event dispatcher thread -     * @param hashDataText -     * @param saveListener -     * @param saveCommand       */ -//    private void showSecureViewer(HashDataInput dataToBeSigned) throws FontProviderException { -//       -//      log.debug("[" + Thread.currentThread().getName() + "] show secure viewer"); -//      if (secureViewer == null) { -//        secureViewer = new SecureViewerDialog(null, messages, -//                fontProvider, helpMouseListener.getActionListener()); -// -//        // workaround for [#439] -//        // avoid AlwaysOnTop at least in applet, otherwise make secureViewer AlwaysOnTop since MOCCA Dialog (JFrame created in LocalSTALFactory) is always on top. -//        Window window = SwingUtilities.getWindowAncestor(contentPane); -//        if (window != null && window.isAlwaysOnTop()) { -//          log.debug("make secureViewer alwaysOnTop"); -//          secureViewer.setAlwaysOnTop(true); -//        } -//      } -//      secureViewer.setContent(dataToBeSigned); -//      log.trace("show secure viewer returned"); -//    }      private void showSecureViewer(HashDataInput dataToBeSigned, ActionListener closeListener, String closeCommand) throws FontProviderException {        log.debug("[" + Thread.currentThread().getName() + "] show secure viewer"); @@ -1479,7 +1366,7 @@ public class BKUGUIImpl implements BKUGUIFacade {            buttonPanel.removeAll();            if (renderHeaderPanel) { -            titleLabel.setText(getMessage(TITLE_HASHDATA)); +            titleLabel.setText(getMessage(TITLE_SIGNATURE_DATA));            }            helpMouseListener.setHelpTopic(HELP_HASHDATALIST); @@ -1613,7 +1500,7 @@ public class BKUGUIImpl implements BKUGUIFacade {                @Override                public void run() {                  try { -                  showMessageDialog(TITLE_HASHDATA, MESSAGE_HASHDATA_VIEWER); +                  showMessageDialog(TITLE_SIGNATURE_DATA, MESSAGE_HASHDATA_VIEWER);                    showSecureViewer(selection, backToListListener, null);  //                  SecureViewerDialog.showSecureViewer(selection, messages, fontProvider, helpMouseListener.getActionListener(), false);                  } catch (FontProviderException ex) { @@ -1625,7 +1512,7 @@ public class BKUGUIImpl implements BKUGUIFacade {              });            } else {              log.debug("[" + Thread.currentThread().getName() + "] mime-type not supported by secure viewer, scheduling save dialog"); -            showMessageDialog(BKUGUIFacade.TITLE_HASHDATA, BKUGUIFacade.MESSAGE_UNSUPPORTED_MIMETYPE); +            showMessageDialog(BKUGUIFacade.TITLE_SIGNATURE_DATA, BKUGUIFacade.MESSAGE_UNSUPPORTED_MIMETYPE);              SecureViewerSaveDialog.showSaveDialog(selection, messages, backToListListener, null);            }          } 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 96032dc1..52a3d5fe 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 @@ -1,19 +1,19 @@  /* -* 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. -*/ + * 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.gui;  import java.util.regex.Matcher; @@ -21,7 +21,6 @@ import java.util.regex.Pattern;  import javax.swing.JButton;  import javax.swing.text.AttributeSet;  import javax.swing.text.BadLocationException; -import javax.swing.text.Document;  import javax.swing.text.PlainDocument;  /** @@ -31,16 +30,15 @@ import javax.swing.text.PlainDocument;  class PINDocument extends PlainDocument {    private static final long serialVersionUID = 1L; -      protected Pattern pinPattern;    protected int minLength;    protected int maxLength; -    protected JButton enterButton; -  protected Document compareTo; -  protected Document oldPin;            public PINDocument(int minLength, int maxLength, String pattern, JButton enterButton) { +    if (enterButton == null) { +      throw new NullPointerException("OK button null"); +    }      if (pattern != null) {        pinPattern = Pattern.compile(pattern);      } else { @@ -51,73 +49,26 @@ class PINDocument extends PlainDocument {      this.enterButton = enterButton;    } -  /** -   * @param pinSpec -   * @param enterButton -   * @param compareTo -   *          enable enterButton if this pinDocument's pin equals to -   *          compareTo's pin. may be null -   */ -  public PINDocument(int minLength, int maxLength, String pattern, JButton enterButton, Document compareTo) { -    this(minLength, maxLength, pattern, enterButton); -    this.compareTo = compareTo; +  @Override +  public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { +    if (maxLength < 0 || maxLength >= (getLength() + str.length())) { +      boolean matches = true; +      for (int i = 0; i < str.length(); i++) { +        Matcher m = pinPattern.matcher(str.substring(i, i + 1)); +        if (!m.matches()) { +          matches = false; +        } +      } +      if (matches) { +        super.insertString(offs, str, a); +        enterButton.setEnabled(getLength() >= minLength); +      } +    }    } -  /** -   * @param pinSpec -   * @param enterButton -   *          may be null -   * @param compareTo -   *          enable enterButton if this pinDocument's pin equals to -   *          compareTo's pin. may be null -   * @param oldPin -   *          enable enterButton if oldPin meets the pinSpec pin length -   *          requirements, may be null -   */ -  public PINDocument(int minLength, int maxLength, String pattern, -      JButton enterButton, Document compareTo, Document oldPin) { -    this(minLength, maxLength, pattern, enterButton); -    this.compareTo = compareTo; -    this.oldPin = oldPin; +  @Override +  public void remove(int offs, int len) throws BadLocationException { +    super.remove(offs, len); +    enterButton.setEnabled(getLength() >= minLength);    } - -        @Override -        public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { -            if (maxLength < 0 || maxLength >= (getLength() + str.length())) { -                boolean matches = true; -                for (int i = 0; i < str.length(); i++) { -                    Matcher m = pinPattern.matcher(str.substring(i, i + 1)); -                    if (!m.matches()) { -                        matches = false; -                    } -                } -                if (matches) { -                    super.insertString(offs, str, a); -                } -            } -            if (enterButton != null) { -              enterButton.setEnabled( -                      (oldPin == null || oldPin.getLength() >= minLength) && -                      getLength() >= minLength && -                      compare()); -            } -        } - -        @Override -        public void remove(int offs, int len) throws BadLocationException { -            super.remove(offs, len); -            if (enterButton != null) { -              enterButton.setEnabled( -                      (oldPin == null || oldPin.getLength() >= minLength) && -                      getLength() >= minLength && -                      compare()); -            } -        } - -        private boolean compare() throws BadLocationException { -          if (compareTo == null) { -            return true; -          } -          return compareTo.getText(0, compareTo.getLength()).equals(getText(0, getLength())); -        } -    }
\ No newline at end of file +} diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SecureViewerDialog.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SecureViewerDialog.java index 7bae4673..7db70c46 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SecureViewerDialog.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SecureViewerDialog.java @@ -17,7 +17,6 @@  package at.gv.egiz.bku.gui;  import at.gv.egiz.bku.gui.viewer.FontProvider; -import at.gv.egiz.bku.gui.viewer.FontProviderException;  import at.gv.egiz.bku.gui.viewer.SecureViewerSaveDialog;  import at.gv.egiz.stal.HashDataInput;  import java.awt.Container; @@ -25,7 +24,6 @@ import java.awt.Cursor;  import java.awt.Dimension;  import java.awt.Font;  import java.awt.Frame; -import java.awt.Window;  import java.awt.event.ActionEvent;  import java.awt.event.ActionListener;  import java.awt.event.FocusAdapter; @@ -34,32 +32,26 @@ import java.awt.event.KeyAdapter;  import java.awt.event.KeyEvent;  import java.awt.event.MouseAdapter;  import java.awt.event.MouseEvent; -import java.io.BufferedOutputStream; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent;  import java.io.BufferedReader; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream;  import java.io.InputStreamReader;  import java.io.Reader;  import java.nio.charset.Charset;  import java.text.MessageFormat;  import java.util.ArrayList;  import java.util.List; -import java.util.Locale;  import java.util.ResourceBundle;  import javax.swing.GroupLayout;  import javax.swing.ImageIcon;  import javax.swing.JButton;  import javax.swing.JDialog;  import javax.swing.JEditorPane; -import javax.swing.JFileChooser;  import javax.swing.JLabel; -import javax.swing.JOptionPane;  import javax.swing.JPanel;  import javax.swing.JScrollPane;  import javax.swing.LayoutStyle; -import javax.swing.SwingUtilities; +import javax.swing.WindowConstants;  import javax.swing.text.Document;  import javax.swing.text.EditorKit;  import javax.swing.text.StyledEditorKit; @@ -71,7 +63,7 @@ import org.apache.commons.logging.LogFactory;   *   * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>   */ -public class SecureViewerDialog extends JDialog implements ActionListener { +public class SecureViewerDialog extends JDialog {    /** don't import BKUFonts in order not to load BKUFonts.jar     * BKUApplet includes BKUFonts as runtime dependency only, the jar is copied to the applet dir in BKUOnline with dependency-plugin @@ -100,19 +92,6 @@ public class SecureViewerDialog extends JDialog implements ActionListener {     * @param owner, dialog is positioned relative to its owner     * (if null, at default location of native windowing system)     */ -//  public static void showDataToBeSigned(HashDataInput dataToBeSigned, -//          ResourceBundle messages, -//          ActionListener saveListener, String saveCommand, -//          ActionListener helpListener) { -// -////      Frame ownerFrame = (owner != null) ? -////        JOptionPane.getFrameForComponent(owner) : -////        null; -//    dialog = new SecureViewerDialog(null, messages, -//            saveListener, saveCommand, helpListener); -//    dialog.setContent(dataToBeSigned); -//    dialog.setVisible(true); -//  }    public SecureViewerDialog(Frame owner, ResourceBundle messages,            ActionListener closeListener, String closeCommand,            FontProvider fontProvider, ActionListener helpListener) { @@ -125,6 +104,10 @@ public class SecureViewerDialog extends JDialog implements ActionListener {              createViewerPanel(helpListener),              createButtonPanel(closeListener, closeCommand)); +    // also leave defaultWindowClosing HIDE_ON_CLOSE +    this.addWindowListener(new WindowCloseListener(closeListener, closeCommand)); +    this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); +      pack();      if (owner != null) {        setLocationRelativeTo(owner); @@ -305,19 +288,11 @@ public class SecureViewerDialog extends JDialog implements ActionListener {      JButton closeButton = new JButton();      closeButton.setText(messages.getString(BKUGUIFacade.BUTTON_CLOSE));      closeButton.setActionCommand(closeCommand); -    closeButton.addActionListener(closeListener); -    closeButton.addActionListener(new ActionListener() { -      @Override -      public void actionPerformed(ActionEvent e) { -        log.trace("[" + Thread.currentThread().getName() + "] closing secure viewer"); -        setVisible(false); -      } -    }); +    closeButton.addActionListener(new CloseButtonListener(closeListener));      JButton saveButton = new JButton();      saveButton.setText(messages.getString(BKUGUIFacade.BUTTON_SAVE)); -    saveButton.setActionCommand("save"); //TODO ensure unequal to closeCommand  -    saveButton.addActionListener(this); +    saveButton.addActionListener(new SaveButtonListener());      int buttonSize = closeButton.getPreferredSize().width;      if (saveButton.getPreferredSize().width > buttonSize) { @@ -336,39 +311,50 @@ public class SecureViewerDialog extends JDialog implements ActionListener {      return buttonPanel;    } -  @Override -  public void actionPerformed(ActionEvent e) { -    if ("save".equals(e.getActionCommand())) { +  public class WindowCloseListener extends WindowAdapter { + +    ActionListener closeListener; +    String closeCommand; + +    public WindowCloseListener(ActionListener closeListener, String closeCommand) { +      this.closeListener = closeListener; +      this.closeCommand = closeCommand; +    } + +    @Override +    public void windowClosing(WindowEvent e) { +      log.trace("[" + Thread.currentThread().getName() + "] closing secure viewer"); +      setVisible(false); +      if (closeListener != null) { +        closeListener.actionPerformed(new ActionEvent(e.getSource(), e.getID(), closeCommand)); +      } +    } +  } + +  public class CloseButtonListener implements ActionListener { + +    ActionListener closeListener; + +    public CloseButtonListener(ActionListener closeListener) { +      this.closeListener = closeListener; +    } + +    @Override +    public void actionPerformed(ActionEvent e) { +      log.trace("[" + Thread.currentThread().getName() + "] closing secure viewer"); +      setVisible(false); +      if (closeListener != null) { +        closeListener.actionPerformed(e); +    } +    } +  } + +  public class SaveButtonListener implements ActionListener { + +    @Override +    public void actionPerformed(ActionEvent e) {        log.trace("[" + Thread.currentThread().getName() + "] display secure viewer save dialog");        SecureViewerSaveDialog.showSaveDialog(content, messages, null, null); -      log.trace("done secure viewer save"); -    } else { -      log.warn("unknown action command " + e.getActionCommand());      }    } -   -   -//  //TEST -//  private static SecureViewerDialog secureViewer; -//  public static void showSecureViewerXXX(HashDataInput dataToBeSigned, ResourceBundle messages, FontProvider fontProvider, ActionListener helpListener, boolean alwaysOnTop) throws FontProviderException { -//     -////    ResourceBundle messages = ResourceBundle.getBundle(BKUGUIFacade.MESSAGES_BUNDLE, locale); -//     -//    log.debug("[" + Thread.currentThread().getName() + "] show secure viewer"); -//    if (secureViewer == null) { -//      secureViewer = new SecureViewerDialog(null, messages, -//              fontProvider, helpListener);  -// -//      // workaround for [#439] -//      // avoid AlwaysOnTop at least in applet, otherwise make secureViewer AlwaysOnTop since MOCCA Dialog (JFrame created in LocalSTALFactory) is always on top. -////      Window window = SwingUtilities.getWindowAncestor(contentPane); -////      if (window != null && window.isAlwaysOnTop()) { -////        log.debug("make secureViewer alwaysOnTop"); -//        secureViewer.setAlwaysOnTop(alwaysOnTop); -////      } -//    } -//    secureViewer.setContent(dataToBeSigned); -//    log.trace("show secure viewer returned"); -//  } -  } 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 3e483fc8..c09433de 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 @@ -16,15 +16,15 @@  title.welcome=<html>Willkommen</html>  title.insertcard=<html>Keine B\u00FCrgerkarte gefunden</html>  title.cardnotsupported=<html>Die Karte wird nicht unterst\u00FCtzt</html> -#title.cardpin=<html>{0} eingeben</html> -title.cardpin=<html>Karte wird gelesen</html> +title.verify.pin=<html>Karte wird gelesen</html>  title.sign=<html>Signatur erstellen</html> +title.verify.pinpad=<html>PIN eingeben  title.error=<html>Fehler</html>  title.warning=<html>Achtung  title.entry.timeout=<html>Zeit\u00FCberschreitung</html>  title.retry=<html>Falsche PIN</html>  title.wait=<html>Bitte warten</html> -title.hashdata=<html>Signaturdaten</html> +title.signature.data=<html>Signaturdaten</html>  windowtitle.save=Signaturdaten speichern  windowtitle.error=Fehler  windowtitle.savedir=Signaturdaten in Verzeichnis speichern @@ -38,7 +38,8 @@ 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> +enterpin.pinpad=<html>PIN am Kartenleser eingeben</html> +enterpin.pinpad.direct=<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>  hashdatalink.focus=<html><a href=\"anzeige\">[Signaturdaten anzeigen]</a></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 c553bcb5..4d86d21b 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 @@ -16,15 +16,15 @@  title.welcome=<html>Welcome</html>  title.insertcard=<html>No citizen card found</html>  title.cardnotsupported=<html>This card is not supported</html> -#title.cardpin=<html>Enter {0}</html> -title.cardpin=<html>Reading card</html> +title.verify.pin=<html>Reading card</html>  title.sign=<html>Create signature</html> +title.verify.pinpad=<html>Enter PIN  title.error=<html>Error</html>  title.warning=<html>Warning  title.entry.timeout=<html>Timeout</html>  title.retry=<html>Wrong PIN</html>  title.wait=<html>Please wait</html> -title.hashdata=<html>Signature data</html> +title.signature.data=<html>Signature data</html>  windowtitle.save=Save signature data  windowtitle.error=Error  windowtitle.savedir=Save signature data to directory @@ -38,7 +38,8 @@ 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> +enterpin.pinpad=<html>Enter PIN on card reader pinpad</html> +enterpin.pinpad.direct=<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>  hashdatalink.focus=<html><a href=\"anzeige\">[Display signature data]</a></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 6e345ee3..a2a84d6e 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 @@ -45,7 +45,7 @@ public class BKUGUIWorker implements Runnable {    @Override    public void run() { -//        try { +        try {      final PINSpec signPinSpec = new PINSpec(6, 10, "[0-9]", "Test-PIN", (byte) 0x81, null);      final PINSpec cardPinSpec = new PINSpec(4, 4, "[0-9]", "Test-PIN", (byte) 0x01, null); @@ -155,7 +155,10 @@ public class BKUGUIWorker implements Runnable {  //  //            gui.showSignaturePINDialog(signPinSpec, -1, signListener, "sign", cancelListener, "cancel", hashdataListener, "hashdata"); -    gui.showPinpadSignaturePINDialog(signPinSpec, -1, hashdataListener, "hashdata"); +    gui.showSignatureDataDialog(signPinSpec, signListener, "sign", cancelListener, "cancel", hashdataListener, "hashdata"); +    Thread.sleep(2000); +     +    gui.showEnterPINDirect(signPinSpec, -1);  //  //            Thread.sleep(4000);  // @@ -189,8 +192,8 @@ public class BKUGUIWorker implements Runnable {  //            gui.showTextPlainHashDataInput("hallo,\n welt!", "12345", null, "cancel", null, "save");  //            Thread.sleep(2000); -//        } catch (InterruptedException ex) { -//            ex.printStackTrace(); -//        } +        } catch (InterruptedException ex) { +            ex.printStackTrace(); +        }    }  } diff --git a/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/ComparePinDocument.java b/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/ComparePinDocument.java new file mode 100644 index 00000000..623f6fad --- /dev/null +++ b/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/ComparePinDocument.java @@ -0,0 +1,102 @@ +/* + * 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.gui; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.swing.JButton; +import javax.swing.text.AttributeSet; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import javax.swing.text.PlainDocument; + +/** + * Checks if the pin confirmation (compareTo) corresponds to this pin. + * Additionally, checks if currentPIN (optional) meets the requirements before enabling the OK button. + * @author clemens + */ +class ComparePinDocument extends PlainDocument { + +  private static final long serialVersionUID = 1L; +  protected Pattern pinPattern; +  protected int minLength; +  protected int maxLength; +  protected JButton enterButton; +  protected Document compareTo; +  protected Document currentPIN; + +  /** +   * Constructor without compareTo Document parameter (allow null and set later to avoid cyclic dependencies) +   */ +  public ComparePinDocument(int minLength, int maxLength, String pattern, JButton enterButton) { +    if (enterButton == null) { +      throw new NullPointerException("OK button null"); +    } +    if (pattern != null) { +      pinPattern = Pattern.compile(pattern); +    } else { +      pinPattern = Pattern.compile("."); +    } +    this.minLength = minLength; +    this.maxLength = maxLength; +    this.enterButton = enterButton; +  } + +  /** +   * @param compareTo should not be null (allow null and set later to avoid cyclic dependencies) +   */ +  public ComparePinDocument(int minLength, int maxLength, String pattern, +          JButton enterButton, Document compareTo) { +    this(minLength, maxLength, pattern, enterButton); +    this.compareTo = compareTo; +  } +   +  public ComparePinDocument(int minLength, int maxLength, String pattern, +          JButton enterButton, Document compareTo, Document currentPIN) { +    this(minLength, maxLength, pattern, enterButton, compareTo); +    this.currentPIN = currentPIN; +  } + +  @Override +  public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { +    if (maxLength < 0 || maxLength >= (getLength() + str.length())) { +      boolean matches = true; +      for (int i = 0; i < str.length(); i++) { +        Matcher m = pinPattern.matcher(str.substring(i, i + 1)); +        if (!m.matches()) { +          matches = false; +        } +      } +      if (matches) { +        super.insertString(offs, str, a); +        enterButton.setEnabled( +                getLength() >= minLength +                && (currentPIN == null || currentPIN.getLength() >= minLength) +                && compareTo.getText(0, compareTo.getLength()).equals(getText(0, getLength()))); +      } +    } +  } + +  @Override +  public void remove(int offs, int len) throws BadLocationException { +    super.remove(offs, len); +    enterButton.setEnabled( +            getLength() >= minLength +            && (currentPIN == null || currentPIN.getLength() >= minLength) +            && compareTo.getText(0, compareTo.getLength()).equals(getText(0, getLength()))); +  } +} diff --git a/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/ExtendedPinDocument.java b/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/ExtendedPinDocument.java new file mode 100644 index 00000000..3a0d7a66 --- /dev/null +++ b/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/ExtendedPinDocument.java @@ -0,0 +1,108 @@ +/* + * 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.gui; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.swing.JButton; +import javax.swing.text.AttributeSet; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import javax.swing.text.PlainDocument; + +/** + * This PINDocument also checks if the additional (optional) pinDocuments also meet the requirements + * to enable the OK button.  + * Checks if (optional) newPIN and confirmPIN correspond + *  + * @author clemens + */ +class ExtendedPinDocument extends PlainDocument { + +  private static final long serialVersionUID = 1L; +  protected Pattern pinPattern; +  protected int minLength; +  protected int maxLength; +  protected JButton enterButton; +  protected Document newPIN; +  protected Document confirmPIN; + +  public ExtendedPinDocument(int minLength, int maxLength, String pattern, JButton enterButton) { +    if (enterButton == null) { +      throw new NullPointerException("OK Button null"); +    } +    if (pattern != null) { +      pinPattern = Pattern.compile(pattern); +    } else { +      pinPattern = Pattern.compile("."); +    } +    this.minLength = minLength; +    this.maxLength = maxLength; +    this.enterButton = enterButton; +  } + +  /** +   * @param pinSpec +   * @param enterButton +   * @param newPIN, confirmPIN +   */ +  public ExtendedPinDocument(int minLength, int maxLength, String pattern, JButton enterButton, Document newPIN, Document confirmPIN) { +    this(minLength, maxLength, pattern, enterButton); +    this.newPIN = newPIN; +    this.confirmPIN = confirmPIN; +  } + +  @Override +  public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { +    if (maxLength < 0 || maxLength >= (getLength() + str.length())) { +      boolean matches = true; +      for (int i = 0; i < str.length(); i++) { +        Matcher m = pinPattern.matcher(str.substring(i, i + 1)); +        if (!m.matches()) { +          matches = false; +        } +      } +      if (matches) { +        super.insertString(offs, str, a); +        enterButton.setEnabled( +                getLength() >= minLength +                && (newPIN == null || newPIN.getLength() >= minLength) +                && (confirmPIN == null || compare())); +      } +    } +  } + +  @Override +  public void remove(int offs, int len) throws BadLocationException { +    super.remove(offs, len); +    enterButton.setEnabled( +            getLength() >= minLength +            && (newPIN == null || newPIN.getLength() >= minLength) +            && (confirmPIN == null || compare())); +  } + +  /** +   * assume confirmPIN != null +   * @return +   */ +  private boolean compare() throws BadLocationException { +    if (newPIN != null) { +      return confirmPIN.getText(0, confirmPIN.getLength()).equals(newPIN.getText(0, newPIN.getLength())); +    } +    return false; +  } +} diff --git a/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java b/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java index 5bbed096..4dcc388f 100644 --- a/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java +++ b/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java @@ -239,23 +239,7 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac    }    @Override -  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) { +  public void showModifyPINDirect(DIALOG type, PINSpec pinSpec, int retries) {      String title, msg;      Object[] params;      if (retries < 0) { @@ -269,19 +253,19 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac        if (type == DIALOG.CHANGE) {          log.debug("show change pin dialog");          title = TITLE_CHANGE_PIN; -        msg = MESSAGE_CHANGEPIN_PINPAD; +        msg = MESSAGE_CHANGE_PINPAD_DIREKT;        } else if (type == DIALOG.ACTIVATE) {          log.debug("show activate pin dialog");          title = TITLE_ACTIVATE_PIN; -        msg = MESSAGE_ENTERPIN_PINPAD; +        msg = MESSAGE_ACTIVATE_PINPAD_DIREKT;        } else if (type == DIALOG.VERIFY) {          log.debug("show verify pin dialog"); -        title = TITLE_VERIFY_PIN; -        msg = MESSAGE_ENTERPIN_PINPAD; +        title = TITLE_VERIFY_PINPAD; +        msg = MESSAGE_ENTERPIN_PINPAD_DIRECT;        } else {          log.debug("show unblock pin dialog");          title = TITLE_UNBLOCK_PIN; -        msg = MESSAGE_ENTERPIN_PINPAD; +        msg = MESSAGE_UNBLOCK_PINPAD_DIREKT;        }      } else { @@ -294,6 +278,15 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac      showMessageDialog(title, msg, params);    } +  @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); +  } + +    private void showPINDialog(final DIALOG type, final PINSpec pinSpec,            final int retries, final boolean pinpad,            final ActionListener okListener, final String okCommand, @@ -322,7 +315,7 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac                  } else if (type == DIALOG.VERIFY) {                    log.debug("show verify pin dialog");                    TITLE = TITLE_VERIFY_PIN; -                  MESSAGE_MGMT = MESSAGE_VERIFY_PIN; +                  MESSAGE_MGMT = MESSAGE_ENTERPIN;                  } else {                    log.debug("show unblock pin dialog");                    TITLE = TITLE_UNBLOCK_PIN; @@ -393,7 +386,7 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac                  if (pinpad) {                    JLabel pinpadLabel = new JLabel();                    pinpadLabel.setFont(mgmtLabel.getFont().deriveFont(mgmtLabel.getFont().getStyle() & ~Font.BOLD)); -                  String pinpadPattern = getMessage(MESSAGE_VERIFYPIN_PINPAD); +                  String pinpadPattern = getMessage(MESSAGE_ENTERPIN_PINPAD);                    pinpadLabel.setText(MessageFormat.format(pinpadPattern,                            new Object[] { pinSpec.getLocalizedName(), pinSpec.getLocalizedLength() })); @@ -403,7 +396,7 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac                            .addComponent(pinpadLabel);                  } else { -                JButton okButton = new JButton(); +                final JButton okButton = new JButton();                  okButton.setFont(okButton.getFont().deriveFont(okButton.getFont().getStyle() & ~Font.BOLD));                  okButton.setText(getMessage(BUTTON_OK));                  okButton.setEnabled(pinSpec.getMinLength() <= 0); @@ -414,7 +407,7 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac                  JLabel repeatPinLabel = null;                  JLabel pinLabel = new JLabel();                  pinLabel.setFont(pinLabel.getFont().deriveFont(pinLabel.getFont().getStyle() & ~Font.BOLD)); -                String pinLabelPattern = (type == DIALOG.CHANGE) ? getMessage(LABEL_NEW_PIN) : getMessage(LABEL_PIN); +                String pinLabelPattern = (type == DIALOG.CHANGE || type == DIALOG.UNBLOCK) ? getMessage(LABEL_NEW_PIN) : getMessage(LABEL_PIN);                  pinLabel.setText(MessageFormat.format(pinLabelPattern, new Object[]{pinSpec.getLocalizedName()}));                  final JPasswordField repeatPinField = new JPasswordField(); @@ -436,8 +429,6 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac                  });                  if (type != DIALOG.VERIFY) { -                  pinField.setDocument( -                      new PINDocument(pinSpec.getRecMinLength(), pinSpec.getRecMaxLength(), pinSpec.getRexepPattern(), null));                    repeatPinLabel = new JLabel();                    repeatPinLabel.setFont(pinLabel.getFont());                    String repeatPinLabelPattern = getMessage(LABEL_REPEAT_PIN); @@ -449,22 +440,20 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac                        @Override                        public void actionPerformed(ActionEvent e) { -                          if (pinField.getPassword().length >= pinSpec.getMinLength()) { +                          if (okButton.isEnabled()) {                                okListener.actionPerformed(e);                            }                        }                    }); -                  if (type == DIALOG.CHANGE) { +                  if (type == DIALOG.CHANGE || type == DIALOG.UNBLOCK) {                      oldPinLabel = new JLabel();                      oldPinLabel.setFont(oldPinLabel.getFont().deriveFont(oldPinLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); -                    String oldPinLabelPattern = getMessage(LABEL_OLD_PIN); +                    String oldPinLabelPattern = getMessage((type == DIALOG.CHANGE) ? LABEL_OLD_PIN : LABEL_PUK);                      oldPinLabel.setText(MessageFormat.format(oldPinLabelPattern, new Object[]{pinSpec.getLocalizedName()}));                      oldPinField = new JPasswordField();                      oldPinField.setText(""); -                    oldPinField.setDocument( -                        new PINDocument(pinSpec.getMinLength(), pinSpec.getMaxLength(), pinSpec.getRexepPattern(), null));                      oldPinField.setActionCommand(okCommand);                      oldPinField.addActionListener(new ActionListener() { @@ -476,16 +465,45 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac                          }                      }); -                    repeatPinField.setDocument( -                        new PINDocument(pinSpec.getRecMinLength(), pinSpec.getRecMaxLength(), pinSpec.getRexepPattern(),  -                            okButton, pinField.getDocument(), oldPinField.getDocument())); +                    ExtendedPinDocument oldPinDocument = +                        new ExtendedPinDocument(pinSpec.getMinLength(), pinSpec.getMaxLength(), +                            pinSpec.getRexepPattern(), okButton); +                    ComparePinDocument newPinDocument = +                        new ComparePinDocument(pinSpec.getRecMinLength(), pinSpec.getRecMaxLength(), pinSpec.getRexepPattern(), +                            okButton); +                    ComparePinDocument confirmPinDocument = +                        new ComparePinDocument(pinSpec.getRecMinLength(), pinSpec.getRecMaxLength(), pinSpec.getRexepPattern(), +                            okButton); + +                    oldPinDocument.newPIN = newPinDocument; +                    oldPinDocument.confirmPIN = confirmPinDocument; +                     +                    newPinDocument.compareTo = confirmPinDocument; +                    newPinDocument.currentPIN = oldPinDocument; +                    confirmPinDocument.compareTo = newPinDocument; +                    confirmPinDocument.currentPIN = oldPinDocument; + +                    oldPinField.setDocument(oldPinDocument); +                    pinField.setDocument(newPinDocument); +                    repeatPinField.setDocument(confirmPinDocument); +                    } else {                      // else -> ACTIVATE (not verify, not change) -                    repeatPinField.setDocument( -                        new PINDocument(pinSpec.getRecMinLength(), pinSpec.getRecMaxLength(), pinSpec.getRexepPattern(),  -                            okButton, pinField.getDocument())); +                    ComparePinDocument newPinDocument = +                        new ComparePinDocument(pinSpec.getRecMinLength(), pinSpec.getRecMaxLength(), pinSpec.getRexepPattern(), +                            okButton); +                    ComparePinDocument confirmPinDocument = +                        new ComparePinDocument(pinSpec.getRecMinLength(), pinSpec.getRecMaxLength(), pinSpec.getRexepPattern(), +                            okButton); + +                    newPinDocument.compareTo = confirmPinDocument; +                    confirmPinDocument.compareTo = newPinDocument; + +                    pinField.setDocument(newPinDocument); +                    repeatPinField.setDocument(confirmPinDocument);                    }                  } else { +                  // VERIFY                    pinField.setDocument(                        new PINDocument(pinSpec.getMinLength(), pinSpec.getMaxLength(), pinSpec.getRexepPattern(), okButton));                  } @@ -534,7 +552,7 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac  //                } else { -                  if (type == DIALOG.CHANGE) { +                  if (type == DIALOG.CHANGE || type == DIALOG.UNBLOCK) {                      pinHorizontal                            .addGroup(mainPanelLayout.createSequentialGroup()                              .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) @@ -675,4 +693,69 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac      return bs;    } +  @Override +  public void showEnterCurrentPIN(DIALOG type, PINSpec pinSpec, int retries) { +    String title, message; +//    Object[] params = null; +     +    if (type == PINManagementGUIFacade.DIALOG.VERIFY) { +      title = PINManagementGUIFacade.TITLE_VERIFY_PINPAD; +      message = BKUGUIFacade.MESSAGE_ENTERPIN_PINPAD; +//      params = new Object[]{pinSpec.getLocalizedName(), pinSpec.getLocalizedLength()}; +    } else if (type == PINManagementGUIFacade.DIALOG.ACTIVATE) { +      title = PINManagementGUIFacade.TITLE_ACTIVATE_PIN; +      message = PINManagementGUIFacade.MESSAGE_ACTIVATE_PINPAD_CURRENT; +//      params = new Object[]{pinSpec.getLocalizedName(), pinSpec.getLocalizedLength()}; +    } else if (type == PINManagementGUIFacade.DIALOG.CHANGE) { +      title = PINManagementGUIFacade.TITLE_CHANGE_PIN; +      message = PINManagementGUIFacade.MESSAGE_CHANGE_PINPAD_CURRENT; +//      params = new Object[]{pinSpec.getLocalizedName(), pinSpec.getLocalizedLength()}; +    } else { //if (type == DIALOG.UNBLOCK) { +      title = PINManagementGUIFacade.TITLE_UNBLOCK_PIN; +      message = PINManagementGUIFacade.MESSAGE_UNBLOCK_PINPAD_CURRENT; +//      params = new Object[]{pinSpec.getLocalizedName(), pinSpec.getLocalizedLength()}; +    } +    showEnterPIN(pinSpec, retries, title, message, null); +  } + +  @Override +  public void showEnterNewPIN(DIALOG type, PINSpec pinSpec) { +    String title, message; +    if (type == PINManagementGUIFacade.DIALOG.ACTIVATE) { +      title = PINManagementGUIFacade.TITLE_ACTIVATE_PIN; +      message = PINManagementGUIFacade.MESSAGE_ACTIVATE_PINPAD_NEW; +    } else if (type == PINManagementGUIFacade.DIALOG.CHANGE) { +      title = PINManagementGUIFacade.TITLE_CHANGE_PIN; +      message = PINManagementGUIFacade.MESSAGE_CHANGE_PINPAD_NEW; +    } else if (type == DIALOG.UNBLOCK) { +      title = PINManagementGUIFacade.TITLE_UNBLOCK_PIN; +      message = PINManagementGUIFacade.MESSAGE_UNBLOCK_PINPAD_NEW; +    } else { +      log.error("enterNewPIN not supported for dialog type " + type); +      showErrorDialog(ERR_UNKNOWN, null); +      return; +    } +    showEnterPIN(pinSpec, -1, title, message, null); +  } + +  @Override +  public void showConfirmNewPIN(DIALOG type, PINSpec pinSpec) { +    String title, message; +    if (type == PINManagementGUIFacade.DIALOG.ACTIVATE) { +      title = PINManagementGUIFacade.TITLE_ACTIVATE_PIN; +      message = PINManagementGUIFacade.MESSAGE_ACTIVATE_PINPAD_CONFIRM; +    } else if (type == PINManagementGUIFacade.DIALOG.CHANGE) { +      title = PINManagementGUIFacade.TITLE_CHANGE_PIN; +      message = PINManagementGUIFacade.MESSAGE_CHANGE_PINPAD_CONFIRM; +    } else if (type == DIALOG.UNBLOCK) { +      title = PINManagementGUIFacade.TITLE_UNBLOCK_PIN; +      message = PINManagementGUIFacade.MESSAGE_UNBLOCK_PINPAD_CONFIRM; +    } else { +      log.error("enterNewPIN not supported for dialog type " + type); +      showErrorDialog(ERR_UNKNOWN, null); +      return; +    } +    showEnterPIN(pinSpec, -1, title, message, null); +  } +  } diff --git a/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java b/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java index f99bcfd1..46ae18b9 100644 --- a/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java +++ b/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java @@ -32,26 +32,39 @@ public interface PINManagementGUIFacade extends BKUGUIFacade {    public static final String TITLE_PINMGMT = "title.pin.mgmt";    public static final String TITLE_ACTIVATE_PIN = "title.activate.pin";    public static final String TITLE_CHANGE_PIN = "title.change.pin"; -  public static final String TITLE_VERIFY_PIN = "title.verify.pin"; +//  public static final String TITLE_VERIFY_PIN = "title.verify.pin";    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_UNBLOCK_SUCCESS = "title.unblock.success";    public static final String TITLE_CHANGE_SUCCESS = "title.change.success";    // 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_UNBLOCK_SUCCESS = "unblock.success";    public static final String MESSAGE_PINMGMT = "pin.mgmt";  //  public static final String MESSAGE_PINPAD = "pinpad"; +    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 MESSAGE_ACTIVATEPIN_PINPAD = "activate.pinpad"; -  public static final String MESSAGE_CHANGEPIN_PINPAD = "change.pinpad"; -  public static final String MESSAGE_VERIFYPIN_PINPAD = "verify.pinpad"; -  public static final String MESSAGE_UNBLOCKPIN_PINPAD = "unblock.pinpad"; + +  public static final String MESSAGE_ACTIVATE_PINPAD_CURRENT = "activate.pinpad.current"; +  public static final String MESSAGE_CHANGE_PINPAD_CURRENT = "change.pinpad.current"; +  public static final String MESSAGE_UNBLOCK_PINPAD_CURRENT = "unblock.pinpad.current"; +  public static final String MESSAGE_ACTIVATE_PINPAD_NEW = "activate.pinpad.new"; +  public static final String MESSAGE_CHANGE_PINPAD_NEW = "change.pinpad.new"; +  public static final String MESSAGE_UNBLOCK_PINPAD_NEW = "unblock.pinpad.new"; +  public static final String MESSAGE_ACTIVATE_PINPAD_CONFIRM = "activate.pinpad.confirm"; +  public static final String MESSAGE_CHANGE_PINPAD_CONFIRM = "change.pinpad.confirm"; +  public static final String MESSAGE_UNBLOCK_PINPAD_CONFIRM = "unblock.pinpad.confirm"; + +  public static final String MESSAGE_ACTIVATE_PINPAD_DIREKT = "activate.pinpad.direct"; +  public static final String MESSAGE_CHANGE_PINPAD_DIREKT = "change.pinpad.direct"; +  public static final String MESSAGE_UNBLOCK_PINPAD_DIREKT = "unblock.pinpad.direct";    public static final String LABEL_OLD_PIN = "label.old.pin"; +  public static final String LABEL_PUK = "label.puk";    public static final String LABEL_NEW_PIN = "label.new.pin";    public static final String LABEL_REPEAT_PIN = "label.repeat.pin"; @@ -81,35 +94,34 @@ public interface PINManagementGUIFacade extends BKUGUIFacade {    public enum STATUS { ACTIV, NOT_ACTIV, BLOCKED, UNKNOWN };    public enum DIALOG { VERIFY, ACTIVATE, CHANGE, UNBLOCK }; +  /** +   * list pins +   */    public void showPINManagementDialog(Map<PINSpec, STATUS> pins,            ActionListener activateListener, String activateCmd, String changeCmd, String unblockCmd, String verifyCmd,            ActionListener cancelListener, String cancelCmd); -  public void showPINDialog(DIALOG type, PINSpec pin, +  /** +   * "software" pin-entry dialog (activate, change, unblock, verify) +   */ +  public void showPINDialog(DIALOG type, PINSpec pinSpec, int retries,            ActionListener okListener, String okCmd,            ActionListener cancelListener, String cancelCmd); -  public void showPINDialog(DIALOG type, PINSpec pin, int retries, -          ActionListener okListener, String okCmd, -          ActionListener cancelListener, String cancelCmd); +  /** +   * <b>direct</b> pinpad pin-entry dialog +   */ +  public void showModifyPINDirect(DIALOG type, PINSpec pinSpec, int retries); + +  /** +   * <b>start/finish</b> pinpad pin-entry dialog +   */ +  public void showEnterCurrentPIN(DIALOG type, PINSpec pinSpec, int retries); + +  public void showEnterNewPIN(DIALOG type, PINSpec pinSpec); + +  public void showConfirmNewPIN(DIALOG type, PINSpec pinSpec); -  public void showPinpadPINDialog(DIALOG type, PINSpec pin, int retries); - -//  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/BKUGuiExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties b/BKUGuiExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties index 977d6e3a..5ef3edee 100644 --- a/BKUGuiExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties +++ b/BKUGuiExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties @@ -15,30 +15,44 @@  title.activation=<html>Aktivierung</html>  title.pin.mgmt=<html>PIN Verwaltung</html> -title.activate.pin=<html>PIN Aktivieren</html> -title.change.pin=<html>PIN \u00C4ndern</html> -title.unblock.pin=<html>PIN Entsperren</html> -title.verify.pin=<html>PIN Eingeben</html> +title.activate.pin=<html>PIN aktivieren</html> +title.change.pin=<html>PIN \u00E4ndern</html> +title.unblock.pin=<html>PIN entsperren</html> +#title.verify.pin=<html>PIN Eingeben</html>  title.activate.success=<html>Erfolg</html>  title.change.success=<html>Erfolg</html> +title.unblock.success=<html>Erfolg</html>  # removed message.* prefix to reuse keys as help keys  pin.mgmt=<html>Die Karte verf\u00FCgt \u00FCber {0} PINs</html> +# software pin-entry messages  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</html> -verify.pinpad=<html>{0} ({1} stellig) am Kartenleser eingeben (und best\u00E4tigen).</html> -activate.pinpad=<html>{0} ({1} stellig) am Kartenleser eingeben und wiederholen (jeweils best\u00E4tigen).</html> -change.pinpad=<html>Alte {0} ({1} stellig) am Kartenleser eingeben, danach neue {0} eingeben und wiederholen (jeweils best\u00E4tigen). </html> -unblock.pinpad=<html>{0} ({1} stellig) am Kartenleser eingeben (und best\u00E4tigen).</html> -activate.success=<html>{0} wurde erfolgreich aktiviert.</html> -change.success=<html>{0} wurde erfolgreich ge\u00E4ndert.</html> +# start/finish pin-entry messages +activate.pinpad.current=<html>Transport-PIN am Kartenleser eingeben +activate.pinpad.new=<html>Neue PIN am Kartenleser eingeben +activate.pinpad.confirm=<html>Neue PIN am Kartenleser best\u00E4tigen +change.pinpad.current=<html>Alte PIN am Kartenleser eingeben +change.pinpad.new=<html>Neue PIN am Kartenleser eingeben +change.pinpad.confirm=<html>Neue PIN am Kartenleser best\u00E4tigen +unblock.pinpad.current=<html>PUK am Kartenleser eingeben +unblock.pinpad.new=<html>Neue PIN am Kartenleser eingeben +unblock.pinpad.confirm=<html>Neue PIN am Kartenleser best\u00E4tigen +# direct pin-entry messages +activate.pinpad.direct=<html>{0} ({1} stellig) am Kartenleser eingeben und wiederholen (jeweils best\u00E4tigen).</html> +change.pinpad.direct=<html>Alte {0} ({1} stellig) am Kartenleser eingeben, danach neue {0} eingeben und wiederholen (jeweils best\u00E4tigen). </html> +unblock.pinpad.direct=<html>{0} ({1} stellig) am Kartenleser eingeben (und best\u00E4tigen).</html> +# response messages +activate.success=<html>{0} wurde erfolgreich aktiviert +change.success=<html>{0} wurde erfolgreich ge\u00E4ndert +unblock.success=<html>{0} wurde erfolgreich entsperrt  label.activation=<html>e-card Aktivierungsprozess</html>  label.activation.step=<html>Schritt {0}</html>  label.activation.idle=<html>Warte auf Server...</html>  label.old.pin=<html>Alte {0}:</html> +label.puk=<html>{0} PUK:</html>  label.new.pin=<html>Neue {0}:</html>  label.repeat.pin=<html>Best\u00E4tigung:</html> diff --git a/BKUGuiExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties b/BKUGuiExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties index 7f01971b..87e3f181 100644 --- a/BKUGuiExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties +++ b/BKUGuiExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties @@ -16,29 +16,43 @@  title.activation=<html>Activation</html>  title.pin.mgmt=<html>PIN Management</html>  title.activate.pin=<html>Activate PIN</html> -title.verify.pin=<html>Enter PIN</html> +#title.verify.pin=<html>Enter PIN</html>  title.change.pin=<html>Change PIN</html>  title.unblock.pin=<html>Unblock PIN</html>  title.activate.success=<html>Success</html>  title.change.success=<html>Success</html> +title.unblock.success=<html>Success</html>  # removed message.* prefix to reuse keys as help keys -pin.mgmt=<html>The smartcard has {0} PINs</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> -verify.pin=<html>Enter {0}</html> -verify.pinpad=<html>Enter {0} ({1} digits) on cardreader (and confirm).</html> -activate.pinpad=<html>Enter {0} ({1} digits) on cardreader and repeat (confirm in each case).</html> -change.pinpad=<html>Enter old {0} ({1} digits) on cardreader, then enter new {0} and repeat (confirm in each case).</html> -unblock.pinpad=<html>Enter {0} ({1} digits) on cardreader (and confirm).</html> +pin.mgmt=<html>{0} PINs available +# software pin-entry messages +activate.pin=<html>Enter and confirm {0} +change.pin=<html>Enter and confirm {0} +unblock.pin=<html>Enter PUK for {0} +# start/finish pin-entry messages +activate.pinpad.current=<html>Enter transport-PIN on cardreader +activate.pinpad.new=<html>Enter new PIN on cardreader +activate.pinpad.confirm=<html>Confirm new PIN on cardreader +change.pinpad.current=<html>Enter old PIN on cardreader +change.pinpad.new=<html>Enter new PIN on cardreader +change.pinpad.confirm=<html>Confirm new PIN on cardreader +unblock.pinpad.current=<html>Enter PUK on cardreader +unblock.pinpad.new=<html>Enter new PIN on cardreader +unblock.pinpad.confirm=<html>Confirm new PIN on cardreader +# direct pin-entry messages +activate.pinpad.direct=<html>Enter {0} ({1} digits) on cardreader and repeat (confirm in each case) +change.pinpad.direct=<html>Enter old {0} ({1} digits) on cardreader, then enter new {0} and repeat (confirm in each case) +unblock.pinpad.direct=<html>Enter {0} ({1} digits) on cardreader, then enter new {0} and repeat (confirm in each case) +# response messages  activate.success=<html>{0} successfully activated</html>  change.success=<html>{0} successfully changed</html> +unblock.success=<html>{0} successfully unblocked  label.activation=<html>e-card activation process</html>  label.activation.step=<html>Step {0}</html>  label.activation.idle=<html>Wait for server...</html>  label.old.pin=<html>Old {0}:</html> +label.puk=<html>{0} PUK:</html>  label.new.pin=<html>New {0}:</html>  label.repeat.pin=<html>Confirmation:</html> diff --git a/BKUOnline/src/main/resources/log4j.properties b/BKUOnline/src/main/resources/log4j.properties index 3eab8604..40133c83 100644 --- a/BKUOnline/src/main/resources/log4j.properties +++ b/BKUOnline/src/main/resources/log4j.properties @@ -15,7 +15,7 @@  #log4j.rootLogger=DEBUG, STDOUT, file -log4j.rootLogger=INFO, file +log4j.rootLogger=TRACE, file  #log4j.logger.at.gv = INFO diff --git a/BKUOnline/src/main/webapp/META-INF/context.xml b/BKUOnline/src/main/webapp/META-INF/context.xml index 2a2da79e..f38215a1 100644 --- a/BKUOnline/src/main/webapp/META-INF/context.xml +++ b/BKUOnline/src/main/webapp/META-INF/context.xml @@ -16,4 +16,4 @@    limitations under the License.  -->  <!--Context path="/bkuonline"/--> -<Context path="/bkuonline"/> +<Context path=""/> 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 1ed5a177..b8cdb208 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java @@ -16,6 +16,8 @@  */  package at.gv.egiz.smcc; +import at.gv.egiz.smcc.pin.gui.ModifyPINGUI; +import at.gv.egiz.smcc.pin.gui.PINGUI;  import java.io.ByteArrayOutputStream;  import java.io.IOException;  import java.io.InputStream; @@ -79,10 +81,16 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC    public static final byte KID_PIN_SIG = (byte) 0x81; +  public static final byte KID_PUK_SIG = (byte) 0x83; +    public static final byte KID_PIN_DEC = (byte) 0x81; +  public static final byte KID_PUK_DEC = (byte) 0x82; +    public static final byte KID_PIN_INF = (byte) 0x83; +  public static final byte KID_PUK_INF = (byte) 0x84; +    public static final byte[] DST_SIG = new byte[] { (byte) 0x84, (byte) 0x01, // tag        // ,        // length @@ -217,7 +225,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC    @Override    @Exclusive -  public byte[] getInfobox(String infobox, PINProvider provider, String domainId) +  public byte[] getInfobox(String infobox, PINGUI provider, String domainId)        throws SignatureCardException, InterruptedException {      if ("IdentityLink".equals(infobox)) { @@ -233,7 +241,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC    } -  protected byte[] getIdentityLinkV1(PINProvider provider, String domainId)  +  protected byte[] getIdentityLinkV1(PINGUI provider, String domainId)        throws SignatureCardException, InterruptedException {      try { @@ -262,7 +270,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC    } -  protected byte[] getIdentityLinkV2(PINProvider provider, String domainId) +  protected byte[] getIdentityLinkV2(PINGUI provider, String domainId)        throws SignatureCardException, InterruptedException {      try { @@ -388,7 +396,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC    @Override    @Exclusive    public byte[] createSignature(InputStream input, KeyboxName keyboxName, -      PINProvider provider, String alg) throws SignatureCardException, InterruptedException, IOException { +      PINGUI provider, String alg) throws SignatureCardException, InterruptedException, IOException {      ByteArrayOutputStream dst = new ByteArrayOutputStream();      // key ID @@ -487,7 +495,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC     * @see at.gv.egiz.smcc.AbstractSignatureCard#verifyPIN(at.gv.egiz.smcc.PINSpec, at.gv.egiz.smcc.PINProvider)     */    @Override -  public void verifyPIN(PINSpec pinSpec, PINProvider pinProvider) +  public void verifyPIN(PINSpec pinSpec, PINGUI pinProvider)        throws LockedException, NotActivatedException, CancelledException,        TimeoutException, SignatureCardException, InterruptedException { @@ -509,7 +517,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC     * @see at.gv.egiz.smcc.AbstractSignatureCard#changePIN(at.gv.egiz.smcc.PINSpec, at.gv.egiz.smcc.ChangePINProvider)     */    @Override -  public void changePIN(PINSpec pinSpec, ChangePINProvider pinProvider) +  public void changePIN(PINSpec pinSpec, ModifyPINGUI pinProvider)        throws LockedException, NotActivatedException, CancelledException,        TimeoutException, SignatureCardException, InterruptedException { @@ -528,7 +536,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC    }    @Override -  public void activatePIN(PINSpec pinSpec, PINProvider pinProvider) +  public void activatePIN(PINSpec pinSpec, ModifyPINGUI pinGUI)        throws CancelledException, SignatureCardException, CancelledException,        TimeoutException, InterruptedException {      log.error("ACTIVATE PIN not supported by ACOS"); @@ -536,7 +544,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC    }    @Override -  public void unblockPIN(PINSpec pinSpec, PINProvider pinProvider) +  public void unblockPIN(PINSpec pinSpec, ModifyPINGUI pinGUI)        throws CancelledException, SignatureCardException, InterruptedException {      throw new SignatureCardException("Unblock PIN not supported.");    } @@ -570,10 +578,8 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC    // PROTECTED METHODS (assume exclusive card access)    //////////////////////////////////////////////////////////////////////// -  protected void verifyPINLoop(CardChannel channel, PINSpec spec, PINProvider provider) -      throws InterruptedException, LockedException, NotActivatedException, -      TimeoutException, PINFormatException, PINOperationAbortedException, -      SignatureCardException, CardException { +  protected void verifyPINLoop(CardChannel channel, PINSpec spec, PINGUI provider) +      throws InterruptedException, CardException, SignatureCardException {      int retries = -1;      do { @@ -581,10 +587,8 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC      } while (retries > 0);    } -  protected void changePINLoop(CardChannel channel, PINSpec spec, ChangePINProvider provider) -      throws InterruptedException, LockedException, NotActivatedException, -      TimeoutException, PINFormatException, PINOperationAbortedException, -      SignatureCardException, CardException { +  protected void changePINLoop(CardChannel channel, PINSpec spec, ModifyPINGUI provider) +      throws InterruptedException, CardException, SignatureCardException {      int retries = -1;      do { @@ -593,7 +597,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC    }    protected int verifyPIN(CardChannel channel, PINSpec pinSpec, -      PINProvider provider, int retries) throws InterruptedException, CardException, SignatureCardException { +      PINGUI provider, int retries) throws InterruptedException, CardException, SignatureCardException {      VerifyAPDUSpec apduSpec = new VerifyAPDUSpec(          new byte[] { @@ -602,7 +606,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC              (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 },           0, VerifyAPDUSpec.PIN_FORMAT_ASCII, 8); -    ResponseAPDU resp = reader.verify(channel, apduSpec, pinSpec, provider, retries); +    ResponseAPDU resp = reader.verify(channel, apduSpec, provider, pinSpec, retries);      if (resp.getSW() == 0x9000) {        return -1; @@ -625,7 +629,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC    }    protected int changePIN(CardChannel channel, PINSpec pinSpec, -      ChangePINProvider pinProvider, int retries) throws CancelledException, InterruptedException, CardException, SignatureCardException { +      ModifyPINGUI pinProvider, int retries) throws CancelledException, InterruptedException, CardException, SignatureCardException {      ChangeReferenceDataAPDUSpec apduSpec = new ChangeReferenceDataAPDUSpec(          new byte[] { @@ -639,7 +643,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC -    ResponseAPDU resp = reader.modify(channel, apduSpec, pinSpec, pinProvider, retries); +    ResponseAPDU resp = reader.modify(channel, apduSpec, pinProvider, pinSpec, retries);      if (resp.getSW() == 0x9000) {        return -1; 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 54b4c7fe..fcb94fc6 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java @@ -16,6 +16,8 @@  */  package at.gv.egiz.smcc; +import at.gv.egiz.smcc.reader.CardReader; +import at.gv.egiz.smcc.reader.ReaderFactory;  import java.util.ArrayList;  import java.util.List;  import java.util.Locale; @@ -29,9 +31,6 @@ import javax.smartcardio.CardTerminal;  import org.apache.commons.logging.Log;  import org.apache.commons.logging.LogFactory; -import at.gv.egiz.smcc.ccid.CCID; -import at.gv.egiz.smcc.ccid.ReaderFactory; -  public abstract class AbstractSignatureCard implements SignatureCard {    private static Log log = LogFactory.getLog(AbstractSignatureCard.class); @@ -45,7 +44,7 @@ public abstract class AbstractSignatureCard implements SignatureCard {    private Card card_; -  protected CCID reader; +  protected CardReader reader;    protected AbstractSignatureCard(String resourceBundleName) {      this.resourceBundleName = resourceBundleName; @@ -68,7 +67,7 @@ public abstract class AbstractSignatureCard implements SignatureCard {    @Override    public void init(Card card, CardTerminal cardTerminal) {      this.card_ = card; -    this.reader = ReaderFactory.getInstance().getReader(card, cardTerminal); +    this.reader = ReaderFactory.getReader(card, cardTerminal);    }    @Override @@ -81,11 +80,6 @@ public abstract class AbstractSignatureCard implements SignatureCard {    }    @Override -  public CCID getReader() { -    return reader; -  } - -  @Override    public void setLocale(Locale locale) {      if (locale == null) {        throw new NullPointerException("Locale must not be set to null"); diff --git a/smcc/src/main/java/at/gv/egiz/smcc/BELPICCard.java b/smcc/src/main/java/at/gv/egiz/smcc/BELPICCard.java index e02a55d4..41358bb5 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/BELPICCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/BELPICCard.java @@ -18,6 +18,7 @@  package at.gv.egiz.smcc; +import at.gv.egiz.smcc.pin.gui.PINGUI;  import java.io.IOException;  import java.io.InputStream;  import java.security.MessageDigest; @@ -110,7 +111,7 @@ public class BELPICCard extends AbstractSignatureCard implements SignatureCard {    @Override    @Exclusive -  public byte[] getInfobox(String infobox, PINProvider provider, String domainId) +  public byte[] getInfobox(String infobox, PINGUI provider, String domainId)        throws SignatureCardException, InterruptedException {      throw new IllegalArgumentException("Infobox '" + infobox @@ -120,7 +121,7 @@ public class BELPICCard extends AbstractSignatureCard implements SignatureCard {    @Override    @Exclusive    public byte[] createSignature(InputStream input, KeyboxName keyboxName, -      PINProvider provider, String alg) throws SignatureCardException, InterruptedException, IOException { +      PINGUI provider, String alg) throws SignatureCardException, InterruptedException, IOException {      if (KeyboxName.SECURE_SIGNATURE_KEYPAIR != keyboxName) {        throw new SignatureCardException("Card does not support key " + keyboxName + "."); @@ -176,7 +177,7 @@ public class BELPICCard extends AbstractSignatureCard implements SignatureCard {    }    protected void verifyPINLoop(CardChannel channel, PINSpec spec, -      PINProvider provider) throws LockedException, NotActivatedException, +      PINGUI provider) throws LockedException, NotActivatedException,        SignatureCardException, InterruptedException, CardException {      int retries = -1; //verifyPIN(channel, spec, null, -1); @@ -186,7 +187,7 @@ public class BELPICCard extends AbstractSignatureCard implements SignatureCard {    }    protected int verifyPIN(CardChannel channel, PINSpec pinSpec, -      PINProvider provider, int retries) throws SignatureCardException, +      PINGUI provider, int retries) throws SignatureCardException,        LockedException, NotActivatedException, InterruptedException,        CardException { @@ -197,7 +198,7 @@ public class BELPICCard extends AbstractSignatureCard implements SignatureCard {              (byte) 0xff, (byte) 0xff, (byte) 0xff },           1, VerifyAPDUSpec.PIN_FORMAT_BCD, 7, 4, 4); -    ResponseAPDU resp = reader.verify(channel, apduSpec, pinSpec, provider, retries); +    ResponseAPDU resp = reader.verify(channel, apduSpec, provider, pinSpec, retries);      if (resp.getSW() == 0x9000) {        return -1; diff --git a/smcc/src/main/java/at/gv/egiz/smcc/ITCard.java b/smcc/src/main/java/at/gv/egiz/smcc/ITCard.java index 831a1f9b..64389190 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/ITCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/ITCard.java @@ -17,6 +17,7 @@  package at.gv.egiz.smcc; +import at.gv.egiz.smcc.pin.gui.PINGUI;  import java.io.ByteArrayOutputStream;  import java.io.IOException;  import java.io.InputStream; @@ -96,7 +97,7 @@ public class ITCard extends AbstractSignatureCard {    @Override    @Exclusive -  public byte[] getInfobox(String infobox, PINProvider provider, String domainId) +  public byte[] getInfobox(String infobox, PINGUI provider, String domainId)        throws SignatureCardException, InterruptedException {      throw new IllegalArgumentException("Infobox '" + infobox @@ -106,7 +107,7 @@ public class ITCard extends AbstractSignatureCard {    @Override    @Exclusive    public byte[] createSignature(InputStream input, KeyboxName keyboxName, -      PINProvider provider, String alg) throws SignatureCardException, +      PINGUI provider, String alg) throws SignatureCardException,        InterruptedException, IOException {      if (KeyboxName.SECURE_SIGNATURE_KEYPAIR != keyboxName) { @@ -159,7 +160,7 @@ public class ITCard extends AbstractSignatureCard {    }    protected void verifyPINLoop(CardChannel channel, PINSpec spec, -      PINProvider provider) throws LockedException, NotActivatedException, +      PINGUI provider) throws LockedException, NotActivatedException,        SignatureCardException, InterruptedException, CardException {      int retries = -1; @@ -169,7 +170,7 @@ public class ITCard extends AbstractSignatureCard {    }    protected int verifyPIN(CardChannel channel, PINSpec pinSpec, -      PINProvider provider, int retries) throws SignatureCardException, +      PINGUI provider, int retries) throws SignatureCardException,        LockedException, NotActivatedException, InterruptedException,        CardException { @@ -180,7 +181,7 @@ public class ITCard extends AbstractSignatureCard {              (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff },           0, VerifyAPDUSpec.PIN_FORMAT_ASCII, 8); -    ResponseAPDU resp = reader.verify(channel, apduSpec, pinSpec, provider, retries); +    ResponseAPDU resp = reader.verify(channel, apduSpec, provider, pinSpec, retries);      if (resp.getSW() == 0x9000) {        return -2; diff --git a/smcc/src/main/java/at/gv/egiz/smcc/PINConfirmationException.java b/smcc/src/main/java/at/gv/egiz/smcc/PINConfirmationException.java index eaf38435..24dfa53c 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/PINConfirmationException.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/PINConfirmationException.java @@ -23,23 +23,4 @@ package at.gv.egiz.smcc;   * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>   */  public class PINConfirmationException extends SignatureCardException { - -  private static final long serialVersionUID = 1L; - -  public PINConfirmationException() { -    super(); -  } - -  public PINConfirmationException(String message, Throwable cause) { -    super(message, cause); -  } - -  public PINConfirmationException(String message) { -    super(message); -  } - -  public PINConfirmationException(Throwable cause) { -    super(cause); -  } -  } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/PINFormatException.java b/smcc/src/main/java/at/gv/egiz/smcc/PINFormatException.java index 774fcdf5..721c63e2 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/PINFormatException.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/PINFormatException.java @@ -23,23 +23,4 @@ package at.gv.egiz.smcc;   * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>   */  public class PINFormatException extends SignatureCardException { - -  private static final long serialVersionUID = 1L; - -  public PINFormatException() { -    super(); -  } - -  public PINFormatException(String message, Throwable cause) { -    super(message, cause); -  } - -  public PINFormatException(String message) { -    super(message); -  } - -  public PINFormatException(Throwable cause) { -    super(cause); -  } -  } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/PINMgmtSignatureCard.java b/smcc/src/main/java/at/gv/egiz/smcc/PINMgmtSignatureCard.java index 53738612..5091c10f 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/PINMgmtSignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/PINMgmtSignatureCard.java @@ -16,6 +16,9 @@  */  package at.gv.egiz.smcc; +import at.gv.egiz.smcc.pin.gui.ModifyPINGUI; + +import at.gv.egiz.smcc.pin.gui.PINGUI;  import java.util.List;  public interface PINMgmtSignatureCard extends SignatureCard { @@ -26,16 +29,16 @@ public interface PINMgmtSignatureCard extends SignatureCard {    public PIN_STATE getPINState(PINSpec pinSpec) throws SignatureCardException; -  public void verifyPIN(PINSpec pinSpec, PINProvider pinProvider) +  public void verifyPIN(PINSpec pinSpec, PINGUI pinGUI)    throws LockedException, NotActivatedException, CancelledException, SignatureCardException, InterruptedException; -  public void changePIN(PINSpec pinSpec, ChangePINProvider pinProvider) +  public void changePIN(PINSpec pinSpec, ModifyPINGUI changePINGUI)    throws LockedException, NotActivatedException, CancelledException, PINFormatException, SignatureCardException, InterruptedException; -  public void activatePIN(PINSpec pinSpec, PINProvider pinProvider) +  public void activatePIN(PINSpec pinSpec, ModifyPINGUI activatePINGUI)    throws CancelledException, SignatureCardException, InterruptedException; -  public void unblockPIN(PINSpec pinSpec, PINProvider pukProvider) +  public void unblockPIN(PINSpec pinSpec, ModifyPINGUI pukGUI)    throws CancelledException, SignatureCardException, InterruptedException;  } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/ResetRetryCounterAPDUSpec.java b/smcc/src/main/java/at/gv/egiz/smcc/ResetRetryCounterAPDUSpec.java new file mode 100644 index 00000000..7e71eb7e --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/ResetRetryCounterAPDUSpec.java @@ -0,0 +1,38 @@ +/* +* 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 ResetRetryCounterAPDUSpec extends ChangeReferenceDataAPDUSpec { + +  /** +   * @param apdu +   * @param pukPosition +   * @param pukFormat +   * @param pukLength +   * @param pukLengthSize +   * @param pukLengthPos +   * @param pinInsertionOffsetNew +   */ +  public ResetRetryCounterAPDUSpec(byte[] apdu, int pukPosition, +      int pukFormat, int pukLength, int pukLengthSize, int pukLengthPos, +      int pinInsertionOffsetNew) { +    super(apdu, pukPosition, pukFormat, pukLength, pukLengthSize, pukLengthPos); +    this.pinInsertionOffsetNew = pinInsertionOffsetNew; +  } + +   +} 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 79a4cc69..ad05352f 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java @@ -17,6 +17,8 @@  package at.gv.egiz.smcc; +import at.gv.egiz.smcc.pin.gui.ModifyPINGUI; +import at.gv.egiz.smcc.pin.gui.PINGUI;  import java.io.ByteArrayOutputStream;  import java.io.IOException;  import java.io.InputStream; @@ -225,7 +227,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu    @Override    @Exclusive -  public byte[] getInfobox(String infobox, PINProvider provider, String domainId) +  public byte[] getInfobox(String infobox, PINGUI pinGUI, String domainId)        throws SignatureCardException, InterruptedException {      try { @@ -243,7 +245,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu            try {              return ISO7816Utils.readTransparentFileTLV(channel, -1, (byte) 0x30);            } catch (SecurityStatusNotSatisfiedException e) { -            verifyPINLoop(channel, spec, provider); +            verifyPINLoop(channel, spec, pinGUI);            }          } @@ -301,7 +303,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu    @Override    @Exclusive    public byte[] createSignature(InputStream input, KeyboxName keyboxName, -      PINProvider provider, String alg) throws SignatureCardException, InterruptedException, IOException { +      PINGUI provider, String alg) throws SignatureCardException, InterruptedException, IOException {      ByteArrayOutputStream dst = new ByteArrayOutputStream();      byte[] ht = null; @@ -431,7 +433,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu     */    @Override    @Exclusive -  public void verifyPIN(PINSpec pinSpec, PINProvider pinProvider) +  public void verifyPIN(PINSpec pinSpec, PINGUI pinProvider)        throws LockedException, NotActivatedException, CancelledException,        TimeoutException, SignatureCardException, InterruptedException { @@ -442,12 +444,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu          // SELECT application          execSELECT_AID(channel, pinSpec.getContextAID());        } -      log.debug("*** verifyPIN loop");        verifyPINLoop(channel, pinSpec, pinProvider); -//      log.debug("*** verifyPIN 0"); -//      int retries = verifyPIN(channel, pinSpec, null, 0); -//      log.debug("*** verifyPIN " + retries + " tries"); -//      verifyPIN(channel, pinSpec, pinProvider, retries);      } catch (CardException e) {        log.info("Failed to verify PIN.", e);        throw new SignatureCardException("Failed to verify PIN.", e); @@ -460,7 +457,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu     */    @Override    @Exclusive -  public void changePIN(PINSpec pinSpec, ChangePINProvider pinProvider) +  public void changePIN(PINSpec pinSpec, ModifyPINGUI pinGUI)        throws LockedException, NotActivatedException, CancelledException,        TimeoutException, SignatureCardException, InterruptedException { @@ -471,9 +468,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu          // SELECT application          execSELECT_AID(channel, pinSpec.getContextAID());        } -      changePINLoop(channel, pinSpec, pinProvider); -//      int retries = verifyPIN(channel, pinSpec, null, 0); -//      changePIN(channel, pinSpec, pinProvider, retries); +      changePINLoop(channel, pinSpec, pinGUI);      } catch (CardException e) {        log.info("Failed to change PIN.", e);        throw new SignatureCardException("Failed to change PIN.", e); @@ -486,7 +481,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu     */    @Override    @Exclusive -  public void activatePIN(PINSpec pinSpec, PINProvider pinProvider) +  public void activatePIN(PINSpec pinSpec, ModifyPINGUI activatePINGUI)        throws CancelledException, SignatureCardException, CancelledException,        TimeoutException, InterruptedException { @@ -497,7 +492,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu          // SELECT application          execSELECT_AID(channel, pinSpec.getContextAID());        } -      activatePIN(channel, pinSpec, pinProvider); +      activatePIN(channel, pinSpec, activatePINGUI);      } catch (CardException e) {        log.info("Failed to activate PIN.", e);        throw new SignatureCardException("Failed to activate PIN.", e); @@ -509,9 +504,16 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu     * @see at.gv.egiz.smcc.PINMgmtSignatureCard#unblockPIN(at.gv.egiz.smcc.PINSpec, at.gv.egiz.smcc.PINProvider)     */    @Override -  public void unblockPIN(PINSpec pinSpec, PINProvider pukProvider) +  public void unblockPIN(PINSpec pinSpec, ModifyPINGUI pukProvider)        throws CancelledException, SignatureCardException, InterruptedException { -    throw new SignatureCardException("Unblock PIN is not supported."); +    CardChannel channel = getCardChannel(); + +    try { +      unblockPINLoop(channel, pinSpec, pukProvider); +    } catch (CardException e) { +      log.info("Failed to activate PIN.", e); +      throw new SignatureCardException("Failed to activate PIN.", e); +    }    }    @Override @@ -574,7 +576,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu    // PROTECTED METHODS (assume exclusive card access)    //////////////////////////////////////////////////////////////////////// -  protected void verifyPINLoop(CardChannel channel, PINSpec spec, PINProvider provider) +  protected void verifyPINLoop(CardChannel channel, PINSpec spec, PINGUI provider)        throws LockedException, NotActivatedException, SignatureCardException,        InterruptedException, CardException { @@ -584,7 +586,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu      } while (retries > 0);    } -  protected void changePINLoop(CardChannel channel, PINSpec spec, ChangePINProvider provider) +  protected void changePINLoop(CardChannel channel, PINSpec spec, ModifyPINGUI provider)        throws LockedException, NotActivatedException, SignatureCardException,        InterruptedException, CardException { @@ -594,8 +596,19 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu      } while (retries > 0);    } +  protected void unblockPINLoop(CardChannel channel, PINSpec spec, ModifyPINGUI provider) +      throws LockedException, NotActivatedException, SignatureCardException, +      InterruptedException, CardException { + +    //TODO get PUK retry counter from EF FID 0036 in MF +    int retries = -1; +    do { +      retries = unblockPIN(channel, spec, provider, retries); +    } while (retries > 0); +  } +    protected int verifyPIN(CardChannel channel, PINSpec pinSpec, -      PINProvider provider, int retries) throws SignatureCardException, +      PINGUI provider, int retries) throws SignatureCardException,        LockedException, NotActivatedException, InterruptedException,        CardException { @@ -608,108 +621,135 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu      ResponseAPDU resp;      if (provider != null) { -      resp = reader.verify(channel, apduSpec, pinSpec, provider, retries); +      resp = reader.verify(channel, apduSpec, provider, pinSpec, retries);      } else {        resp = channel.transmit(new CommandAPDU(0x00, 0x20, 0x00, pinSpec.getKID()));      } -     + +      if (resp.getSW() == 0x9000) {        return -1; -    } -    if (resp.getSW() == 0x63c0) { -      // returned by the 'short' VERIFY +    } else if (resp.getSW() == 0x6983 || resp.getSW() == 0x63c0) { +      // authentication method blocked (0x63c0 returned by 'short' VERIFY)        throw new LockedException(); -    } -    if (resp.getSW() >> 4 == 0x63c) { -      return 0x0f & resp.getSW(); -    } -     -    switch (resp.getSW()) { -    case 0x6983: -      // authentication method blocked -      // returned by the 'long' VERIFY -      throw new LockedException(); -    case 0x6984: -      // reference data not usable +    } else if (resp.getSW() == 0x6984 || resp.getSW() == 0x6985) { +      // reference data not usable; conditions of use not satisfied        throw new NotActivatedException(); -    case 0x6985: -      // conditions of use not satisfied +    } else if (resp.getSW() >> 4 == 0x63c) { +      return 0x0f & resp.getSW(); +    } else if (version > 1.2 && resp.getSW() == 0x6400) { +      log.warn("cannot query pin status prior to card activation");        throw new NotActivatedException(); -   -    default: +    } else {        String msg = "VERIFY failed. SW=" + Integer.toHexString(resp.getSW());         log.info(msg);        throw new SignatureCardException(msg);      } -        }    protected int changePIN(CardChannel channel, PINSpec pinSpec, -      ChangePINProvider pinProvider, int retries) throws CancelledException, +      ModifyPINGUI pinProvider, int retries) throws CancelledException,        InterruptedException, CardException, SignatureCardException { -     -    ChangeReferenceDataAPDUSpec apduSpec = new ChangeReferenceDataAPDUSpec( -        new byte[] {  -            (byte) 0x00, (byte) 0x24, (byte) 0x00, pinSpec.getKID(), (byte) 0x10,  -            (byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,  -            (byte) 0xff, (byte) 0xff, (byte) 0xff,  -            (byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,  -            (byte) 0xff, (byte) 0xff, (byte) 0xff },  + +      ChangeReferenceDataAPDUSpec apduSpec = new ChangeReferenceDataAPDUSpec( +        new byte[] { +            (byte) 0x00, (byte) 0x24, (byte) 0x00, pinSpec.getKID(), (byte) 0x10, +            (byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, +            (byte) 0xff, (byte) 0xff, (byte) 0xff, +            (byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, +            (byte) 0xff, (byte) 0xff, (byte) 0xff },          1, VerifyAPDUSpec.PIN_FORMAT_BCD, 7, 4, 4, 8); -     -    ResponseAPDU resp = reader.modify(channel, apduSpec, pinSpec, pinProvider, retries); -     + +    ResponseAPDU resp = reader.modify(channel, apduSpec, pinProvider, pinSpec, retries); +      if (resp.getSW() == 0x9000) {        return -1; -    } -    if (resp.getSW() >> 4 == 0x63c) { -      return 0x0f & resp.getSW(); -    } -     -    switch (resp.getSW()) { -    case 0x6983: +    } else if (resp.getSW() == 0x6983) {        // authentication method blocked        throw new LockedException(); -   -    default: +    } else if (resp.getSW() == 0x6984) { +      throw new NotActivatedException(); +    } else if (resp.getSW() >> 4 == 0x63c) { +      return 0x0f & resp.getSW(); +    } else {        String msg = "CHANGE REFERENCE DATA failed. SW=" + Integer.toHexString(resp.getSW());         log.info(msg);        throw new SignatureCardException(msg);      } -    -        }    protected int activatePIN(CardChannel channel, PINSpec pinSpec, -      PINProvider provider) throws SignatureCardException, +      ModifyPINGUI provider) throws SignatureCardException,        InterruptedException, CardException { -    NewReferenceDataAPDUSpec apduSpec = new NewReferenceDataAPDUSpec( +    ResponseAPDU resp; +    if (version < 1.2) { +      NewReferenceDataAPDUSpec apduSpec = new NewReferenceDataAPDUSpec( +          new byte[] { +              (byte) 0x00, (byte) 0x24, (byte) 0x01, pinSpec.getKID(), (byte) 0x08, +              (byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, +              (byte) 0xff, (byte) 0xff, (byte) 0xff }, +          1, VerifyAPDUSpec.PIN_FORMAT_BCD, 7, 4, 4); + +      resp = reader.modify(channel, apduSpec, provider, pinSpec); +    } else { +      NewReferenceDataAPDUSpec apduSpec = new NewReferenceDataAPDUSpec( +          new byte[] { +              (byte) 0x00, (byte) 0x24, (byte) 0x00, pinSpec.getKID(), (byte) 0x10, +              (byte) 0x26, (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0xff, +              (byte) 0xff, (byte) 0xff, (byte) 0xff,  +              (byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, +              (byte) 0xff, (byte) 0xff, (byte) 0xff }, +          1, VerifyAPDUSpec.PIN_FORMAT_BCD, 7, 4, 4); +      apduSpec.setPinInsertionOffsetNew(8); +      resp = reader.modify(channel, apduSpec, provider, pinSpec); +    } + +    if (resp.getSW() == 0x9000) { +      return -1; +    } else { +      String msg = "CHANGE REFERENCE DATA failed. SW=" + Integer.toHexString(resp.getSW()); +      log.info(msg); +      throw new SignatureCardException(msg); +    } +  } +   +  protected int unblockPIN(CardChannel channel, PINSpec pinSpec, +      ModifyPINGUI provider, int retries) throws SignatureCardException, +      InterruptedException, CardException { + +    if (version < 1.2) { +      // would return 0x6982 (Security status not satisfied) +      throw new SignatureCardException("RESET RETRY COUNTER is not supported by this card."); +    } + +    ResetRetryCounterAPDUSpec apduSpec = new ResetRetryCounterAPDUSpec(          new byte[] { -            (byte) 0x00, (byte) 0x24, (byte) 0x01, pinSpec.getKID(), (byte) 0x08, +            (byte) 0x00, (byte) 0x2c, (byte) 0x00, pinSpec.getKID(), (byte) 0x10,              (byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, -            (byte) 0xff, (byte) 0xff, (byte) 0xff },  -        1, VerifyAPDUSpec.PIN_FORMAT_BCD, 7, 4, 4); -     -    ResponseAPDU resp = reader.activate(channel, apduSpec, pinSpec, provider); -     -    switch (resp.getSW()) { -     -    case 0x9000: -      return -1; +            (byte) 0xff, (byte) 0xff, (byte) 0xff, +            (byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, +            (byte) 0xff, (byte) 0xff, (byte) 0xff }, +        1, VerifyAPDUSpec.PIN_FORMAT_BCD, 7, 4, 4, 8); -    case 0x6983: -      // authentication method blocked -      throw new LockedException(); +    ResponseAPDU resp = reader.modify(channel, apduSpec, provider, pinSpec, retries); -    default: -      String msg = "CHANGE REFERENCE DATA failed. SW=" + Integer.toHexString(resp.getSW());  +    if (resp.getSW() == 0x9000) { +      return -1; +    } else if (resp.getSW() == 0x6983) { +      // PUK blocked +      throw new LockedException(); +    } else if (resp.getSW() == 0x6984) { +      throw new NotActivatedException(); +    } else if (resp.getSW() >> 4 == 0x63c) { +      return 0x0f & resp.getSW(); +    } else { +      String msg = "RESET RETRY COUNTER failed. SW=" + Integer.toHexString(resp.getSW());        log.info(msg);        throw new SignatureCardException(msg);      } -        } -   +    protected void execSELECT_MF(CardChannel channel) throws CardException, SignatureCardException {      ResponseAPDU resp = channel.transmit(          new CommandAPDU(0x00, 0xA4, 0x00, 0x0C)); 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 670704d5..73c7faa8 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java @@ -40,15 +40,12 @@ import java.util.Enumeration;  import java.util.Locale;  import javax.smartcardio.Card; -import javax.smartcardio.CardChannel; -import javax.smartcardio.CardException;  import javax.smartcardio.CardTerminal; -import javax.smartcardio.ResponseAPDU;  import org.apache.commons.logging.Log;  import org.apache.commons.logging.LogFactory; -import at.gv.egiz.smcc.ccid.CCID; +import at.gv.egiz.smcc.pin.gui.PINGUI;  /**   * @@ -280,7 +277,7 @@ public class SWCard implements SignatureCard {    } -  public byte[] getInfobox(String infobox, PINProvider provider, String domainId) throws SignatureCardException { +  public byte[] getInfobox(String infobox, PINGUI provider, String domainId) throws SignatureCardException {      String fileName = getFileName(infobox + ".ibx");      FileInputStream file; @@ -309,7 +306,7 @@ public class SWCard implements SignatureCard {    }    @Override -  public byte[] createSignature(InputStream input, KeyboxName keyboxName, PINProvider provider, String alg) throws SignatureCardException, InterruptedException, IOException { +  public byte[] createSignature(InputStream input, KeyboxName keyboxName, PINGUI provider, String alg) throws SignatureCardException, InterruptedException, IOException {      // KeyStore password      char[] password = getPassword(keyboxName); @@ -396,101 +393,4 @@ public class SWCard implements SignatureCard {    @Override    public void reset() throws SignatureCardException {    } - -  @Override -  public CCID getReader() { -    return new CCID() { - -      @Override -      public boolean hasFeature(Byte feature) { -        return false; -      } - -      @Override -      public byte getbTimeOut() { -        return 0; -      } - -      @Override -      public byte getbTimeOut2() { -        return 0; -      } - -      @Override -      public byte getwPINMaxExtraDigitL() { -        return 0x12; -      } - -      @Override -      public byte getwPINMaxExtraDigitH() { -        return 0x00; -      } - -      @Override -      public byte getbEntryValidationCondition() { -        return 0x02; -      } - -      @Override -      public Card connect() { -        return null; -      } - -      @Override -      public String getName() { -        return "Software CardReader"; -      } - -      @Override -      public byte[] verifyPin(byte[] PIN_VERIFY) throws CardException { -        throw new UnsupportedOperationException("Not supported yet."); -      } - -      @Override -      public byte[] verifyPinDirect(byte[] PIN_VERIFY) throws CardException { -        throw new UnsupportedOperationException("Not supported yet."); -      } - -      @Override -      public byte[] modifyPin(byte[] PIN_MODIFY) throws CardException { -        throw new UnsupportedOperationException("Not supported yet."); -      } - -      @Override -      public byte[] modifyPinDirect(byte[] PIN_MODIFY) throws CardException { -        throw new UnsupportedOperationException("Not supported yet."); -      } - -      @Override -      public void setDisablePinpad(boolean disable) { -        throw new UnsupportedOperationException("Not supported yet."); -      } - -      @Override -      public ResponseAPDU verify(CardChannel channel, VerifyAPDUSpec apduSpec, -          PINSpec pinSpec, PINProvider provider, int retries) -          throws CancelledException, InterruptedException, CardException, -          SignatureCardException { -        throw new UnsupportedOperationException("Not supported yet."); -      } - -      @Override -      public ResponseAPDU activate(CardChannel channel, -          NewReferenceDataAPDUSpec apduSpec, PINSpec pinSpec, -          PINProvider provider) throws CancelledException, -          InterruptedException, CardException, SignatureCardException { -        // TODO Auto-generated method stub -        return null; -      } - -      @Override -      public ResponseAPDU modify(CardChannel channel, -          ChangeReferenceDataAPDUSpec apduSpec, PINSpec pinSpec, -          ChangePINProvider provider, int retries) throws CancelledException, -          InterruptedException, CardException, SignatureCardException { -        // TODO Auto-generated method stub -        return null; -      } -    }; -  }  } 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 3d56f97b..fa589b84 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java @@ -17,8 +17,7 @@  package at.gv.egiz.smcc; -import at.gv.egiz.smcc.ccid.CCID; - +import at.gv.egiz.smcc.pin.gui.PINGUI;  import java.io.IOException;  import java.io.InputStream;  import java.util.Locale; @@ -99,7 +98,7 @@ public interface SignatureCard {     * @throws SignatureCardException     * @throws InterruptedException if applet is destroyed while in pin dialog     */ -  public byte[] getInfobox(String infobox, PINProvider provider, String domainId) +  public byte[] getInfobox(String infobox, PINGUI pinGUI, String domainId)        throws SignatureCardException, InterruptedException;    /** @@ -114,9 +113,7 @@ public interface SignatureCard {     * @throws IOException      */    public byte[] createSignature(InputStream input, KeyboxName keyboxName, -      PINProvider provider, String alg) throws SignatureCardException, InterruptedException, IOException; - -  public CCID getReader(); +      PINGUI pinGUI, String alg) throws SignatureCardException, InterruptedException, IOException;    /**     * Sets the local for evtl. required callbacks (e.g. PINSpec) diff --git a/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/ModifyPINGUI.java b/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/ModifyPINGUI.java new file mode 100644 index 00000000..00dc2d0e --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/ModifyPINGUI.java @@ -0,0 +1,36 @@ +/* +* 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.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; + + +public interface ModifyPINGUI extends ModifyPINProvider { + +  void modifyPINDirect(PINSpec spec, int retries) throws CancelledException, InterruptedException; +  void finishDirect(); + +  void enterCurrentPIN(PINSpec spec, int retries); +  void enterNewPIN(PINSpec spec); +  void confirmNewPIN(PINSpec spec); +  void validKeyPressed(); +  void correctionButtonPressed(); +  void allKeysCleared(); +  /** called prior to MODIFY_PIN_FINISH control command transmission (clear display or display wait message) */ +  void finish(); +} diff --git a/smcc/src/main/java/at/gv/egiz/smcc/ChangePINProvider.java b/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/ModifyPINProvider.java index 41010551..36f0097d 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/ChangePINProvider.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/ModifyPINProvider.java @@ -14,13 +14,22 @@  * See the License for the specific language governing permissions and  * limitations under the License.  */ -package at.gv.egiz.smcc; +package at.gv.egiz.smcc.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; +  /** - * + * user interface for "software pin-entry" of + * <ul> + * <li> current pin and new pin (change pin) + * <li> new pin (pin activation, no current pin) + * <li> puk and new pin (probably verify only?) + * </ul>   * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>   */ -public interface ChangePINProvider extends PINProvider { +public interface ModifyPINProvider {    /**     * @@ -30,7 +39,10 @@ public interface ChangePINProvider extends PINProvider {     * @throws at.gv.egiz.smcc.CancelledException if cancelled by user     * @throws java.lang.InterruptedException     */ -  public char[] provideOldPIN(PINSpec spec, int retries) +  public char[] provideCurrentPIN(PINSpec spec, int retries) +          throws CancelledException, InterruptedException; + +  public char[] provideNewPIN(PINSpec spec)            throws CancelledException, InterruptedException;  } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/PINGUI.java b/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/PINGUI.java new file mode 100644 index 00000000..5199977b --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/PINGUI.java @@ -0,0 +1,42 @@ +/* +* 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.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; + + +/** + * Display messages for pinpad pin-entry. + * Provides an interface for two types of pinpad pin-entry: pinpad-direct and pinpad-start/finish + * @author clemens.orthacker@iaik.tugraz.at + */ +public interface PINGUI extends PINProvider { + +  void enterPINDirect(PINSpec spec, int retries) +          throws CancelledException, InterruptedException; +   +  /** +   * @throws CancelledException, InterruptedException if signature-data dialog is interrupted or cancelled +   */ +  void enterPIN(PINSpec spec, int retries) +          throws CancelledException, InterruptedException; +  void validKeyPressed(); +  void correctionButtonPressed(); +  void allKeysCleared(); +   +} diff --git a/smcc/src/main/java/at/gv/egiz/smcc/PINProvider.java b/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/PINProvider.java index 5c294b5b..3bf49888 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/PINProvider.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/PINProvider.java @@ -14,7 +14,11 @@  * See the License for the specific language governing permissions and  * limitations under the License.  */ -package at.gv.egiz.smcc; +package at.gv.egiz.smcc.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; +  /**   * The number of retries is not fixed and there is no way (?) to obtain this value. @@ -39,7 +43,7 @@ public interface PINProvider {     * @throws at.gv.egiz.smcc.CancelledException     * @throws java.lang.InterruptedException     */ -  public char[] providePIN(PINSpec spec, int retries) +  char[] providePIN(PINSpec pinSpec, int retries)            throws CancelledException, InterruptedException;  } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/reader/CardReader.java b/smcc/src/main/java/at/gv/egiz/smcc/reader/CardReader.java new file mode 100644 index 00000000..a1246dd6 --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/reader/CardReader.java @@ -0,0 +1,92 @@ +/* + * 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.reader; + +import javax.smartcardio.CardChannel; +import javax.smartcardio.CardException; +import javax.smartcardio.ResponseAPDU; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.ChangeReferenceDataAPDUSpec; +import at.gv.egiz.smcc.NewReferenceDataAPDUSpec; +import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.ResetRetryCounterAPDUSpec; +import at.gv.egiz.smcc.SignatureCardException; +import at.gv.egiz.smcc.VerifyAPDUSpec; +import at.gv.egiz.smcc.pin.gui.ModifyPINGUI; +import at.gv.egiz.smcc.pin.gui.PINGUI; +import javax.smartcardio.Card; + +/** + * + * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at> + */ +public interface CardReader { + + +  String[] FEATURES = new String[]{"NO_FEATURE", +    "FEATURE_VERIFY_PIN_START", +    "FEATURE_VERIFY_PIN_FINISH", +    "FEATURE_MODIFY_PIN_START", +    "FEATURE_MODIFY_PIN_FINISH", +    "FEATURE_GET_KEY_PRESSED", +    "FEATURE_VERIFY_PIN_DIRECT", +    "FEATURE_MODIFY_PIN_DIRECT", +    "FEATURE_MCT_READER_DIRECT", +    "FEATURE_MCT_UNIVERSAL", +    "FEATURE_IFD_PIN_PROPERTIES", +    "FEATURE_ABORT", +    "FEATURE_SET_SPE_MESSAGE", +    "FEATURE_VERIFY_PIN_DIRECT_APP_ID", +    "FEATURE_MODIFY_PIN_DIRECT_APP_ID", +    "FEATURE_WRITE_DISPLAY", +    "FEATURE_GET_KEY", +    "FEATURE_IFD_DISPLAY_PROPERTIES"}; + +  Byte FEATURE_VERIFY_PIN_START = new Byte((byte) 0x01); +  Byte FEATURE_VERIFY_PIN_FINISH = new Byte((byte) 0x02); +  Byte FEATURE_MODIFY_PIN_START = new Byte((byte) 0x03); +  Byte FEATURE_MODIFY_PIN_FINISH = new Byte((byte) 0x04); +  Byte FEATURE_GET_KEY_PRESSED = new Byte((byte) 0x05); +  Byte FEATURE_VERIFY_PIN_DIRECT = new Byte((byte) 0x06); +  Byte FEATURE_MODIFY_PIN_DIRECT = new Byte((byte) 0x07); +  Byte FEATURE_MCT_READER_DIRECT = new Byte((byte) 0x08); +  Byte FEATURE_MCT_UNIVERSAL = new Byte((byte) 0x09); +  Byte FEATURE_IFD_PIN_PROPERTIES = new Byte((byte) 0x0a); +  //TODO continue list + + +  Card connect() throws CardException; + +  boolean hasFeature(Byte feature); + +  ResponseAPDU verify(CardChannel channel, VerifyAPDUSpec apduSpec, +          PINGUI pinGUI, PINSpec pinSpec, int retries) +      throws CancelledException, InterruptedException, CardException, SignatureCardException; + +  ResponseAPDU modify(CardChannel channel, ChangeReferenceDataAPDUSpec apduSpec, +          ModifyPINGUI pinGUI, PINSpec pinSpec, int retries) +      throws CancelledException, InterruptedException, CardException, SignatureCardException; + +  ResponseAPDU modify(CardChannel channel, NewReferenceDataAPDUSpec apduSpec, +          ModifyPINGUI pinGUI, PINSpec pinSpec) +      throws CancelledException, InterruptedException, CardException, SignatureCardException; + +  ResponseAPDU modify(CardChannel channel, ResetRetryCounterAPDUSpec apduSpec, +          ModifyPINGUI pinGUI, PINSpec pinSpec, int retries) +      throws CancelledException, InterruptedException, CardException, SignatureCardException; +} diff --git a/smcc/src/main/java/at/gv/egiz/smcc/reader/DefaultCardReader.java b/smcc/src/main/java/at/gv/egiz/smcc/reader/DefaultCardReader.java new file mode 100644 index 00000000..45ea7a5a --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/reader/DefaultCardReader.java @@ -0,0 +1,106 @@ +/* + * 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.reader; + + +import javax.smartcardio.Card; +import javax.smartcardio.CardChannel; +import javax.smartcardio.CardException; +import javax.smartcardio.CardTerminal; +import javax.smartcardio.ResponseAPDU; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.smcc.ChangeReferenceDataAPDUSpec; +import at.gv.egiz.smcc.NewReferenceDataAPDUSpec; +import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.ResetRetryCounterAPDUSpec; +import at.gv.egiz.smcc.SignatureCardException; +import at.gv.egiz.smcc.VerifyAPDUSpec; +import at.gv.egiz.smcc.pin.gui.ModifyPINGUI; +import at.gv.egiz.smcc.pin.gui.PINGUI; +import at.gv.egiz.smcc.util.ISO7816Utils; + +/** + * + * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at> + */ +public class DefaultCardReader implements CardReader { + +  protected final static Log log = LogFactory.getLog(DefaultCardReader.class); + +  protected CardTerminal ct; +  protected String name; + +  public DefaultCardReader(CardTerminal ct) { +    if (ct == null) { +      throw new NullPointerException("no card or card terminal provided"); +    } +    this.ct = ct; +    this.name = ct.getName(); +  } + +  @Override +  public ResponseAPDU verify(CardChannel channel, VerifyAPDUSpec apduSpec, +          PINGUI pinGUI, PINSpec pinSpec, int retries) +        throws SignatureCardException, CardException, InterruptedException { + +    log.debug("VERIFY"); +    return channel.transmit(ISO7816Utils.createVerifyAPDU(apduSpec, pinGUI.providePIN(pinSpec, retries))); +  } + +  @Override +  public ResponseAPDU modify(CardChannel channel, ChangeReferenceDataAPDUSpec apduSpec, +          ModifyPINGUI pinGUI, PINSpec pinSpec, int retries) +        throws SignatureCardException, CardException, InterruptedException { +    log.debug("MODIFY (CHANGE_REFERENCE_DATA)"); +    char[] oldPin = pinGUI.provideCurrentPIN(pinSpec, retries); +    char[] newPin = pinGUI.provideNewPIN(pinSpec); +    return channel.transmit(ISO7816Utils.createChangeReferenceDataAPDU(apduSpec, oldPin, newPin)); +  } + +  @Override +  public ResponseAPDU modify(CardChannel channel, NewReferenceDataAPDUSpec apduSpec, +          ModifyPINGUI pinGUI, PINSpec pinSpec) +        throws SignatureCardException, CardException, InterruptedException { +    log.debug("MODIFY (NEW_REFERENCE_DATA)"); +    char[] newPIN = pinGUI.provideNewPIN(pinSpec); +    return channel.transmit(ISO7816Utils.createNewReferenceDataAPDU(apduSpec, newPIN)); +  } + +  @Override +  public ResponseAPDU modify(CardChannel channel, ResetRetryCounterAPDUSpec apduSpec, +          ModifyPINGUI pinGUI, PINSpec pinSpec, int retries) +          throws InterruptedException, CardException, SignatureCardException { +    log.debug("MODIFY (RESET_RETRY_COUNTER)"); +    //TODO +    return modify(channel, (ChangeReferenceDataAPDUSpec) apduSpec, pinGUI, pinSpec, retries); +  } + +  @Override +  public Card connect() throws CardException { +    log.debug("connect icc"); +    return ct.connect("*"); +  } + +  @Override +  public boolean hasFeature(Byte feature) { +    return false; +  } + +} diff --git a/smcc/src/main/java/at/gv/egiz/smcc/reader/PinpadCardReader.java b/smcc/src/main/java/at/gv/egiz/smcc/reader/PinpadCardReader.java new file mode 100644 index 00000000..c2537af8 --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/reader/PinpadCardReader.java @@ -0,0 +1,703 @@ +/* + * 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.reader; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Map; + +import javax.smartcardio.Card; +import javax.smartcardio.CardChannel; +import javax.smartcardio.CardException; +import javax.smartcardio.CardTerminal; +import javax.smartcardio.ResponseAPDU; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.ChangeReferenceDataAPDUSpec; +import at.gv.egiz.smcc.NewReferenceDataAPDUSpec; +import at.gv.egiz.smcc.PINConfirmationException; +import at.gv.egiz.smcc.PINFormatException; +import at.gv.egiz.smcc.PINOperationAbortedException; +import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.ResetRetryCounterAPDUSpec; +import at.gv.egiz.smcc.SignatureCardException; +import at.gv.egiz.smcc.TimeoutException; +import at.gv.egiz.smcc.VerifyAPDUSpec; +import at.gv.egiz.smcc.pin.gui.ModifyPINGUI; +import at.gv.egiz.smcc.pin.gui.PINGUI; +import at.gv.egiz.smcc.util.SMCCHelper; + +/** + * + * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at> + */ +public class PinpadCardReader extends DefaultCardReader { + +  public static final int PIN_ENTRY_POLLING_INTERVAL = 10; + +  protected final static Log log = LogFactory.getLog(PinpadCardReader.class); + +  protected byte bEntryValidationCondition = 0x02;  // validation key pressed +  protected byte bTimeOut = 0x3c;                   // 60sec (= max on ReinerSCT) +  protected byte bTimeOut2 = 0x00;                  // default (attention with SCM) +  protected byte wPINMaxExtraDigitH = 0x00;         // min pin length zero digits +  protected byte wPINMaxExtraDigitL = 0x0c;         // max pin length 12 digits + +  /** +   * supported features and respective control codes +   */ +  protected Map<Byte, Integer> features; +  protected boolean VERIFY, MODIFY, VERIFY_DIRECT, MODIFY_DIRECT; + +  public PinpadCardReader(CardTerminal ct, Map<Byte, Integer> features) { +    super(ct); +    if (features == null) { +      throw new NullPointerException("Pinpad card reader does not support any features"); +    } +    this.features = features; + +    if (features.containsKey(FEATURE_VERIFY_PIN_START) && +        features.containsKey(FEATURE_GET_KEY_PRESSED) && +        features.containsKey(FEATURE_VERIFY_PIN_FINISH)) { +      VERIFY = true; +    } +    if (features.containsKey(FEATURE_MODIFY_PIN_START) && +        features.containsKey(FEATURE_GET_KEY_PRESSED) && +        features.containsKey(FEATURE_MODIFY_PIN_FINISH)) { +      MODIFY = true; +    } +    if (features.containsKey(FEATURE_VERIFY_PIN_DIRECT)) { +      VERIFY_DIRECT = true; +    } +    if (features.containsKey(FEATURE_MODIFY_PIN_DIRECT)) { +      MODIFY_DIRECT = true; +    } + +    if (name != null) { +      name = name.toLowerCase(); +      //ReinerSCT: http://support.reiner-sct.de/downloads/LINUX +      //           http://www.linux-club.de/viewtopic.php?f=61&t=101287&start=0 +      //old: REINER SCT CyberJack 00 00 +      //new (CCID): 0C4B/0300 Reiner-SCT cyberJack pinpad(a) 00 00 +      //Snow Leopard: Reiner-SCT cyberJack pinpad(a) 00 00 +      //display: REINER SCT CyberJack 00 00 +      if(name.startsWith("gemplus gempc pinpad") || name.startsWith("gemalto gempc pinpad")) { +        log.debug("setting custom wPINMaxExtraDigitH (0x04) for " + name); +        wPINMaxExtraDigitH = 0x04; +        log.debug("setting custom wPINMaxExtraDigitL (0x08) for " + name); +        wPINMaxExtraDigitL = 0x08; +      } else if (name.startsWith("omnikey cardman 3621")) { +        log.debug("setting custom wPINMaxExtraDigitH (0x01) for " + name); +        wPINMaxExtraDigitH = 0x01; +      } else if (name.startsWith("scm spr 532") || name.startsWith("scm microsystems inc. sprx32 usb smart card reader")) { +        log.debug("setting custom bTimeOut (0x3c) for " + name); +        bTimeOut = 0x3c; +        log.debug("setting custom bTimeOut2 (0x0f) for " + name); +        bTimeOut2 = 0x0f; +      } else if (name.startsWith("cherry smartboard xx44")) { +        log.debug("setting custom wPINMaxExtraDigitH (0x01) for " + name); +        wPINMaxExtraDigitH = 0x01; +      } +    } + +  } + +  @Override +  public boolean hasFeature(Byte feature) { +    return features.containsKey(feature); +  } +   +  private void VERIFY_PIN_START(Card icc, byte[] PIN_VERIFY) throws CardException { +    int ioctl = features.get(FEATURE_VERIFY_PIN_START); +    if (log.isTraceEnabled()) { +      log.trace("VERIFY_PIN_START (" + Integer.toHexString(ioctl) + +              ")  " + SMCCHelper.toString(PIN_VERIFY)); +    } +    byte[] resp = icc.transmitControlCommand(ioctl, PIN_VERIFY); +    if (resp != null && resp.length > 0) { +      if (resp[0] == (byte) 0x57) { +        log.error("Invalid parameter in PIN_VERIFY structure"); +        throw new CardException("ERROR_INVALID_PARAMETER"); +      } else { +        log.error("unexpected response to VERIFY_PIN_START: " + +                SMCCHelper.toString(resp)); +        throw new CardException("unexpected response to VERIFY_PIN_START: " + +                SMCCHelper.toString(resp)); +      } +    } +  } + +  private byte GET_KEY_PRESSED(Card icc) throws CardException { +    int ioctl = features.get(FEATURE_GET_KEY_PRESSED); +    byte[] resp = icc.transmitControlCommand(ioctl, new byte[0]); +    if (resp != null && resp.length == 1) { +//      if (log.isTraceEnabled()) { +//        log.trace("response " + SMCCHelper.toString(resp)); +//      } +      return resp[0]; +    } +    log.error("unexpected response to GET_KEY_PRESSED: " + +            SMCCHelper.toString(resp)); +    throw new CardException("unexpected response to GET_KEY_PRESSED: " + +            SMCCHelper.toString(resp)); +  } + +  private byte[] VERIFY_PIN_FINISH(Card icc) throws CardException { +    int ioctl = features.get(FEATURE_VERIFY_PIN_FINISH); +    if (log.isTraceEnabled()) { +      log.trace("VERIFY_PIN_FINISH (" + Integer.toHexString(ioctl) + ")"); +    } +    byte[] resp = icc.transmitControlCommand(ioctl, new byte[0]); +    if (resp != null && resp.length == 2) { +      if (log.isTraceEnabled()) { +        log.trace("response " + SMCCHelper.toString(resp)); +      } +      return resp; +    } +    log.error("unexpected response to VERIFY_PIN_FINISH: " + +            SMCCHelper.toString(resp)); +    throw new CardException("unexpected response to VERIFY_PIN_FINISH: " + +            SMCCHelper.toString(resp)); +  } + +  private void MODIFY_PIN_START(Card icc, byte[] PIN_MODIFY) throws CardException { +    int ioctl = features.get(FEATURE_MODIFY_PIN_START); +    if (log.isTraceEnabled()) { +      log.trace("MODFIY_PIN_START (" + Integer.toHexString(ioctl) + +              ")  " + SMCCHelper.toString(PIN_MODIFY)); +    } +    byte[] resp = icc.transmitControlCommand(ioctl, PIN_MODIFY); +    if (resp != null && resp.length > 0) { +      if (resp[0] == (byte) 0x57) { +        log.error("Invalid parameter in PIN_MODIFY structure"); +        throw new CardException("ERROR_INVALID_PARAMETER"); +      } else { +        log.error("unexpected response to MODIFY_PIN_START: " + +                SMCCHelper.toString(resp)); +        throw new CardException("unexpected response to MODIFY_PIN_START: " + +                SMCCHelper.toString(resp)); +      } +    } +  } + +  private byte[] MODIFY_PIN_FINISH(Card icc) throws CardException { +    int ioctl = features.get(FEATURE_MODIFY_PIN_FINISH); +    if (log.isTraceEnabled()) { +      log.trace("MODIFY_PIN_FINISH (" + Integer.toHexString(ioctl) + ")"); +    } +    byte[] resp = icc.transmitControlCommand(ioctl, new byte[0]); +    if (resp != null && resp.length == 2) { +      if (log.isTraceEnabled()) { +        log.trace("response " + SMCCHelper.toString(resp)); +      } +      return resp; +    } +    log.error("unexpected response to MODIFY_PIN_FINISH: " + +            SMCCHelper.toString(resp)); +    throw new CardException("unexpected response to MODIFY_PIN_FINISH: " + +            SMCCHelper.toString(resp)); +  } + +  private byte[] VERIFY_PIN_DIRECT(Card icc, byte[] PIN_VERIFY) throws CardException { +    int ioctl = features.get(FEATURE_VERIFY_PIN_DIRECT); +    if (log.isTraceEnabled()) { +      log.trace("VERIFY_PIN_DIRECT (" + Integer.toHexString(ioctl) + +              ")  " + SMCCHelper.toString(PIN_VERIFY)); +    } +    byte[] resp = icc.transmitControlCommand(ioctl, PIN_VERIFY); +    if (log.isTraceEnabled()) { +      log.trace("response " + SMCCHelper.toString(resp)); +    } +    return resp; +  } + +  private byte[] verifyPin(Card icc, byte[] PIN_VERIFY, PINGUI pinGUI)  +          throws SignatureCardException, CardException, InterruptedException { + +//    pinGUI.enterPIN(pinSpec, retries); + +    log.debug("VERIFY_PIN_START [" + FEATURES[FEATURE_VERIFY_PIN_START] + "]"); +    VERIFY_PIN_START(icc, PIN_VERIFY); + +    byte resp; +    do { +      resp = GET_KEY_PRESSED(icc); +      if (resp == (byte) 0x00) { +        synchronized(this) { +          try { +            wait(PIN_ENTRY_POLLING_INTERVAL); +          } catch (InterruptedException ex) { +            log.error("interrupted in VERIFY_PIN"); +          } +        } +      } else if (resp == (byte) 0x0d) { +        log.debug("GET_KEY_PRESSED: 0x0d (user confirmed)"); +        break; +      } else if (resp == (byte) 0x2b) { +        log.trace("GET_KEY_PRESSED: 0x2b (user entered valid key 0-9)"); +        pinGUI.validKeyPressed(); +      } else if (resp == (byte) 0x1b) { +        log.debug("GET_KEY_PRESSED: 0x1b (user cancelled VERIFY_PIN via cancel button)"); +        break; // returns 0x6401 +      } else if (resp == (byte) 0x08) { +        log.debug("GET_KEY_PRESSED: 0x08 (user pressed correction/backspace button)"); +        pinGUI.correctionButtonPressed(); +      } else if (resp == (byte) 0x0e) { +        log.debug("GET_KEY_PRESSED: 0x0e (timeout occured)"); +        break; // return 0x6400 +      } else if (resp == (byte) 0x40) { +        log.debug("GET_KEY_PRESSED: 0x40 (PIN_Operation_Aborted)"); +        throw new PINOperationAbortedException("PIN_Operation_Aborted (0x40)"); +      } else if (resp == (byte) 0x0a) { +        log.debug("GET_KEY_PRESSED: 0x0a (all keys cleared"); +        pinGUI.allKeysCleared(); +      } else { +        log.error("unexpected response to GET_KEY_PRESSED: " + +            Integer.toHexString(resp)); +        throw new CardException("unexpected response to GET_KEY_PRESSED: " + +            Integer.toHexString(resp)); +      } +    } while (true);  + +    return VERIFY_PIN_FINISH(icc); +  } + +  /** +   * does not display the first pin dialog (enterCurrentPIN or enterNewPIN, depends on bConfirmPIN), +   * since this is easier to do in calling modify() +   */ +  private byte[] modifyPin(Card icc, byte[] PIN_MODIFY, ModifyPINGUI pinGUI, PINSpec pINSpec) +          throws PINOperationAbortedException, CardException { + +    byte pinConfirmations = (byte) 0x00; //b0: new pin not entered (0) / entered (1) +                                         //b1: current pin not entered (0) / entered (1) +    byte bConfirmPIN = PIN_MODIFY[9]; +     +//    if ((bConfirmPIN & (byte) 0x02) == 0) { +//      log.debug("no current PIN entry requested"); +//      pinGUI.enterNewPIN(pINSpec); +//    } else { +//      log.debug("current PIN entry requested"); +//      pinGUI.enterCurrentPIN(pINSpec, retries); +//    } + +    log.debug("MODIFY_PIN_START [" + FEATURES[FEATURE_MODIFY_PIN_START] + "]"); +    MODIFY_PIN_START(icc, PIN_MODIFY); + +    byte resp; +    while (true) { +      resp = GET_KEY_PRESSED(icc); +      if (resp == (byte) 0x00) { +        synchronized(this) { +          try { +            wait(PIN_ENTRY_POLLING_INTERVAL); +          } catch (InterruptedException ex) { +            log.error("interrupted in MODIFY_PIN"); +          } +        } +      } else if (resp == (byte) 0x0d) { +        if (log.isTraceEnabled()) { +          log.trace("requested pin confirmations: 0b" + Integer.toBinaryString(bConfirmPIN & 0xff)); +          log.trace("performed pin confirmations: 0b" + Integer.toBinaryString(pinConfirmations & 0xff)); +        } +        log.debug("GET_KEY_PRESSED: 0x0d (user confirmed)"); +        if (pinConfirmations == bConfirmPIN) { +          break; +        } else if ((bConfirmPIN & (byte) 0x02) == 0 || +            (pinConfirmations & (byte) 0x02) == (byte) 0x02) { +          // no current pin entry or current pin entry already performed +          if ((pinConfirmations & (byte) 0x01) == 0) { +            // new pin +            pinConfirmations |= (byte) 0x01; +            pinGUI.confirmNewPIN(pINSpec); +          } // else: new pin confirmed +        } else { +          // current pin entry +          pinConfirmations |= (byte) 0x02; +          pinGUI.enterNewPIN(pINSpec); +        } +      } else if (resp == (byte) 0x2b) { +        log.trace("GET_KEY_PRESSED: 0x2b (user entered valid key 0-9)"); +        pinGUI.validKeyPressed(); +      } else if (resp == (byte) 0x1b) { +        log.debug("GET_KEY_PRESSED: 0x1b (user cancelled VERIFY_PIN via cancel button)"); +        break; // returns 0x6401 +      } else if (resp == (byte) 0x08) { +        log.debug("GET_KEY_PRESSED: 0x08 (user pressed correction/backspace button)"); +        pinGUI.correctionButtonPressed(); +      } else if (resp == (byte) 0x0e) { +        log.debug("GET_KEY_PRESSED: 0x0e (timeout occured)"); +        break; // return 0x6400 +      } else if (resp == (byte) 0x40) { +        log.debug("GET_KEY_PRESSED: 0x40 (PIN_Operation_Aborted)"); +        throw new PINOperationAbortedException("PIN_Operation_Aborted (0x40)"); +      } else if (resp == (byte) 0x0a) { +        log.debug("GET_KEY_PRESSED: 0x0a (all keys cleared"); +        pinGUI.allKeysCleared(); +      } else { +        log.error("unexpected response to GET_KEY_PRESSED: " + +            Integer.toHexString(resp)); +        throw new CardException("unexpected response to GET_KEY_PRESSED: " + +            Integer.toHexString(resp)); +      } + +    } + +    pinGUI.finish(); +    return MODIFY_PIN_FINISH(icc); +  } + +  private byte[] MODIFY_PIN_DIRECT(Card icc, byte[] PIN_MODIFY) throws CardException { +    int ioctl = features.get(FEATURE_MODIFY_PIN_DIRECT); +    if (log.isTraceEnabled()) { +      log.trace("MODIFY_PIN_DIRECT (" + Integer.toHexString(ioctl) + +              ")  " + SMCCHelper.toString(PIN_MODIFY)); +    } +    byte[] resp = icc.transmitControlCommand(ioctl, PIN_MODIFY); +    if (log.isTraceEnabled()) { +      log.trace("response " + SMCCHelper.toString(resp)); +    } +    return resp; +  } +   +  protected byte[] createPINModifyStructure(NewReferenceDataAPDUSpec apduSpec, PINSpec pinSpec) { + +    ByteArrayOutputStream s = new ByteArrayOutputStream(); +    // bTimeOut +    s.write(bTimeOut); +    // bTimeOut2 +    s.write(bTimeOut2); +    // bmFormatString +    s.write(1 << 7 // system unit = byte +        | (0xF & apduSpec.getPinPosition()) << 3 +        | (0x1 & apduSpec.getPinJustification() << 2) +        | (0x3 & apduSpec.getPinFormat())); +    // bmPINBlockString +    s.write((0xF & apduSpec.getPinLengthSize()) << 4 +        | (0xF & apduSpec.getPinLength())); +    // bmPINLengthFormat +    s.write(// system unit = bit +        (0xF & apduSpec.getPinLengthPos())); +    // bInsertionOffsetOld +    s.write(0x00); +    // bInsertionOffsetNew +    s.write(apduSpec.getPinInsertionOffsetNew()); +    // wPINMaxExtraDigit +    s.write(Math.min(pinSpec.getMaxLength(), wPINMaxExtraDigitL)); +    s.write(Math.max(pinSpec.getMinLength(), wPINMaxExtraDigitH)); +    // bConfirmPIN +    s.write(0x01); +    // bEntryValidationCondition +    s.write(bEntryValidationCondition); +    // bNumberMessage +    s.write(0x02); +    // wLangId English (United States), see http://www.usb.org/developers/docs/USB_LANGIDs.pdf +    s.write(0x09); +    s.write(0x04); +    // bMsgIndex1 +    s.write(0x01); +    // bMsgIndex2 +    s.write(0x02); +    // bMsgIndex3 +    s.write(0x00); + +    // bTeoPrologue +    s.write(0x00); +    s.write(0x00); +    s.write(0x00); +    // ulDataLength +    s.write(apduSpec.getApdu().length); +    s.write(0x00); +    s.write(0x00); +    s.write(0x00); +    // abData +    try { +      s.write(apduSpec.getApdu()); +    } catch (IOException e) { +      // As we are dealing with ByteArrayOutputStreams no exception is to be +      // expected. +      throw new RuntimeException(e); +    } + +    return s.toByteArray(); + +  } +   +  protected byte[] createPINModifyStructure(ChangeReferenceDataAPDUSpec apduSpec, PINSpec pinSpec) { +    //TODO bInsertionOffsetOld (0x00), bConfirmPIN (0x01), bNumberMessage (0x02), bMsgIndex1/2/3 + +    ByteArrayOutputStream s = new ByteArrayOutputStream(); +    // bTimeOut +    s.write(bTimeOut); +    // bTimeOut2 +    s.write(bTimeOut2); +    // bmFormatString +    s.write(1 << 7 // system unit = byte +        | (0xF & apduSpec.getPinPosition()) << 3 +        | (0x1 & apduSpec.getPinJustification() << 2) +        | (0x3 & apduSpec.getPinFormat())); +    // bmPINBlockString +    s.write((0xF & apduSpec.getPinLengthSize()) << 4 +        | (0xF & apduSpec.getPinLength())); +    // bmPINLengthFormat +    s.write(// system unit = bit +        (0xF & apduSpec.getPinLengthPos())); +    // bInsertionOffsetOld (0x00 for no old pin?) +    s.write(apduSpec.getPinInsertionOffsetOld()); +    // bInsertionOffsetNew +    s.write(apduSpec.getPinInsertionOffsetNew()); +    // wPINMaxExtraDigit +    s.write(Math.min(pinSpec.getMaxLength(), wPINMaxExtraDigitL)); +    s.write(Math.max(pinSpec.getMinLength(), wPINMaxExtraDigitH)); +    // bConfirmPIN +    s.write(0x03); +    // bEntryValidationCondition +    s.write(bEntryValidationCondition); +    // bNumberMessage +    s.write(0x03); +    // wLangId English (United States), see http://www.usb.org/developers/docs/USB_LANGIDs.pdf +    s.write(0x09); +    s.write(0x04); +    // bMsgIndex1 +    s.write(0x00); +    // bMsgIndex2 +    s.write(0x01); +    // bMsgIndex3 +    s.write(0x02); +     +    // bTeoPrologue +    s.write(0x00); +    s.write(0x00); +    s.write(0x00); +    // ulDataLength +    s.write(apduSpec.getApdu().length); +    s.write(0x00); +    s.write(0x00); +    s.write(0x00); +    // abData +    try { +      s.write(apduSpec.getApdu()); +    } catch (IOException e) { +      // As we are dealing with ByteArrayOutputStreams no exception is to be +      // expected. +      throw new RuntimeException(e); +    } +     +    return s.toByteArray(); + +  } +   +  protected byte[] createPINVerifyStructure(VerifyAPDUSpec apduSpec, PINSpec pinSpec) { +     +    ByteArrayOutputStream s = new ByteArrayOutputStream(); +    // bTimeOut +    s.write(bTimeOut); +    // bTimeOut2 +    s.write(bTimeOut2); +    // bmFormatString +    s.write(1 << 7 // system unit = byte +        | (0xF & apduSpec.getPinPosition()) << 3 +        | (0x1 & apduSpec.getPinJustification() << 2) +        | (0x3 & apduSpec.getPinFormat())); +    // bmPINBlockString +    s.write((0xF & apduSpec.getPinLengthSize()) << 4 +        | (0xF & apduSpec.getPinLength())); +    // bmPINLengthFormat +    s.write(// system unit = bit +        (0xF & apduSpec.getPinLengthPos())); +    // wPINMaxExtraDigit +    s.write(Math.min(pinSpec.getMaxLength(), wPINMaxExtraDigitL)); // max PIN length +    s.write(Math.max(pinSpec.getMinLength(), wPINMaxExtraDigitH)); // min PIN length +    // bEntryValidationCondition +    s.write(bEntryValidationCondition); +    // bNumberMessage +    s.write(0x01); +    // wLangId +    s.write(0x09); +    s.write(0x04); +    // bMsgIndex +    s.write(0x00); +    // bTeoPrologue +    s.write(0x00); +    s.write(0x00); +    s.write(0x00); +    // ulDataLength +    s.write(apduSpec.getApdu().length); +    s.write(0x00); +    s.write(0x00); +    s.write(0x00); +    // abData +    try { +      s.write(apduSpec.getApdu()); +    } catch (IOException e) { +      // As we are dealing with ByteArrayOutputStreams no exception is to be +      // expected. +      throw new RuntimeException(e); +    } +     +    return s.toByteArray(); +     +  } + +  @Override +  public ResponseAPDU verify(CardChannel channel, VerifyAPDUSpec apduSpec, +          PINGUI pinGUI, PINSpec pinSpec, int retries) +        throws SignatureCardException, CardException, InterruptedException { + +    ResponseAPDU resp = null; + +    byte[] s = createPINVerifyStructure(apduSpec, pinSpec); +    Card icc = channel.getCard(); + +    if (VERIFY) { +      pinGUI.enterPIN(pinSpec, retries); +      resp = new ResponseAPDU(verifyPin(icc, s, pinGUI)); +    } else if (VERIFY_DIRECT) { +      pinGUI.enterPINDirect(pinSpec, retries); +      log.debug("VERIFY_PIN_DIRECT [" + FEATURES[FEATURE_VERIFY_PIN_DIRECT] + "]"); +      resp = new ResponseAPDU(VERIFY_PIN_DIRECT(icc, s)); +    } else { +      log.warn("falling back to default pin-entry"); +      return super.verify(channel, apduSpec, pinGUI, pinSpec, retries); +    } + +    switch (resp.getSW()) { +      case 0x6400: +        log.debug("SPE operation timed out."); +        throw new TimeoutException(); +      case 0x6401: +        log.debug("SPE operation was cancelled by the 'Cancel' button."); +        throw new CancelledException(); +      case 0x6403: +          log.debug("User entered too short or too long PIN " +              + "regarding MIN/MAX PIN length."); +          throw new PINFormatException(); +      case 0x6480: +        log.debug("SPE operation was aborted by the 'Cancel' operation " +            + "at the host system."); +      case 0x6b80: +        log.info("Invalid parameter in passed structure."); +      default: +        return resp; +    } +  } + +  @Override +  public ResponseAPDU modify(CardChannel channel, ChangeReferenceDataAPDUSpec apduSpec, +          ModifyPINGUI pinGUI, PINSpec pinSpec, int retries) +        throws SignatureCardException, CardException, InterruptedException { +     +    ResponseAPDU resp = null; + +    byte[] s = createPINModifyStructure(apduSpec, pinSpec); +    Card icc = channel.getCard(); +     +    if (MODIFY) { +      pinGUI.enterCurrentPIN(pinSpec, retries); +      resp = new ResponseAPDU(modifyPin(icc, s, pinGUI, pinSpec)); +    } else if (MODIFY_DIRECT) { +      pinGUI.modifyPINDirect(pinSpec, retries); +      log.debug("MODIFY_PIN_DIRECT [" + FEATURES[FEATURE_MODIFY_PIN_DIRECT] + "]"); +      resp = new ResponseAPDU(MODIFY_PIN_DIRECT(icc, s)); +    } else { +      log.warn("falling back to default pin-entry"); +      return super.modify(channel, apduSpec, pinGUI, pinSpec, retries); +    } + +    switch (resp.getSW()) { +      case 0x6400: +        log.debug("SPE operation timed out."); +        throw new TimeoutException(); +      case 0x6401: +        log.debug("SPE operation was cancelled by the 'Cancel' button."); +        throw new CancelledException(); +      case 0x6402: +        log.debug("Modify PIN operation failed because two 'new PIN' " + +                "entries do not match"); +        throw new PINConfirmationException(); +      case 0x6403: +        log.debug("User entered too short or too long PIN " +              + "regarding MIN/MAX PIN length."); +        throw new PINFormatException(); +      case 0x6480: +        log.debug("SPE operation was aborted by the 'Cancel' operation " +            + "at the host system."); +      case 0x6b80: +        log.info("Invalid parameter in passed structure."); +      default: +        return resp; +    } +  } + +  @Override +  public ResponseAPDU modify(CardChannel channel, NewReferenceDataAPDUSpec apduSpec, +          ModifyPINGUI pinGUI, PINSpec pinSpec) +        throws SignatureCardException, CardException, InterruptedException { + +    ResponseAPDU resp = null; + +    byte[] s = createPINModifyStructure(apduSpec, pinSpec); +    Card icc = channel.getCard(); + +    if (MODIFY) { +      pinGUI.enterNewPIN(pinSpec); +      resp = new ResponseAPDU(modifyPin(icc, s, pinGUI, pinSpec)); +    } else if (MODIFY_DIRECT) { +      pinGUI.modifyPINDirect(pinSpec, -1); +      log.debug("MODIFY_PIN_DIRECT [" + FEATURES[FEATURE_MODIFY_PIN_DIRECT] + "]"); +      resp = new ResponseAPDU(MODIFY_PIN_DIRECT(icc, s)); +    } else { +      log.warn("falling back to default pin-entry"); +      return super.modify(channel, apduSpec, pinGUI, pinSpec); +    } + +    switch (resp.getSW()) { +      case 0x6400: +        log.debug("SPE operation timed out."); +        throw new TimeoutException(); +      case 0x6401: +        log.debug("SPE operation was cancelled by the 'Cancel' button."); +        throw new CancelledException(); +      case 0x6402: +        log.debug("Modify PIN operation failed because two 'new PIN' " + +                "entries do not match"); +        throw new PINConfirmationException(); +      case 0x6403: +        log.debug("User entered too short or too long PIN " +              + "regarding MIN/MAX PIN length."); +        throw new PINFormatException(); +      case 0x6480: +        log.debug("SPE operation was aborted by the 'Cancel' operation " +            + "at the host system."); +      case 0x6b80: +        log.info("Invalid parameter in passed structure."); +      default: +        return resp; +    } +  } + +  @Override +  public ResponseAPDU modify(CardChannel channel, ResetRetryCounterAPDUSpec apduSpec, +          ModifyPINGUI pinGUI, PINSpec pinSpec, int retries) +          throws InterruptedException, CardException, SignatureCardException { +    //TODO +    return modify(channel, (ChangeReferenceDataAPDUSpec) apduSpec, pinGUI, pinSpec, retries); +  } +} diff --git a/smcc/src/main/java/at/gv/egiz/smcc/reader/ReaderFactory.java b/smcc/src/main/java/at/gv/egiz/smcc/reader/ReaderFactory.java new file mode 100644 index 00000000..eb197d9f --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/reader/ReaderFactory.java @@ -0,0 +1,128 @@ +/* + * 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.reader; + +import at.gv.egiz.smcc.conf.SMCCConfiguration; +import at.gv.egiz.smcc.util.SMCCHelper; +import java.util.HashMap; +import java.util.Map; +import javax.smartcardio.Card; +import javax.smartcardio.CardException; +import javax.smartcardio.CardTerminal; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * + * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at> + */ +public class ReaderFactory { + +  protected final static Log log = LogFactory.getLog(ReaderFactory.class); +   +  protected SMCCConfiguration configuration; + +  private ReaderFactory() { +  } + +  /** +   * @param configuration the configuration to set +   */ +  public void setConfiguration(SMCCConfiguration configuration) { +    this.configuration = configuration; +  } + +  public static CardReader getReader(Card icc, CardTerminal ct) { + +    String name = ct.getName(); +    log.info("creating reader " + name); + +    Map<Byte, Integer> features = queryFeatures(icc); +    boolean disablePinpad = false; +    CardReader reader; + +        //TODO query application context for reader config +//    if (configuration != null) { +//      String disablePinpad = configuration.getProperty(SMCCConfiguration.DISABLE_PINPAD_P); +//      log.debug("setting disablePinpad to " + Boolean.parseBoolean(disablePinpad)); +//      reader.setDisablePinpad(Boolean.parseBoolean(disablePinpad)); +//    } +    log.warn("card reader configuration is not considered"); + +    if (features.isEmpty() || disablePinpad) { +      reader = new DefaultCardReader(ct); +    } else { +      reader = new PinpadCardReader(ct, features); +    } + +    return reader; +  } + +  private static int CTL_CODE(int code) { +    String os_name = System.getProperty("os.name").toLowerCase(); +    if (os_name.indexOf("windows") > -1) { +      // cf. WinIOCTL.h +      return (0x31 << 16 | (code) << 2); +    } +    // cf. reader.h +    return 0x42000000 + (code); +  } + +  static int IOCTL_GET_FEATURE_REQUEST = CTL_CODE(3400); + +  private static Map<Byte, Integer> queryFeatures(Card icc) { +    Map<Byte, Integer> features = new HashMap<Byte, Integer>(); + +    if (icc == null) { +      log.warn("invalid card handle, cannot query ifd features"); +    } else { +      try { +        if (log.isTraceEnabled()) { +          log.trace("GET_FEATURE_REQUEST " + Integer.toHexString(IOCTL_GET_FEATURE_REQUEST)); +        } +        byte[] resp = icc.transmitControlCommand(IOCTL_GET_FEATURE_REQUEST, +                new byte[0]); + +        if (log.isTraceEnabled()) { +          log.trace("Response TLV " + SMCCHelper.toString(resp)); +        } +        // tag +        // length in bytes (always 4) +        // control code value for supported feature (in big endian) +        for (int i = 0; i < resp.length; i += 6) { +          Byte feature = new Byte(resp[i]); +          Integer ioctl = new Integer((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 " + CardReader.FEATURES[feature.intValue()] + +                    ": " + Integer.toHexString(ioctl.intValue())); +          } +          features.put(feature, ioctl); +        } +      } catch (CardException ex) { +        log.debug("Failed to query IFD features: " + ex.getMessage()); +        log.trace(ex); +        log.info("IFD does not support secure pin entry"); +      } +    } +    return features; +  } + +} diff --git a/smcc/src/test/java/at/gv/egiz/smcc/AbstractAppl.java b/smcc/src/test/java/at/gv/egiz/smcc/AbstractAppl.java index 137de509..affb06ff 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/AbstractAppl.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/AbstractAppl.java @@ -51,6 +51,7 @@ public abstract class AbstractAppl implements CardAppl {      return files;    } +  @Override    public abstract void setPin(int kid, char[] value);  }
\ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/CardEmul.java b/smcc/src/test/java/at/gv/egiz/smcc/CardEmul.java index 6017bcce..3dfc8510 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/CardEmul.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/CardEmul.java @@ -28,15 +28,15 @@ import javax.smartcardio.CardException;  @SuppressWarnings("restriction")  public abstract class CardEmul extends Card { -  protected Thread exclThread = null; -  protected CardChannel channel = newCardChannel(this); +  protected Thread exclThread; // = null; +  protected CardChannel channel; // = newCardChannel(this);    protected List<AbstractAppl> applications = new ArrayList<AbstractAppl>();    public CardEmul() {      super();    } -  protected abstract CardChannelEmul newCardChannel(CardEmul cardEmul); +//  protected abstract CardChannelEmul newCardChannel(CardEmul cardEmul);    @Override    public void beginExclusive() throws CardException { @@ -71,9 +71,9 @@ public abstract class CardEmul extends Card {    @Override    public void disconnect(boolean reset) throws CardException { -    if (reset) { -      channel = newCardChannel(this); -    } +//    if (reset) { +//      channel = newCardChannel(this); +//    }    }    @Override @@ -93,7 +93,7 @@ public abstract class CardEmul extends Card {        }    public AbstractAppl getApplication(byte[] fid) { -     +      for(AbstractAppl appl : applications) {        if (Arrays.equals(appl.getAID(), fid) || Arrays.equals(appl.getFID(), fid)) {          return appl; diff --git a/smcc/src/test/java/at/gv/egiz/smcc/CardTest.java b/smcc/src/test/java/at/gv/egiz/smcc/CardTest.java index b3bd07ab..44e48836 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/CardTest.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/CardTest.java @@ -16,12 +16,14 @@  */  package at.gv.egiz.smcc; +import at.gv.egiz.smcc.pin.gui.CancelPINProvider; +import at.gv.egiz.smcc.pin.gui.InterruptPINProvider; +import at.gv.egiz.smcc.pin.gui.CancelChangePINProvider;  import static org.junit.Assert.*;  import java.io.ByteArrayInputStream;  import java.io.IOException;  import java.io.UnsupportedEncodingException; -import java.security.MessageDigest;  import java.security.NoSuchAlgorithmException;  import java.util.Arrays;  import java.util.List; @@ -32,119 +34,15 @@ import org.junit.Test;  import at.gv.egiz.smcc.SignatureCard.KeyboxName;  import at.gv.egiz.smcc.acos.A04ApplDEC; +import at.gv.egiz.smcc.pin.gui.DummyPINGUI; +import at.gv.egiz.smcc.pin.gui.ModifyPINGUI; +import at.gv.egiz.smcc.pin.gui.PINGUI; +import at.gv.egiz.smcc.pin.gui.SMCCTestPINProvider; +import org.junit.Ignore;  @SuppressWarnings("restriction")  public abstract class CardTest { -  public class TestPINProvider implements PINProvider { -     -    int provided = 0; -   -    char[] pin; -   -    public TestPINProvider(char[] pin) { -      super(); -      this.pin = pin; -    } -   -    @Override -    public char[] providePIN(PINSpec spec, int retries) -        throws CancelledException, InterruptedException { -      provided++; -      return pin; -    } - -    public int getProvided() { -      return provided; -    } -   -  } - -  public class TestChangePINProvider extends TestPINProvider implements -      ChangePINProvider { -   -    char[] oldPin; -   -    public TestChangePINProvider(char[] oldPin, char[] pin) { -      super(pin); -      this.oldPin = oldPin; -    } -   -    @Override -    public char[] provideOldPIN(PINSpec spec, int retries) -        throws CancelledException, InterruptedException { -      return oldPin; -    } -   -  } - -  public class TestInvalidPINProvider implements PINProvider { - -    int provided = 0; -    int numWrongTries = 0; - -    char[] pin; - -    public TestInvalidPINProvider(char[] pin, int numWrongTries) { -      super(); -      this.pin = pin; -      this.numWrongTries = numWrongTries; -    } - -    @Override -    public char[] providePIN(PINSpec spec, int retries) -        throws CancelledException, InterruptedException { -      if (provided >= numWrongTries) { -        throw new CancelledException("Number of wrong tries reached: " + provided); -      } else { -        provided++; -        return pin; -      } -    } - -    public int getProvided() { -      return provided; -    } -  } - -  public class TestInvalidChangePINProvider implements ChangePINProvider { - -    int provided = 0; -    int numWrongTries = 0; - -    char[] pin; -    char[] oldPin; - -    /** emulate ChangePinProvider */ -    public TestInvalidChangePINProvider(char[] oldPin, char[] newPin, int numWrongTries) { -      super(); -      this.pin = newPin; -      this.oldPin = oldPin; -      this.numWrongTries = numWrongTries; -    } - -    @Override -    public char[] providePIN(PINSpec spec, int retries) -        throws CancelledException, InterruptedException { -      return pin; -    } - -    public int getProvided() { -      return provided; -    } - -    @Override -    public char[] provideOldPIN(PINSpec spec, int retries) -        throws CancelledException, InterruptedException { -      if (provided >= numWrongTries) { -        throw new CancelledException("Number of wrong tries reached: " + provided); -      } else { -        provided++; -        return oldPin; -      } -    } -  } -    public CardTest() {      super();    } @@ -167,7 +65,7 @@ public abstract class CardTest {      SignatureCard signatureCard = createSignatureCard(); -    TestPINProvider pinProvider = new TestPINProvider(pin); +    SMCCTestPINProvider pinProvider = new SMCCTestPINProvider(pin);      byte[] idlink = signatureCard.getInfobox("IdentityLink",          pinProvider, null); @@ -184,13 +82,7 @@ public abstract class CardTest {          SignatureCard signatureCard = createSignatureCard(); -        PINProvider pinProvider = new PINProvider() { -          @Override -          public char[] providePIN(PINSpec spec, int retries) -              throws CancelledException, InterruptedException { -            throw new CancelledException(); -          } -        }; +        PINGUI pinProvider = new CancelPINProvider();      signatureCard.createSignature(new ByteArrayInputStream("MOCCA"          .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, pinProvider, @@ -205,13 +97,7 @@ public abstract class CardTest {          SignatureCard signatureCard = createSignatureCard(); -        PINProvider pinProvider = new PINProvider() { -          @Override -          public char[] providePIN(PINSpec spec, int retries) -              throws CancelledException, InterruptedException { -            throw new CancelledException(); -          } -        }; +        PINGUI pinProvider = new CancelPINProvider();          signatureCard.createSignature(new ByteArrayInputStream("MOCCA"              .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, @@ -226,13 +112,7 @@ public abstract class CardTest {          SignatureCard signatureCard = createSignatureCard(); -        PINProvider pinProvider = new PINProvider() { -          @Override -          public char[] providePIN(PINSpec spec, int retries) -              throws CancelledException, InterruptedException { -            throw new InterruptedException(); -          } -        }; +        PINGUI pinProvider = new InterruptPINProvider();          signatureCard.createSignature(new ByteArrayInputStream("MOCCA"              .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, @@ -247,13 +127,7 @@ public abstract class CardTest {          SignatureCard signatureCard = createSignatureCard(); -        PINProvider pinProvider = new PINProvider() { -          @Override -          public char[] providePIN(PINSpec spec, int retries) -              throws CancelledException, InterruptedException { -            throw new InterruptedException(); -          } -        }; +        PINGUI pinProvider = new InterruptPINProvider();          signatureCard.createSignature(new ByteArrayInputStream("MOCCA"              .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, @@ -268,11 +142,11 @@ public abstract class CardTest {          final SignatureCard signatureCard = createSignatureCard(); -        PINProvider pinProvider = new PINProvider() { +        PINGUI pinProvider = new DummyPINGUI() {            @Override            public char[] providePIN(PINSpec spec, int retries)                throws CancelledException, InterruptedException { -       +              try {                signatureCard.getCertificate(KeyboxName.SECURE_SIGNATURE_KEYPAIR);                assertTrue(false); @@ -281,10 +155,10 @@ public abstract class CardTest {                // expected                throw new CancelledException();              } -       +            }          }; -       +          signatureCard.createSignature(new ByteArrayInputStream("MOCCA"              .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR,              pinProvider, null); @@ -298,7 +172,7 @@ public abstract class CardTest {          final SignatureCard signatureCard = createSignatureCard(); -        PINProvider pinProvider = new PINProvider() { +        PINGUI pinProvider = new DummyPINGUI() {            @Override            public char[] providePIN(PINSpec spec, int retries)                throws CancelledException, InterruptedException { @@ -311,7 +185,6 @@ public abstract class CardTest {                // expected                throw new CancelledException();              } -                  }          }; @@ -339,13 +212,7 @@ public abstract class CardTest {          PINMgmtSignatureCard signatureCard = (PINMgmtSignatureCard) createSignatureCard(); -        PINProvider pinProvider = new PINProvider() { -          @Override -          public char[] providePIN(PINSpec spec, int retries) -              throws CancelledException, InterruptedException { -            throw new CancelledException(); -          } -        }; +        ModifyPINGUI pinProvider = new CancelChangePINProvider();          List<PINSpec> specs = signatureCard.getPINSpecs(); diff --git a/smcc/src/test/java/at/gv/egiz/smcc/PIN.java b/smcc/src/test/java/at/gv/egiz/smcc/PIN.java index ae883727..2cda0c2f 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/PIN.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/PIN.java @@ -23,19 +23,23 @@ public class PIN {    public static final int STATE_PIN_VERIFIED = 1;    public static final int STATE_PIN_BLOCKED = -1; + +  public static final int STATE_PIN_NOTACTIVE = 2;    public byte[] pin;    public int kid; -  public int state = STATE_RESET; +  public int state; // = STATE_RESET; -  public int kfpc = 10; +  public int kfpc; // = 10; -  public PIN(byte[] pin, int kid, int kfpc) { +  //TODO also provde default constructor without state param +  public PIN(byte[] pin, int kid, int kfpc, int state) {      this.pin = pin;      this.kid = kid;      this.kfpc = kfpc; +    this.state = state;    }  } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/acos/A03ApplDEC.java b/smcc/src/test/java/at/gv/egiz/smcc/acos/A03ApplDEC.java index 9fd96d73..f4ac5c35 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/acos/A03ApplDEC.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/acos/A03ApplDEC.java @@ -40,7 +40,7 @@ public class A03ApplDEC extends ACOSApplDEC {      putFile(new File(FID_EF_INFOBOX, EF_INFOBOX, FCI_EF_INFOBOX, KID_PIN_INF));      try { -      pins.put(KID_PIN_INF, new PIN("0000\0\0\0\0".getBytes("ASCII"), KID_PIN_INF, 10)); +      pins.put(KID_PIN_INF, new PIN("0000\0\0\0\0".getBytes("ASCII"), KID_PIN_INF, 10, PIN.STATE_RESET));      } catch (UnsupportedEncodingException e) {        throw new RuntimeException(e);      } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/acos/A03CardEmul.java b/smcc/src/test/java/at/gv/egiz/smcc/acos/A03CardEmul.java index 58216b6b..7394bae7 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/acos/A03CardEmul.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/acos/A03CardEmul.java @@ -24,13 +24,8 @@ import at.gv.egiz.smcc.CardEmul;  public class A03CardEmul extends ACOSCardEmul {    public A03CardEmul(A03ApplSIG applSIG, A03ApplDEC applDEC) { +    channel = new A03CardChannelEmul(this);      applications.add(applSIG);      applications.add(applDEC);    } - -  @Override -  protected CardChannelEmul newCardChannel(CardEmul cardEmul) { -    return new A03CardChannelEmul(this); -  } -  } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/acos/A03CardTest.java b/smcc/src/test/java/at/gv/egiz/smcc/acos/A03CardTest.java index 776c0370..3a8ac41c 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/acos/A03CardTest.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/acos/A03CardTest.java @@ -22,15 +22,16 @@ import java.util.Arrays;  import org.junit.Test; -import at.gv.egiz.smcc.ACOSCard;  import at.gv.egiz.smcc.CancelledException;  import at.gv.egiz.smcc.CardEmul;  import at.gv.egiz.smcc.CardNotSupportedException;  import at.gv.egiz.smcc.CardTerminalEmul; +import at.gv.egiz.smcc.pin.gui.ChangePINProvider;  import at.gv.egiz.smcc.LockedException;  import at.gv.egiz.smcc.NotActivatedException;  import at.gv.egiz.smcc.PINFormatException;  import at.gv.egiz.smcc.PINMgmtSignatureCard; +import at.gv.egiz.smcc.pin.gui.SMCCTestPINProvider;  import at.gv.egiz.smcc.PINSpec;  import at.gv.egiz.smcc.SignatureCard;  import at.gv.egiz.smcc.SignatureCardException; @@ -74,12 +75,12 @@ public class A03CardTest extends ACOSCardTest {        char[] pin = defaultPin;        for (int i = pinSpec.getMinLength(); i <= pinSpec.getMaxLength(); i++) { -        signatureCard.verifyPIN(pinSpec, new TestPINProvider(pin)); +        signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(pin));          char[] newPin = new char[i];          Arrays.fill(newPin, '0');          signatureCard -            .changePIN(pinSpec, new TestChangePINProvider(pin, newPin)); -        signatureCard.verifyPIN(pinSpec, new TestPINProvider(newPin)); +            .changePIN(pinSpec, new ChangePINProvider(pin, newPin)); +        signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(newPin));          pin = newPin;        } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/acos/A04CardEmul.java b/smcc/src/test/java/at/gv/egiz/smcc/acos/A04CardEmul.java index 70925aa6..dd44d05b 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/acos/A04CardEmul.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/acos/A04CardEmul.java @@ -24,14 +24,9 @@ import at.gv.egiz.smcc.CardEmul;  public class A04CardEmul extends ACOSCardEmul {    public A04CardEmul(A04ApplSIG applSIG, A04ApplDEC applDEC) { +    channel = new A04CardChannelEmul(this);      applications.add(applSIG);      applications.add(applDEC);    } - -  @Override -  protected CardChannelEmul newCardChannel(CardEmul cardEmul) { -    return new A04CardChannelEmul(this); -  } -  } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/acos/A04CardTest.java b/smcc/src/test/java/at/gv/egiz/smcc/acos/A04CardTest.java index d15e80d7..1cbea1b3 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/acos/A04CardTest.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/acos/A04CardTest.java @@ -28,7 +28,6 @@ import java.util.Arrays;  import org.junit.BeforeClass;  import org.junit.Test; -import at.gv.egiz.smcc.ACOSCard;  import at.gv.egiz.smcc.CancelledException;  import at.gv.egiz.smcc.CardEmul;  import at.gv.egiz.smcc.CardNotSupportedException; @@ -41,7 +40,8 @@ import at.gv.egiz.smcc.PINSpec;  import at.gv.egiz.smcc.SignatureCard;  import at.gv.egiz.smcc.SignatureCardException;  import at.gv.egiz.smcc.SignatureCardFactory; -import at.gv.egiz.smcc.CardTest.TestPINProvider; +import at.gv.egiz.smcc.pin.gui.ChangePINProvider; +import at.gv.egiz.smcc.pin.gui.SMCCTestPINProvider;  public class A04CardTest extends ACOSCardTest { @@ -88,8 +88,8 @@ public class A04CardTest extends ACOSCardTest {          char[] newPin = new char[i];          Arrays.fill(newPin, '0');          signatureCard -            .changePIN(pinSpec, new TestChangePINProvider(pin, newPin)); -        signatureCard.verifyPIN(pinSpec, new TestPINProvider(newPin)); +            .changePIN(pinSpec, new ChangePINProvider(pin, newPin)); +        signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(newPin));          pin = newPin;        } @@ -111,7 +111,7 @@ public class A04CardTest extends ACOSCardTest {      SignatureCard signatureCard = factory.createSignatureCard(card,          new CardTerminalEmul(card)); -    TestPINProvider pinProvider = new TestPINProvider(pin); +    SMCCTestPINProvider pinProvider = new SMCCTestPINProvider(pin);      byte[] idlink = signatureCard.getInfobox("IdentityLink",          pinProvider, null); @@ -129,7 +129,7 @@ public class A04CardTest extends ACOSCardTest {      SignatureCard signatureCard = createSignatureCard(); -    TestPINProvider pinProvider = new TestPINProvider(pin); +    SMCCTestPINProvider pinProvider = new SMCCTestPINProvider(pin);      byte[] idlink = signatureCard.getInfobox("IdentityLink",          pinProvider, null); diff --git a/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSApplDEC.java b/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSApplDEC.java index 08979536..09a754f3 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSApplDEC.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSApplDEC.java @@ -297,7 +297,7 @@ public abstract class ACOSApplDEC extends ACOSAppl {      System.arraycopy(C_CH_EKEY, 0, EF_C_CH_EKEY, 0, C_CH_EKEY.length);      putFile(new File(FID_EF_C_CH_EKEY, EF_C_CH_EKEY, FCI_EF_C_CH_EKEY));      try { -      pins.put(KID_PIN_DEC, new PIN("1234\0\0\0\0".getBytes("ASCII"), KID_PIN_DEC, 10)); +      pins.put(KID_PIN_DEC, new PIN("1234\0\0\0\0".getBytes("ASCII"), KID_PIN_DEC, 10, PIN.STATE_RESET));      } catch (UnsupportedEncodingException e) {        throw new RuntimeException(e);      } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSApplSIG.java b/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSApplSIG.java index e476b434..6ab5903a 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSApplSIG.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSApplSIG.java @@ -221,7 +221,7 @@ public abstract class ACOSApplSIG extends ACOSAppl {      // PINs      try { -      pins.put(KID_PIN_SIG, new PIN(Arrays.copyOf("123456".getBytes("ASCII"), 8), KID_PIN_SIG, 3)); +      pins.put(KID_PIN_SIG, new PIN(Arrays.copyOf("123456".getBytes("ASCII"), 8), KID_PIN_SIG, 3, PIN.STATE_RESET));      } catch (UnsupportedEncodingException e) {        throw new RuntimeException(e);      } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSCardTest.java b/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSCardTest.java index 56d1e4b2..4f012739 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSCardTest.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSCardTest.java @@ -16,26 +16,23 @@  */  package at.gv.egiz.smcc.acos; -import static org.junit.Assert.assertEquals;  import static org.junit.Assert.assertNotNull;  import static org.junit.Assert.assertNull;  import static org.junit.Assert.assertTrue;  import java.io.ByteArrayInputStream;  import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.security.MessageDigest;  import java.security.NoSuchAlgorithmException;  import java.util.Arrays;  import org.junit.Test; -import at.gv.egiz.smcc.ACOSCard;  import at.gv.egiz.smcc.CardEmul;  import at.gv.egiz.smcc.CardNotSupportedException;  import at.gv.egiz.smcc.CardTest;  import at.gv.egiz.smcc.LockedException;  import at.gv.egiz.smcc.NotActivatedException; +import at.gv.egiz.smcc.pin.gui.SMCCTestPINProvider;  import at.gv.egiz.smcc.SignatureCard;  import at.gv.egiz.smcc.SignatureCardException;  import at.gv.egiz.smcc.SignatureCard.KeyboxName; @@ -60,7 +57,7 @@ public abstract class ACOSCardTest extends CardTest {      appl.clearInfobox();      byte[] idlink = signatureCard.getInfobox("IdentityLink", -        new TestPINProvider(pin), null); +        new SMCCTestPINProvider(pin), null);      assertNull(idlink);    } @@ -76,7 +73,7 @@ public abstract class ACOSCardTest extends CardTest {      ACOSApplDEC appl = (ACOSApplDEC) card.getApplication(ACOSAppl.AID_DEC);      appl.setInfoboxHeader((byte) 0xFF); -    signatureCard.getInfobox("IdentityLink", new TestPINProvider(pin), null); +    signatureCard.getInfobox("IdentityLink", new SMCCTestPINProvider(pin), null);    } @@ -138,7 +135,7 @@ public abstract class ACOSCardTest extends CardTest {      byte[] signature = signatureCard.createSignature(new ByteArrayInputStream("MOCCA"          .getBytes("ASCII")), -        KeyboxName.SECURE_SIGNATURE_KEYPAIR, new TestPINProvider(pin), null); +        KeyboxName.SECURE_SIGNATURE_KEYPAIR, new SMCCTestPINProvider(pin), null);      assertNotNull(signature); @@ -158,7 +155,7 @@ public abstract class ACOSCardTest extends CardTest {      byte[] signature = signatureCard.createSignature(new ByteArrayInputStream("MOCCA"          .getBytes("ASCII")), -        KeyboxName.CERITIFIED_KEYPAIR, new TestPINProvider(pin), null); +        KeyboxName.CERITIFIED_KEYPAIR, new SMCCTestPINProvider(pin), null);      assertNotNull(signature); @@ -171,7 +168,7 @@ public abstract class ACOSCardTest extends CardTest {      SignatureCard signatureCard = createSignatureCard(); -    TestPINProvider pinProvider = new TestPINProvider("000000".toCharArray()); +    SMCCTestPINProvider pinProvider = new SMCCTestPINProvider("000000".toCharArray());      signatureCard.createSignature(new ByteArrayInputStream("MOCCA"          .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, @@ -186,7 +183,7 @@ public abstract class ACOSCardTest extends CardTest {      SignatureCard signatureCard = createSignatureCard(); -    TestPINProvider pinProvider = new TestPINProvider("0000".toCharArray()); +    SMCCTestPINProvider pinProvider = new SMCCTestPINProvider("0000".toCharArray());      signatureCard.createSignature(new ByteArrayInputStream("MOCCA"          .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, @@ -204,7 +201,7 @@ public abstract class ACOSCardTest extends CardTest {      ACOSApplSIG appl = (ACOSApplSIG) card.getApplication(ACOSAppl.AID_SIG);      appl.setPin(ACOSApplSIG.KID_PIN_SIG, null); -    TestPINProvider pinProvider = new TestPINProvider("000000".toCharArray()); +    SMCCTestPINProvider pinProvider = new SMCCTestPINProvider("000000".toCharArray());      signatureCard.createSignature(new ByteArrayInputStream("MOCCA"          .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, @@ -222,7 +219,7 @@ public abstract class ACOSCardTest extends CardTest {      ACOSApplDEC appl = (ACOSApplDEC) card.getApplication(ACOSAppl.AID_DEC);      appl.setPin(ACOSApplDEC.KID_PIN_DEC, null); -    TestPINProvider pinProvider = new TestPINProvider("0000".toCharArray()); +    SMCCTestPINProvider pinProvider = new SMCCTestPINProvider("0000".toCharArray());      signatureCard.createSignature(new ByteArrayInputStream("MOCCA"          .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/CancelChangePINProvider.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/CancelChangePINProvider.java new file mode 100644 index 00000000..dffe7e29 --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/CancelChangePINProvider.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.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; + +public class CancelChangePINProvider extends DummyChangePINGUI implements ModifyPINGUI { + +  public CancelChangePINProvider() { +  } + +  @Override +  public char[] provideCurrentPIN(PINSpec spec, int retries) +          throws CancelledException, InterruptedException { +    throw new CancelledException("cancelled by cancelPINProvider"); +  } + +  @Override +  public char[] provideNewPIN(PINSpec spec) +          throws CancelledException, InterruptedException { +    throw new CancelledException("cancelled by cancelPINProvider"); +  } + +}
\ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/CancelPINProvider.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/CancelPINProvider.java new file mode 100644 index 00000000..77f19345 --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/CancelPINProvider.java @@ -0,0 +1,29 @@ +/* + * 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.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; + +public class CancelPINProvider extends DummyPINGUI implements PINGUI { + +  @Override +  public char[] providePIN(PINSpec spec, int retries) +          throws CancelledException, InterruptedException { +    throw new CancelledException("cancelled by cancelPINProvider"); +  } +}
\ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/ChangePINProvider.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/ChangePINProvider.java new file mode 100644 index 00000000..5eb8b9a1 --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/ChangePINProvider.java @@ -0,0 +1,49 @@ +/* + * 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.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; + +public class ChangePINProvider extends DummyChangePINGUI implements ModifyPINGUI { + +  int provided = 0; +  char[] pin; +  char[] oldPin; + +  public ChangePINProvider(char[] oldPin, char[] pin) { +    this.pin = pin; +    this.oldPin = oldPin; +  } + +  public int getProvided() { +    return provided; +  } + +  @Override +  public char[] provideCurrentPIN(PINSpec spec, int retries) +          throws CancelledException, InterruptedException { +    provided++; +    return oldPin; +  } + +  @Override +  public char[] provideNewPIN(PINSpec spec) { +    return pin; +  } + +} diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/DummyChangePINGUI.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/DummyChangePINGUI.java new file mode 100644 index 00000000..fff89409 --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/DummyChangePINGUI.java @@ -0,0 +1,68 @@ +/* + * 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.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; + +public abstract class DummyChangePINGUI implements ModifyPINGUI { + +  @Override +  public void validKeyPressed() { +    throw new UnsupportedOperationException("Not supported yet."); +  } + +  @Override +  public void correctionButtonPressed() { +    throw new UnsupportedOperationException("Not supported yet."); +  } + +  @Override +  public void allKeysCleared() { +    throw new UnsupportedOperationException("Not supported yet."); +  } + +  @Override +  public void finish() { +    throw new UnsupportedOperationException("Not supported yet."); +  } + +  @Override +  public void finishDirect() { +    throw new UnsupportedOperationException("Not supported yet."); +  } + +  @Override +  public void modifyPINDirect(PINSpec spec, int retries) throws CancelledException, InterruptedException { +    throw new UnsupportedOperationException("Not supported yet."); +  } + +  @Override +  public void enterCurrentPIN(PINSpec spec, int retries) { +    throw new UnsupportedOperationException("Not supported yet."); +  } + +  @Override +  public void enterNewPIN(PINSpec spec) { +    throw new UnsupportedOperationException("Not supported yet."); +  } + +  @Override +  public void confirmNewPIN(PINSpec spec) { +    throw new UnsupportedOperationException("Not supported yet."); +  } +}
\ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/DummyPINGUI.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/DummyPINGUI.java new file mode 100644 index 00000000..4d99b5c1 --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/DummyPINGUI.java @@ -0,0 +1,48 @@ +/* + * 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.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; + +public abstract class DummyPINGUI implements PINGUI { + +   @Override +  public void enterPINDirect(PINSpec spec, int retries) throws CancelledException, InterruptedException { +    throw new UnsupportedOperationException("Not supported yet."); +  } + +  @Override +  public void enterPIN(PINSpec spec, int retries) throws CancelledException, InterruptedException { +    throw new UnsupportedOperationException("Not supported yet."); +  } + +  @Override +  public void validKeyPressed() { +    throw new UnsupportedOperationException("Not supported yet."); +  } + +  @Override +  public void correctionButtonPressed() { +    throw new UnsupportedOperationException("Not supported yet."); +  } + +  @Override +  public void allKeysCleared() { +    throw new UnsupportedOperationException("Not supported yet."); +  } +}
\ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InterruptPINProvider.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InterruptPINProvider.java new file mode 100644 index 00000000..5706b888 --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InterruptPINProvider.java @@ -0,0 +1,34 @@ +/* + * 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.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; + +@SuppressWarnings("restriction") +public class InterruptPINProvider extends DummyPINGUI implements PINGUI { + +  public InterruptPINProvider() { +  } + +  @Override +  public char[] providePIN(PINSpec spec, int retries) +          throws CancelledException, InterruptedException { +    throw new InterruptedException("interrupted by cancelPINProvider"); +  } + +}
\ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InvalidChangePINProvider.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InvalidChangePINProvider.java new file mode 100644 index 00000000..69c9f42a --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InvalidChangePINProvider.java @@ -0,0 +1,56 @@ +/* + * 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.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; + +public class InvalidChangePINProvider extends DummyChangePINGUI implements ModifyPINGUI { + +  int provided = 0; +  int numWrongTries = 0; +  char[] pin; +  char[] oldPin; + +  /** emulate ChangePinProvider */ +  public InvalidChangePINProvider(char[] oldPin, char[] newPin, int numWrongTries) { +    super(); +    this.pin = newPin; +    this.oldPin = oldPin; +    this.numWrongTries = numWrongTries; +  } + +  @Override +  public char[] provideCurrentPIN(PINSpec spec, int retries) +          throws CancelledException, InterruptedException { +    if (provided >= numWrongTries) { +      throw new CancelledException("Number of wrong tries reached: " + provided); +    } else { +      provided++; +      return oldPin; +    } +  } + +  public int getProvided() { +    return provided; +  } + +  @Override +  public char[] provideNewPIN(PINSpec spec) { +    return pin; +  } +} diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InvalidPINProvider.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InvalidPINProvider.java new file mode 100644 index 00000000..db01fd0d --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InvalidPINProvider.java @@ -0,0 +1,48 @@ +/* + * 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.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; + +public class InvalidPINProvider extends DummyPINGUI implements PINGUI { + +  int provided = 0; +  int numWrongTries = 0; +  char[] pin; + +  public InvalidPINProvider(char[] pin, int numWrongTries) { +    super(); +    this.pin = pin; +    this.numWrongTries = numWrongTries; +  } + +  @Override +  public char[] providePIN(PINSpec spec, int retries) +          throws CancelledException, InterruptedException { +    if (provided >= numWrongTries) { +      throw new CancelledException("Number of wrong tries reached: " + provided); +    } else { +      provided++; +      return pin; +    } +  } + +  public int getProvided() { +    return provided; +  } +} diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/SMCCTestPINProvider.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/SMCCTestPINProvider.java new file mode 100644 index 00000000..dffc90d7 --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/SMCCTestPINProvider.java @@ -0,0 +1,43 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package at.gv.egiz.smcc.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; + +public class SMCCTestPINProvider extends DummyPINGUI implements PINGUI { + +  public int provided = 0; +  char[] pin; + +  public SMCCTestPINProvider(char[] pin) { +    this.pin = pin; +  } + +  @Override +  public char[] providePIN(PINSpec spec, int retries) +          throws CancelledException, InterruptedException { +    provided++; +    return pin; +  } + +  public int getProvided() { +    return provided; +  } + +  +}
\ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSAppl.java b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSAppl.java index 2ca63eea..62528e6e 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSAppl.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSAppl.java @@ -69,27 +69,4 @@ public abstract class STARCOSAppl extends AbstractAppl implements CardAppl {        pin.next().state = PIN.STATE_RESET;      }    } -   -  public void setPin(int kid, char[] value) { -    PIN pin = pins.get(kid); -    if (pin != null) { -      if (value == null) { -        pin.pin = null; -      } else { -        byte[] b = new byte[8]; -        b[0] = (byte) (0x20 | value.length); -        for(int i = 1, j = 0; i < b.length; i++) { -          int h = ((j < value.length)  -                  ? Character.digit(value[j++], 10)  -                  : 0x0F); -          int l = ((j < value.length)  -                  ? Character.digit(value[j++], 10)  -                  : 0x0F); -          b[i] = (byte) ((h << 4) | l); -        } -        pin.pin = b; -      } -    } -  } -  } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSApplGewoehnlicheSignatur.java b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSApplGewoehnlicheSignatur.java index cec305da..8741dd2d 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSApplGewoehnlicheSignatur.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSApplGewoehnlicheSignatur.java @@ -16,7 +16,6 @@  */  package at.gv.egiz.smcc.starcos; -import java.io.UnsupportedEncodingException;  import java.util.Arrays;  import java.util.Random; @@ -200,12 +199,18 @@ public class STARCOSApplGewoehnlicheSignatur extends STARCOSAppl {    protected byte[] EF_C_X509_CH_AUT = new byte[2000]; -   -  public STARCOSApplGewoehnlicheSignatur(STARCOSCardChannelEmul channel) { + +  protected byte[] dst; + +  public static final byte[] DST = new byte[] { (byte) 0x84, (byte) 0x03, (byte) 0x80, (byte) 0x02, (byte) 0x00, (byte) 0x89, (byte) 0x03, (byte) 0x13, (byte) 0x35, (byte) 0x10}; +  public static final byte[] DST_G3 = new byte[] { (byte) 0x84, (byte) 0x03, (byte) 0x80, (byte) 0x02, (byte) 0x00, (byte) 0x80, (byte) 0x01, (byte) 0x04 }; + +  public STARCOSApplGewoehnlicheSignatur(STARCOSCardChannelEmul channel, byte[] dst) {      super(channel);      // Files      System.arraycopy(C_X509_CH_AUT, 0, EF_C_X509_CH_AUT, 0, C_X509_CH_AUT.length);      putFile(new File(FID_EF_C_X509_CH_AUT, EF_C_X509_CH_AUT, FCI_EF_C_X509_CH_AUT)); +    this.dst = dst;    }    @Override @@ -240,12 +245,19 @@ public class STARCOSApplGewoehnlicheSignatur extends STARCOSAppl {        case 0x81:          // EXTERNAL AUTHENTICATE        } +    case 0xAA: +      switch (command.getP1()) { +      case 0x41:  +        if (Arrays.equals(new byte[] {(byte) 0x80, (byte) 0x01, (byte) 0x10}, command.getData())) { +          return new ResponseAPDU(new byte[] {(byte) 0x90, (byte) 0x00}); +        } +      default: +        return new ResponseAPDU(new byte[] {(byte) 0x6A, (byte) 0x80}); +      }      case 0xB6:        switch (command.getP1()) {        case 0x41: {          // PSO - COMPUTE DIGITAL SIGNATURE -        byte[] dst = new byte[] { (byte) 0x84, (byte) 0x03, (byte) 0x80, -            (byte) 0x02, (byte) 0x00, (byte) 0x89, (byte) 0x03, (byte) 0x13, (byte) 0x35, (byte) 0x10};          if (Arrays.equals(dst, command.getData())) {            securityEnv = command.getData();            return new ResponseAPDU(new byte[] {(byte) 0x90, (byte) 0x00}); @@ -328,5 +340,10 @@ public class STARCOSApplGewoehnlicheSignatur extends STARCOSAppl {    } +  @Override +  public void setPin(int kid, char[] value) { +    throw new UnsupportedOperationException("Not supported yet."); +  } +  }
\ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSApplInfobox.java b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSApplInfobox.java index b7835a43..c470351a 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSApplInfobox.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSApplInfobox.java @@ -156,5 +156,10 @@ public class STARCOSApplInfobox extends STARCOSAppl {      throw new CardException("Not supported.");    } +  @Override +  public void setPin(int kid, char[] value) { +    throw new UnsupportedOperationException("Not supported yet."); +  } +  }
\ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSApplSichereSignatur.java b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSApplSichereSignatur.java index 9fb5ad37..4036ca41 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSApplSichereSignatur.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSApplSichereSignatur.java @@ -213,16 +213,14 @@ public class STARCOSApplSichereSignatur extends STARCOSAppl {    protected byte[] EF_C_X509_CH_DS = new byte[2000]; -  public STARCOSApplSichereSignatur(STARCOSCardChannelEmul channel) { +  public STARCOSApplSichereSignatur(STARCOSCardChannelEmul channel, byte[] SS_pin, int pinState) {      super(channel);      // Files      System.arraycopy(C_X509_CH_DS, 0, EF_C_X509_CH_DS, 0, C_X509_CH_DS.length);      putFile(new File(FID_EF_C_X509_CH_DS, EF_C_X509_CH_DS, FCI_EF_C_X509_CH_DS));      // PINs -    pins.put(KID_PIN_SS, new PIN(new byte[] { (byte) 0x24, (byte) 0x12, -        (byte) 0x34, (byte) 0x56, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, -        (byte) 0xFF }, KID_PIN_SS, 3)); +    pins.put(KID_PIN_SS, new PIN(SS_pin, KID_PIN_SS, 3, pinState));    }    @Override @@ -344,4 +342,34 @@ public class STARCOSApplSichereSignatur extends STARCOSAppl {    } +  /** +   * set and activate pin +   * @param value if null, pin will be set to NOTACTIVE +   */ +  @Override +  public void setPin(int kid, char[] value) { +    PIN pin = pins.get(kid); +    if (pin != null) { +      if (value == null) { +//        pin.pin = null; +        //TransportPIN +//        pin.pin = new byte[] { (byte) 0x26, (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}; +        pin.state = PIN.STATE_PIN_NOTACTIVE; +      } else { +        byte[] b = new byte[8]; +        b[0] = (byte) (0x20 | value.length); +        for(int i = 1, j = 0; i < b.length; i++) { +          int h = ((j < value.length) +                  ? Character.digit(value[j++], 10) +                  : 0x0F); +          int l = ((j < value.length) +                  ? Character.digit(value[j++], 10) +                  : 0x0F); +          b[i] = (byte) ((h << 4) | l); +        } +        pin.pin = b; +        pin.state = PIN.STATE_RESET; +      } +    } +  }  }
\ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardChannelEmul.java b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardChannelEmul.java index 89030894..2e0c54eb 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardChannelEmul.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardChannelEmul.java @@ -16,7 +16,6 @@  */  package at.gv.egiz.smcc.starcos; -import java.io.UnsupportedEncodingException;  import java.util.Arrays;  import java.util.HashMap; @@ -30,6 +29,8 @@ import at.gv.egiz.smcc.CardChannelEmul;  import at.gv.egiz.smcc.CardEmul;  import at.gv.egiz.smcc.File;  import at.gv.egiz.smcc.PIN; +import java.util.ArrayList; +import java.util.List;  @SuppressWarnings("restriction")  public class STARCOSCardChannelEmul extends CardChannelEmul { @@ -40,14 +41,13 @@ public class STARCOSCardChannelEmul extends CardChannelEmul {     *      */    protected CardEmul cardEmul; -   + +  public final List<File> globalFiles = new ArrayList<File>();    public final HashMap<Integer, PIN> globalPins = new HashMap<Integer, PIN>(); -  public STARCOSCardChannelEmul(CardEmul cardEmul) { +  public STARCOSCardChannelEmul(CardEmul cardEmul, byte[] Glob_PIN, int PIN_STATE) {      this.cardEmul = cardEmul; -    globalPins.put(KID_PIN_Glob, new PIN(new byte[] { (byte) 0x24, (byte) 0x00, -        (byte) 0x00, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, -        (byte) 0xFF }, KID_PIN_Glob, 10)); +    globalPins.put(KID_PIN_Glob, new PIN(Glob_PIN, KID_PIN_Glob, 10, PIN_STATE));   }    @Override @@ -88,6 +88,21 @@ public class STARCOSCardChannelEmul extends CardChannelEmul {            }          }          return new ResponseAPDU(new byte[] {(byte) 0x6A, (byte) 0x82}); +      } else if (globalFiles != null) { +        if (command.getP2() != 0x04) { +          throw new CardException("Not supported."); +        } +        for (File file : globalFiles) { +          if (Arrays.equals(fid, file.fid)) { +            currentFile = file; +            byte[] response = new byte[file.fcx.length + 2]; +            System.arraycopy(file.fcx, 0, response, 0, file.fcx.length); +            response[file.fcx.length] = (byte) 0x90; +            response[file.fcx.length + 1] = (byte) 0x00; +            return new ResponseAPDU(response); +          } +        } +        return new ResponseAPDU(new byte[] {(byte) 0x6A, (byte) 0x82});        } else {          throw new CardException("Not supported.");        } @@ -121,6 +136,23 @@ public class STARCOSCardChannelEmul extends CardChannelEmul {    } +  protected ResponseAPDU cmdREAD_RECORD(CommandAPDU command) throws CardException { +    if (command.getINS() != 0xB2) { +      throw new IllegalArgumentException("INS has to be 0xB2"); +    } +    if (currentFile == null) { +      return new ResponseAPDU(new byte[]{ (byte) 0x69, (byte) 0x86 }); +    } +    if (command.getP1() != 0x01 || command.getP2() != 0x04) { +      throw new CardException("Not implemented."); +    } +    byte[] response = new byte[currentFile.file.length + 2]; +    System.arraycopy(currentFile.file, 0, response, 0, currentFile.file.length); +    response[currentFile.file.length] = (byte) 0x90; +    response[currentFile.file.length + 1] = (byte) 0x00; +    return new ResponseAPDU(response); +  } +    protected ResponseAPDU cmdREAD_BINARY(CommandAPDU command) throws CardException {      if (command.getINS() != 0xB0) { @@ -192,6 +224,10 @@ public class STARCOSCardChannelEmul extends CardChannelEmul {        case 0xB0:          return cmdREAD_BINARY(command); +      // READ RECORD +      case 0xB2: +        return cmdREAD_RECORD(command); +        // VERIFY        case 0x20:          return cmdVERIFY(command); @@ -248,9 +284,15 @@ public class STARCOSCardChannelEmul extends CardChannelEmul {      }      if (pin != null) { -   -      if (reference.length == 0) { -        return new ResponseAPDU(new byte[] { (byte) 0x63, (byte) (pin.kfpc | 0xC0)}); + +      if (reference == null || reference.length == 0) { +        if (pin.state == PIN.STATE_PIN_NOTACTIVE) { +          return new ResponseAPDU(new byte[] { (byte) 0x69, (byte) 0x84 }); +        } else if (pin.state == PIN.STATE_PIN_BLOCKED) { +          return new ResponseAPDU(new byte[] { (byte) 0x63, (byte) 0xc0 }); +        } else { +          return new ResponseAPDU(new byte[] { (byte) 0x63, (byte) (pin.kfpc | 0xC0)}); +        }        }        if (reference.length != 8) { @@ -264,7 +306,7 @@ public class STARCOSCardChannelEmul extends CardChannelEmul {          case PIN.STATE_RESET:            pin.state = PIN.STATE_PIN_VERIFIED; -           +          default:            pin.kfpc = 10;            return new ResponseAPDU(new byte[] { (byte) 0x90, (byte) 0x00 }); @@ -321,7 +363,20 @@ public class STARCOSCardChannelEmul extends CardChannelEmul {          return new ResponseAPDU(new byte[] {(byte) 0x67, (byte) 0x00});        } -      response = verifyPin(0xFF & command.getP2(), data); +      PIN pin; +      if (currentAppl != null) { +        pin = currentAppl.pins.get(command.getP2()); +      } else { +        pin = globalPins.get(command.getP2()); +      } +      if (pin.state == PIN.STATE_PIN_NOTACTIVE) { +        pin.pin = data; +        pin.state = PIN.STATE_RESET; +        response = new ResponseAPDU(new byte[] { (byte) 0x90, (byte) 0x00 }); +      } else { +        // P1 == 0x01 not allowed on active pin (?) +        response = new ResponseAPDU(new byte[] { (byte) 0x6A, (byte) 0x86}); +      }      } else if (command.getP1() == 0x00) { @@ -330,21 +385,22 @@ public class STARCOSCardChannelEmul extends CardChannelEmul {        }        response = verifyPin(0xFF & command.getP2(), Arrays.copyOf(data, 8)); -     + +      if (response.getSW() == 0x9000) { +        PIN pin; +        if (currentAppl != null) { +          pin = currentAppl.pins.get(command.getP2()); +        } else { +          pin = globalPins.get(command.getP2()); +        } +        pin.pin = Arrays.copyOfRange(data, 8, 16); +        pin.state = PIN.STATE_PIN_VERIFIED; +      } +      } else {        return new ResponseAPDU(new byte[] { (byte) 0x6A, (byte) 0x81 });      } -    if (response.getSW() == 0x9000) { -      PIN pin; -      if (currentAppl != null) { -        pin = currentAppl.pins.get(command.getP2()); -      } else { -        pin = globalPins.get(command.getP2()); -      } -      pin.pin = Arrays.copyOfRange(data, 8, 16); -    } -      return response;    } @@ -353,7 +409,10 @@ public class STARCOSCardChannelEmul extends CardChannelEmul {      PIN pin = globalPins.get(kid);      if (pin != null) {        if (value == null) { -        pin.pin = null; +//        pin.pin = null; +        //TransportPIN +//        pin.pin = new byte[] { (byte) 0x24, (byte) 0x12, (byte) 0x34, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}; +        pin.state = PIN.STATE_PIN_NOTACTIVE;        } else {          byte[] b = new byte[8];          b[0] = (byte) (0x20 | value.length); diff --git a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardEmul.java b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardEmul.java index 7b2f3fbe..5963fb63 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardEmul.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardEmul.java @@ -21,30 +21,34 @@ import javax.smartcardio.ATR;  import at.gv.egiz.smcc.CardChannelEmul;  import at.gv.egiz.smcc.CardEmul; +import at.gv.egiz.smcc.PIN;  @SuppressWarnings("restriction")  public class STARCOSCardEmul extends CardEmul { -   + +  public static byte[] DEFAULT_SS_PIN = new byte[] { (byte) 0x26, (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}; +  public static byte[] DEFAULT_Glob_PIN = new byte[] { (byte) 0x24, (byte) 0x00, (byte) 0x00, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}; +    protected static ATR ATR = new ATR(new byte[] {        (byte) 0x3b, (byte) 0xbd, (byte) 0x18, (byte) 0x00, (byte) 0x81, (byte) 0x31, (byte) 0xfe, (byte) 0x45,         (byte) 0x80, (byte) 0x51, (byte) 0x02, (byte) 0x67, (byte) 0x05, (byte) 0x18, (byte) 0xb1, (byte) 0x02,         (byte) 0x02, (byte) 0x02, (byte) 0x01, (byte) 0x81, (byte) 0x05, (byte) 0x31    }); -   +    public STARCOSCardEmul() { -    applications.add(new STARCOSApplSichereSignatur((STARCOSCardChannelEmul) channel)); +    this(DEFAULT_SS_PIN, DEFAULT_Glob_PIN, PIN.STATE_RESET); +  } + +  public STARCOSCardEmul(byte[] SS_PIN, byte[] Glob_PIN, int PIN_STATE) { +    channel = new STARCOSCardChannelEmul(this, Glob_PIN, PIN_STATE); +    applications.add(new STARCOSApplSichereSignatur((STARCOSCardChannelEmul) channel, SS_PIN, PIN_STATE));      applications.add(new STARCOSApplInfobox((STARCOSCardChannelEmul) channel)); -    applications.add(new STARCOSApplGewoehnlicheSignatur((STARCOSCardChannelEmul) channel)); +    applications.add(new STARCOSApplGewoehnlicheSignatur((STARCOSCardChannelEmul) channel, +            STARCOSApplGewoehnlicheSignatur.DST));    }    @Override    public ATR getATR() {      return ATR;    } - -  @Override -  protected CardChannelEmul newCardChannel(CardEmul cardEmul) { -    return new STARCOSCardChannelEmul(this); -  } -  }
\ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardTest.java b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardTest.java index b7dc9a0c..154884d4 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardTest.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardTest.java @@ -22,12 +22,9 @@ import static org.junit.Assert.assertTrue;  import java.io.ByteArrayInputStream;  import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.security.MessageDigest;  import java.security.NoSuchAlgorithmException;  import java.util.Arrays; -import javax.smartcardio.CardChannel;  import org.junit.Test; @@ -36,25 +33,20 @@ import at.gv.egiz.smcc.CardEmul;  import at.gv.egiz.smcc.CardNotSupportedException;  import at.gv.egiz.smcc.CardTerminalEmul;  import at.gv.egiz.smcc.CardTest; +import at.gv.egiz.smcc.pin.gui.ChangePINProvider; +import at.gv.egiz.smcc.pin.gui.InvalidChangePINProvider; +import at.gv.egiz.smcc.pin.gui.InvalidPINProvider;  import at.gv.egiz.smcc.LockedException;  import at.gv.egiz.smcc.NotActivatedException; +import at.gv.egiz.smcc.PIN;  import at.gv.egiz.smcc.PINFormatException;  import at.gv.egiz.smcc.PINMgmtSignatureCard;  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.SignatureCardFactory; -import at.gv.egiz.smcc.CardTest.TestChangePINProvider; -import at.gv.egiz.smcc.CardTest.TestPINProvider; -import at.gv.egiz.smcc.PINProvider; +import at.gv.egiz.smcc.pin.gui.SMCCTestPINProvider;  import at.gv.egiz.smcc.SignatureCard.KeyboxName; -import at.gv.egiz.smcc.acos.A03ApplDEC; -import at.gv.egiz.smcc.acos.A04ApplDEC; -import at.gv.egiz.smcc.acos.A04ApplSIG; -import at.gv.egiz.smcc.acos.ACOSAppl; -import at.gv.egiz.smcc.acos.ACOSApplDEC; -import at.gv.egiz.smcc.acos.ACOSApplSIG;  import org.junit.Ignore;  public class STARCOSCardTest extends CardTest { @@ -69,7 +61,17 @@ public class STARCOSCardTest extends CardTest {      assertTrue(signatureCard instanceof PINMgmtSignatureCard);      return signatureCard;    } -   + +  protected SignatureCard createSignatureCard(byte[] SS_PIN, byte[] Glob_PIN, int pinState) +      throws CardNotSupportedException { +    SignatureCardFactory factory = SignatureCardFactory.getInstance(); +    STARCOSCardEmul card = new STARCOSCardEmul(SS_PIN, Glob_PIN, pinState); +    SignatureCard signatureCard = factory.createSignatureCard(card, +        new CardTerminalEmul(card)); +    assertTrue(signatureCard instanceof PINMgmtSignatureCard); +    return signatureCard; +  } +    @Test    public void testGetInfoboxIdentityLinkEmpty() throws SignatureCardException,        InterruptedException, CardNotSupportedException { @@ -82,7 +84,7 @@ public class STARCOSCardTest extends CardTest {      appl.clearInfobox();      byte[] idlink = signatureCard.getInfobox("IdentityLink", -        new TestPINProvider(pin), null); +        new SMCCTestPINProvider(pin), null);      assertNull(idlink);    } @@ -98,10 +100,10 @@ public class STARCOSCardTest extends CardTest {      STARCOSApplInfobox appl = (STARCOSApplInfobox) card.getApplication(STARCOSAppl.AID_Infobox);      appl.setInfoboxHeader((byte) 0xFF); -    signatureCard.getInfobox("IdentityLink", new TestPINProvider(pin), null); +    signatureCard.getInfobox("IdentityLink", new SMCCTestPINProvider(pin), null);    } -  +    @Test    public void testGetCerts() throws SignatureCardException,        InterruptedException, CardNotSupportedException { @@ -145,7 +147,7 @@ public class STARCOSCardTest extends CardTest {      signatureCard.getCertificate(KeyboxName.CERITIFIED_KEYPAIR);    } -   +    @Test    public void testSignSichereSignatur() throws SignatureCardException,        InterruptedException, CardNotSupportedException, @@ -160,7 +162,7 @@ public class STARCOSCardTest extends CardTest {      byte[] signature = signatureCard.createSignature(new ByteArrayInputStream("MOCCA"          .getBytes("ASCII")), -        KeyboxName.SECURE_SIGNATURE_KEYPAIR, new TestPINProvider(pin), null); +        KeyboxName.SECURE_SIGNATURE_KEYPAIR, new SMCCTestPINProvider(pin), null);      assertNotNull(signature); @@ -180,12 +182,12 @@ public class STARCOSCardTest extends CardTest {      byte[] signature = signatureCard.createSignature(new ByteArrayInputStream("MOCCA"          .getBytes("ASCII")), -        KeyboxName.CERITIFIED_KEYPAIR, new TestPINProvider(pin), null); +        KeyboxName.CERITIFIED_KEYPAIR, new SMCCTestPINProvider(pin), null);      assertNotNull(signature);    } -   +    @Test(expected = LockedException.class)    public void testSignSichereSignaturInvalidPin() throws SignatureCardException,        InterruptedException, CardNotSupportedException, @@ -193,7 +195,7 @@ public class STARCOSCardTest extends CardTest {      SignatureCard signatureCard = createSignatureCard(); -    TestPINProvider pinProvider = new TestPINProvider("000000".toCharArray()); +    SMCCTestPINProvider pinProvider = new SMCCTestPINProvider("000000".toCharArray());      signatureCard.createSignature(new ByteArrayInputStream("MOCCA"          .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, @@ -208,7 +210,7 @@ public class STARCOSCardTest extends CardTest {      SignatureCard signatureCard = createSignatureCard(); -    TestPINProvider pinProvider = new TestPINProvider("1234".toCharArray()); +    SMCCTestPINProvider pinProvider = new SMCCTestPINProvider("1234".toCharArray());      signatureCard.createSignature(new ByteArrayInputStream("MOCCA"          .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, @@ -221,12 +223,9 @@ public class STARCOSCardTest extends CardTest {        InterruptedException, CardNotSupportedException,        NoSuchAlgorithmException, IOException { -    SignatureCard signatureCard = createSignatureCard(); -    CardEmul card = (CardEmul) signatureCard.getCard(); -    STARCOSApplSichereSignatur appl = (STARCOSApplSichereSignatur) card.getApplication(STARCOSApplSichereSignatur.AID_SichereSignatur); -    appl.setPin(STARCOSApplSichereSignatur.KID_PIN_SS, null); +    SignatureCard signatureCard = createSignatureCard(null, null, PIN.STATE_PIN_BLOCKED); -    TestPINProvider pinProvider = new TestPINProvider("000000".toCharArray()); +    SMCCTestPINProvider pinProvider = new SMCCTestPINProvider("000000".toCharArray());      assertTrue(pinProvider.getProvided() <= 0);      signatureCard.createSignature(new ByteArrayInputStream("MOCCA" @@ -240,68 +239,79 @@ public class STARCOSCardTest extends CardTest {        InterruptedException, CardNotSupportedException,        NoSuchAlgorithmException, IOException { -    SignatureCard signatureCard = createSignatureCard(); -    CardEmul card = (CardEmul) signatureCard.getCard(); -    STARCOSCardChannelEmul channel = (STARCOSCardChannelEmul) card.getBasicChannel(); -    channel.setPin(STARCOSCardChannelEmul.KID_PIN_Glob, null); - -    TestPINProvider pinProvider = new TestPINProvider("0000".toCharArray()); +    SignatureCard signatureCard = createSignatureCard(null, null, PIN.STATE_PIN_BLOCKED); +     +    SMCCTestPINProvider pinProvider = new SMCCTestPINProvider("0000".toCharArray());      signatureCard.createSignature(new ByteArrayInputStream("MOCCA"          .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR,          pinProvider, null);    } -   +    @Test    public void testChangePin() throws CardNotSupportedException,        LockedException, NotActivatedException, CancelledException,        PINFormatException, SignatureCardException, InterruptedException { -    char[] defaultPin = "123456".toCharArray(); - -    PINMgmtSignatureCard signatureCard = (PINMgmtSignatureCard) createSignatureCard(); -    CardEmul card = (CardEmul) signatureCard.getCard(); -    STARCOSCardChannelEmul channel = (STARCOSCardChannelEmul) card.getBasicChannel(); -    channel.setPin(STARCOSCardChannelEmul.KID_PIN_Glob, defaultPin); -    STARCOSApplSichereSignatur appl = (STARCOSApplSichereSignatur) card.getApplication(STARCOSApplSichereSignatur.AID_SichereSignatur); -    appl.setPin(STARCOSApplSichereSignatur.KID_PIN_SS, defaultPin); +    // set all initial pins to DEFAULT_SS_PIN (123456) +    PINMgmtSignatureCard signatureCard = (PINMgmtSignatureCard) createSignatureCard( +            STARCOSCardEmul.DEFAULT_SS_PIN, STARCOSCardEmul.DEFAULT_SS_PIN, PIN.STATE_RESET);      for (PINSpec pinSpec : signatureCard.getPINSpecs()) { -      char[] pin = defaultPin; +      char[] pin = "123456".toCharArray();        for (int i = pinSpec.getMinLength(); i <= pinSpec.getMaxLength(); i++) { -        signatureCard.verifyPIN(pinSpec, new TestPINProvider(pin)); +        signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(pin));          char[] newPin = new char[i];          Arrays.fill(newPin, '0');          signatureCard -            .changePIN(pinSpec, new TestChangePINProvider(pin, newPin)); -        signatureCard.verifyPIN(pinSpec, new TestPINProvider(newPin)); +            .changePIN(pinSpec, new ChangePINProvider(pin, newPin)); +        signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(newPin));          pin = newPin;        }      }    }    @Test -  public void testVerifyInvalidPin() throws CardNotSupportedException, +  @Override +  public void testActivatePin() throws CardNotSupportedException,        LockedException, NotActivatedException, CancelledException,        PINFormatException, SignatureCardException, InterruptedException { -    char[] defaultPin = "123456".toCharArray(); +    PINMgmtSignatureCard signatureCard = (PINMgmtSignatureCard) createSignatureCard( +            null, null, PIN.STATE_PIN_NOTACTIVE); + +    for (PINSpec pinSpec : signatureCard.getPINSpecs()) { + +      char[] pin = "1234567890".substring(0, pinSpec.getMinLength()).toCharArray(); + +      boolean notActive = false; +      try { +        signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(pin)); +      } catch (NotActivatedException ex) { +        notActive = true; +      } +      assertTrue(notActive); + +      signatureCard.activatePIN(pinSpec, new ChangePINProvider(null, pin)); +      signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(pin)); +    } +  } + +  @Test +  public void testVerifyInvalidPin() throws CardNotSupportedException, +      LockedException, NotActivatedException, CancelledException, +      PINFormatException, SignatureCardException, InterruptedException {      PINMgmtSignatureCard signatureCard = (PINMgmtSignatureCard) createSignatureCard(); -    CardEmul card = (CardEmul) signatureCard.getCard(); -    STARCOSCardChannelEmul channel = (STARCOSCardChannelEmul) card.getBasicChannel(); -    channel.setPin(STARCOSCardChannelEmul.KID_PIN_Glob, defaultPin); -    STARCOSApplSichereSignatur appl = (STARCOSApplSichereSignatur) card.getApplication(STARCOSApplSichereSignatur.AID_SichereSignatur); -    appl.setPin(STARCOSApplSichereSignatur.KID_PIN_SS, defaultPin);      for (PINSpec pinSpec : signatureCard.getPINSpecs()) {        char[] invalidPin = "999999".toCharArray();        int numInvalidTries = 2; -      TestInvalidPINProvider invalidPinProvider = new TestInvalidPINProvider(invalidPin, numInvalidTries); +      InvalidPINProvider invalidPinProvider = new InvalidPINProvider(invalidPin, numInvalidTries);        try {          signatureCard.verifyPIN(pinSpec, invalidPinProvider);        } catch (CancelledException ex) { @@ -315,21 +325,15 @@ public class STARCOSCardTest extends CardTest {    public void testChangeInvalidPin() throws CardNotSupportedException,        LockedException, NotActivatedException, CancelledException,        PINFormatException, SignatureCardException, InterruptedException { -    char[] defaultPin = "123456".toCharArray();      PINMgmtSignatureCard signatureCard = (PINMgmtSignatureCard) createSignatureCard(); -    CardEmul card = (CardEmul) signatureCard.getCard(); -    STARCOSCardChannelEmul channel = (STARCOSCardChannelEmul) card.getBasicChannel(); -    channel.setPin(STARCOSCardChannelEmul.KID_PIN_Glob, defaultPin); -    STARCOSApplSichereSignatur appl = (STARCOSApplSichereSignatur) card.getApplication(STARCOSApplSichereSignatur.AID_SichereSignatur); -    appl.setPin(STARCOSApplSichereSignatur.KID_PIN_SS, defaultPin); - +          for (PINSpec pinSpec : signatureCard.getPINSpecs()) {        char[] invalidPin = "999999".toCharArray();        int numInvalidTries = 2; -      TestInvalidChangePINProvider invalidPinProvider = -              new TestInvalidChangePINProvider(invalidPin, defaultPin, numInvalidTries); +      InvalidChangePINProvider invalidPinProvider = +              new InvalidChangePINProvider(invalidPin, invalidPin, numInvalidTries);        try {          signatureCard.changePIN(pinSpec, invalidPinProvider); diff --git a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSG3CardChannelEmul.java b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSG3CardChannelEmul.java new file mode 100644 index 00000000..dc6836ae --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSG3CardChannelEmul.java @@ -0,0 +1,46 @@ +/* + * 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.starcos; + +import at.gv.egiz.smcc.CardEmul; +import at.gv.egiz.smcc.File; +import at.gv.egiz.smcc.PIN; + +/** + * + * @author clemens + */ +public class STARCOSG3CardChannelEmul extends STARCOSCardChannelEmul { + +  public STARCOSG3CardChannelEmul(CardEmul cardEmul, byte[] Glob_PIN, int PIN_STATE) { +    super(cardEmul, Glob_PIN, PIN_STATE); + +    // G3 version file +    byte[] versionFileFID = new byte[]{(byte) 0x00, (byte) 0x32}; +    byte[] versionFile = new byte[]{ +      (byte) 0xa5, (byte) 0x0e, (byte) 0x53, (byte) 0x02, (byte) 0x01, (byte) 0x20, (byte) 0x54, (byte) 0x08, +      (byte) 0x01, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x04, (byte) 0x01, (byte) 0x70, (byte) 0x01}; +    byte[] versionFileFCX = new byte[]{ +      (byte) 0x62, (byte) 0x1a, (byte) 0x80, (byte) 0x02, (byte) 0x00, (byte) 0x14, (byte) 0x82, (byte) 0x05, +      (byte) 0x44, (byte) 0x41, (byte) 0x00, (byte) 0x14, (byte) 0x01, (byte) 0x83, (byte) 0x02, (byte) 0x00, +      (byte) 0x32, (byte) 0x88, (byte) 0x01, (byte) 0xd8, (byte) 0x8a, (byte) 0x01, (byte) 0x05, (byte) 0xa1, +      (byte) 0x03, (byte) 0x8b, (byte) 0x01, (byte) 0x03}; + +    globalFiles.add(new File(versionFileFID, versionFile, versionFileFCX)); + +  } + } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSG3CardEmul.java b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSG3CardEmul.java new file mode 100644 index 00000000..7583b3ad --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSG3CardEmul.java @@ -0,0 +1,57 @@ +/* + * 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.starcos; + +import at.gv.egiz.smcc.CardEmul; +import javax.smartcardio.ATR; + +import at.gv.egiz.smcc.PIN; + +@SuppressWarnings("restriction") +public class STARCOSG3CardEmul extends CardEmul { + +  public static byte[] TRANSPORT_SS_PIN = new byte[] { (byte) 0x26, (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}; +  public static byte[] TRANSPORT_Glob_PIN = new byte[] { (byte) 0x24, (byte) 0x12, (byte) 0x34, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}; + +  public static byte[] DEFAULT_SS_PIN = TRANSPORT_SS_PIN; +  public static byte[] DEFAULT_Glob_PIN = new byte[] { (byte) 0x24, (byte) 0x00, (byte) 0x00, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}; + +  protected static ATR ATR = new ATR(new byte[] { +      (byte) 0x3b, (byte) 0xbd, (byte) 0x18, (byte) 0x00, (byte) 0x81, (byte) 0x31, (byte) 0xfe, (byte) 0x45, +      (byte) 0x80, (byte) 0x51, (byte) 0x02, (byte) 0x67, (byte) 0x05, (byte) 0x18, (byte) 0xb1, (byte) 0x02, +      (byte) 0x02, (byte) 0x02, (byte) 0x01, (byte) 0x81, (byte) 0x05, (byte) 0x31 +  }); + +  public STARCOSG3CardEmul(byte[] SS_PIN, byte[] Glob_PIN, int PIN_STATE){ +    channel = new STARCOSG3CardChannelEmul(this, Glob_PIN, PIN_STATE); +    applications.add(new STARCOSApplSichereSignatur((STARCOSCardChannelEmul) channel, +            SS_PIN, PIN_STATE)); +    applications.add(new STARCOSApplInfobox((STARCOSCardChannelEmul) channel)); +    applications.add(new STARCOSApplGewoehnlicheSignatur((STARCOSCardChannelEmul) channel, +            STARCOSApplGewoehnlicheSignatur.DST_G3)); +  } + + +  public STARCOSG3CardEmul() { +    this(DEFAULT_SS_PIN, DEFAULT_Glob_PIN, PIN.STATE_RESET); +  } + +  @Override +  public ATR getATR() { +    return ATR; +  } +} diff --git a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSG3CardTest.java b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSG3CardTest.java new file mode 100644 index 00000000..06744c82 --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSG3CardTest.java @@ -0,0 +1,119 @@ +/* +* 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.starcos; + +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; + + +import org.junit.Test; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.CardEmul; +import at.gv.egiz.smcc.CardNotSupportedException; +import at.gv.egiz.smcc.CardTerminalEmul; +import at.gv.egiz.smcc.CardTest; +import at.gv.egiz.smcc.pin.gui.ChangePINProvider; +import at.gv.egiz.smcc.LockedException; +import at.gv.egiz.smcc.NotActivatedException; +import at.gv.egiz.smcc.PIN; +import at.gv.egiz.smcc.PINFormatException; +import at.gv.egiz.smcc.PINMgmtSignatureCard; +import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.SignatureCard; +import at.gv.egiz.smcc.SignatureCardException; +import at.gv.egiz.smcc.SignatureCardFactory; +import at.gv.egiz.smcc.pin.gui.SMCCTestPINProvider; +import org.junit.Ignore; + +public class STARCOSG3CardTest extends CardTest { + +  @Override +  protected SignatureCard createSignatureCard() +      throws CardNotSupportedException { +    SignatureCardFactory factory = SignatureCardFactory.getInstance(); +    STARCOSG3CardEmul card = new STARCOSG3CardEmul(); +    SignatureCard signatureCard = factory.createSignatureCard(card, +        new CardTerminalEmul(card)); +    assertTrue(signatureCard instanceof PINMgmtSignatureCard); +    return signatureCard; +  } + +  protected SignatureCard createSignatureCard(byte[] SS_PIN, byte[] Glob_PIN, int pinState) +      throws CardNotSupportedException { +    SignatureCardFactory factory = SignatureCardFactory.getInstance(); +    STARCOSG3CardEmul card = new STARCOSG3CardEmul(SS_PIN, Glob_PIN, pinState); +    SignatureCard signatureCard = factory.createSignatureCard(card, +        new CardTerminalEmul(card)); +    assertTrue(signatureCard instanceof PINMgmtSignatureCard); +    return signatureCard; +  } + +  @Test +  public void testChangePin() throws CardNotSupportedException, +      LockedException, NotActivatedException, CancelledException, +      PINFormatException, SignatureCardException, InterruptedException { + +    PINMgmtSignatureCard signatureCard = (PINMgmtSignatureCard) createSignatureCard( +            STARCOSG3CardEmul.DEFAULT_SS_PIN, STARCOSG3CardEmul.DEFAULT_SS_PIN, PIN.STATE_RESET); +     +    for (PINSpec pinSpec : signatureCard.getPINSpecs()) { + +      char[] pin = "123456".toCharArray(); + +      for (int i = pinSpec.getMinLength(); i <= pinSpec.getMaxLength(); i++) { +        signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(pin)); +        char[] newPin = new char[i]; +        Arrays.fill(newPin, '0'); +        signatureCard +            .changePIN(pinSpec, new ChangePINProvider(pin, newPin)); +        signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(newPin)); +        pin = newPin; +      } +    } +  } + +  @Test +  @Override +  public void testActivatePin() throws CardNotSupportedException, +      LockedException, NotActivatedException, CancelledException, +      PINFormatException, SignatureCardException, InterruptedException { + +    PINMgmtSignatureCard signatureCard = (PINMgmtSignatureCard) createSignatureCard( +            STARCOSG3CardEmul.TRANSPORT_SS_PIN, STARCOSG3CardEmul.TRANSPORT_SS_PIN, PIN.STATE_PIN_NOTACTIVE); +     +    for (PINSpec pinSpec : signatureCard.getPINSpecs()) { + +      char[] pin = "123456789".substring(0, pinSpec.getMinLength()).toCharArray(); +      char[] transportPIN = "123456".toCharArray(); + +      boolean notActive = false; +      try { +        signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(pin)); +      } catch (NotActivatedException ex) { +        notActive = true; +      } +      assertTrue(notActive); + +      signatureCard.activatePIN(pinSpec, new ChangePINProvider(transportPIN, pin)); +      signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(pin)); +    } +  } + +   +} diff --git a/smccSTAL/src/main/java/META-INF/MANIFEST.MF b/smccSTAL/src/main/java/META-INF/MANIFEST.MF deleted file mode 100644 index 5e949512..00000000 --- a/smccSTAL/src/main/java/META-INF/MANIFEST.MF +++ /dev/null @@ -1,3 +0,0 @@ -Manifest-Version: 1.0
 -Class-Path: 
 -
 diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractPINProvider.java b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/AbstractPINProvider.java index bc52c955..00738188 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractPINProvider.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/AbstractPINProvider.java @@ -15,32 +15,25 @@   * limitations under the License.   */ -package at.gv.egiz.bku.smccstal; +package at.gv.egiz.bku.pin.gui; -import at.gv.egiz.smcc.PINProvider; +import at.gv.egiz.smcc.pin.gui.PINProvider;  import java.awt.event.ActionEvent;  import java.awt.event.ActionListener;  import org.apache.commons.logging.Log;  import org.apache.commons.logging.LogFactory;  /** - * + * common super class providing action listener for all PIN GUIs   * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>   */ -public abstract class AbstractPINProvider implements PINProvider, ActionListener { +public abstract class AbstractPINProvider implements ActionListener {    protected static final Log log = LogFactory.getLog(AbstractPINProvider.class); -  protected boolean retry = false; -    protected String action; -    protected boolean actionPerformed; -//  protected void waitForAction() throws InterruptedException { -//    super.wait(); -//  } -    protected synchronized void waitForAction() throws InterruptedException {      try {        while (!actionPerformed) { diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/SignPINGUI.java b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/SignPINGUI.java new file mode 100644 index 00000000..81db0e90 --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/SignPINGUI.java @@ -0,0 +1,136 @@ +/* + * 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.pin.gui; + +import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.bku.smccstal.SecureViewer; +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.pin.gui.PINGUI; +import at.gv.egiz.stal.signedinfo.SignedInfoType; +import java.security.DigestException; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * 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 class SignPINGUI extends SignPINProvider implements PINGUI { + +  protected static final Log log = LogFactory.getLog(SignPINGUI.class); + +  private boolean retry = false; + +  public SignPINGUI(BKUGUIFacade gui, SecureViewer viewer, SignedInfoType signedInfo) { +    super(gui, viewer, signedInfo); +  } + +  @Override +  public void enterPINDirect(PINSpec spec, int retries) +          throws CancelledException, InterruptedException { +    if (retry) { +      gui.showEnterPINDirect(spec, retries); +    } else { +      showSignatureData(spec); +      gui.showEnterPINDirect(spec, -1); +      retry = true; +    } +  } + +  @Override +  public void enterPIN(PINSpec spec, int retries) +          throws CancelledException, InterruptedException { +    if (retry) { +      gui.showEnterPIN(spec, retries); +    } else { +      showSignatureData(spec); +      gui.showEnterPIN(spec, -1); +      retry = true; +    } +  } + +  private void showSignatureData(PINSpec spec) +          throws CancelledException, InterruptedException { + +    gui.showSignatureDataDialog(spec, +            this, "enterPIN", +            this, "cancel", +            this, "secureViewer"); + +    do { +      log.trace("[" + Thread.currentThread().getName() + "] wait for action"); +      waitForAction(); +      log.trace("[" + Thread.currentThread().getName() + "] received action " + action); + +      if ("secureViewer".equals(action)) { +        try { +          viewer.displayDataToBeSigned(signedInfo, this, "signatureData"); +        } 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 ("signatureData".equals(action)) { +        gui.showSignatureDataDialog(spec, +                this, "enterPIN", +                this, "cancel", +                this, "secureViewer"); +      } else if ("enterPIN".equals(action)) { +        return; +      } else if ("cancel".equals(action) || +              "error".equals(action)) { +        gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, +                BKUGUIFacade.MESSAGE_WAIT); +        throw new CancelledException(spec.getLocalizedName() + +                " entry cancelled"); +      } else { +        log.error("unknown action command " + action); +      } +    } while (true); +  } + +  @Override +  public void validKeyPressed() { +    gui.validKeyPressed(); +  } + +  @Override +  public void correctionButtonPressed() { +    gui.correctionButtonPressed(); +  } + +  @Override +  public void allKeysCleared() { +    gui.allKeysCleared(); +  } + +} diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/SignPINProvider.java b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/SignPINProvider.java new file mode 100644 index 00000000..fc1d39af --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/SignPINProvider.java @@ -0,0 +1,105 @@ +/* + * 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.pin.gui; + +import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.bku.smccstal.SecureViewer; +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.pin.gui.PINProvider; +import at.gv.egiz.stal.signedinfo.SignedInfoType; +import java.security.DigestException; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * 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 class SignPINProvider extends AbstractPINProvider implements PINProvider { + +  protected static final Log log = LogFactory.getLog(SignPINProvider.class); + +  protected BKUGUIFacade gui; +  protected SecureViewer viewer; +  protected SignedInfoType signedInfo; +  private boolean retry = false; + +  public SignPINProvider(BKUGUIFacade gui, SecureViewer viewer, SignedInfoType signedInfo) { +    this.gui = gui; +    this.viewer = viewer; +    this.signedInfo = signedInfo; +  } + +  @Override +  public char[] providePIN(PINSpec spec, int retries) +          throws CancelledException, InterruptedException { + +    gui.showSignaturePINDialog(spec, (retry) ? retries : -1, +            this, "sign", +            this, "cancel", +            this, "secureViewer"); + +    do { +      log.trace("[" + Thread.currentThread().getName() + "] wait for action"); +      waitForAction(); +      log.trace("[" + Thread.currentThread().getName() + "] received action " + action); + +      if ("secureViewer".equals(action)) { +        try { +          viewer.displayDataToBeSigned(signedInfo, this, "pinEntry"); +        } catch (DigestException ex) { +          log.error("Bad digest value: " + ex.getMessage()); +          gui.showErrorDialog(BKUGUIFacade.ERR_INVALID_HASH, +                  new Object[]{ex.getMessage()}, +                  this, "error"); +        } catch (Exception ex) { +          log.error("Could not display hashdata inputs: " + +                  ex.getMessage()); +          gui.showErrorDialog(BKUGUIFacade.ERR_DISPLAY_HASHDATA, +                  new Object[]{ex.getMessage()}, +                  this, "error"); +        } +      } else if ("sign".equals(action)) { +        gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, +                BKUGUIFacade.MESSAGE_WAIT); +        retry = true; +        return gui.getPin(); +      } else if ("pinEntry".equals(action)) { +        gui.showSignaturePINDialog(spec, (retry) ? retries : -1, +                this, "sign", +                this, "cancel", +                this, "secureViewer"); +      } else if ("cancel".equals(action) || +              "error".equals(action)) { +        gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, +                BKUGUIFacade.MESSAGE_WAIT); +        throw new CancelledException(spec.getLocalizedName() + +                " entry cancelled"); +      } else { +        log.error("unknown action command " + action); +      } +    } while (true); +  } +} diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/VerifyPINGUI.java b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/VerifyPINGUI.java new file mode 100644 index 00000000..dc21492e --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/VerifyPINGUI.java @@ -0,0 +1,76 @@ +/* + * 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.pin.gui; + +import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.pin.gui.PINGUI; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * 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 class VerifyPINGUI extends VerifyPINProvider implements PINGUI { + +  protected static final Log log = LogFactory.getLog(VerifyPINGUI.class); + +  private boolean retry = false; + +  public VerifyPINGUI(BKUGUIFacade gui) { +    super(gui); +  } + +  @Override +  public void enterPINDirect(PINSpec spec, int retries) +          throws CancelledException, InterruptedException {     +    gui.showEnterPINDirect(spec, (retry) ? retries : -1); +    retry = true; +  } + +  @Override +  public void enterPIN(PINSpec spec, int retries) { +    gui.showEnterPIN(spec, (retry) ? retries : -1); +    retry = true; +  } + + +  @Override +  public void validKeyPressed() { +    gui.validKeyPressed(); +  } + +  @Override +  public void correctionButtonPressed() { +    gui.correctionButtonPressed(); +  } + +  @Override +  public void allKeysCleared() { +    gui.allKeysCleared(); +  } + +} diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/VerifyPINProvider.java b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/VerifyPINProvider.java new file mode 100644 index 00000000..fda1e402 --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/VerifyPINProvider.java @@ -0,0 +1,72 @@ +/* + * 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.pin.gui; + +import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.pin.gui.PINProvider; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * 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 class VerifyPINProvider extends AbstractPINProvider implements PINProvider { + +  protected static final Log log = LogFactory.getLog(VerifyPINProvider.class); + +  protected BKUGUIFacade gui; +  private boolean retry = false; + +  public VerifyPINProvider(BKUGUIFacade gui) { +    this.gui = gui; +  } + +  @Override +  public char[] providePIN(PINSpec spec, int retries) +          throws CancelledException, InterruptedException { + +    gui.showVerifyPINDialog(spec, (retry) ? retries : -1, +            this, "verify", +            this, "cancel"); + +    log.trace("[" + Thread.currentThread().getName() + "] wait for action"); +    waitForAction(); +    log.trace("[" + Thread.currentThread().getName() + "] received action " + action); + +    if ("cancel".equals(action)) { +      gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, +              BKUGUIFacade.MESSAGE_WAIT); +      throw new CancelledException(spec.getLocalizedName() + +              " entry cancelled"); +    } +     +    gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, +            BKUGUIFacade.MESSAGE_WAIT); +    retry = true; +    return gui.getPin(); +  } +} 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 32e990c5..b34ab862 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 @@ -17,14 +17,13 @@  package at.gv.egiz.bku.smccstal;  import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.bku.pin.gui.VerifyPINGUI;  import org.apache.commons.logging.Log;  import org.apache.commons.logging.LogFactory;  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.stal.ErrorResponse; @@ -49,8 +48,7 @@ public class InfoBoxReadRequestHandler extends AbstractRequestHandler {            newSTALMessage("Message.RequestCaption", "Message.IdentityLink");            log.debug("Handling identitylink infobox");            byte[] resp = card.getInfobox(infoBox.getInfoboxIdentifier(), -                  new PINProviderFactory(card.getReader(), gui) -                  .getCardPINProvider(), +                  new VerifyPINGUI(gui),                    infoBox.getDomainIdentifier());            if (resp == null) {              log.info("Infobox doesn't contain any data. Assume card is not activated."); @@ -97,8 +95,7 @@ public class InfoBoxReadRequestHandler extends AbstractRequestHandler {            log.warn("Unknown infobox identifier: "                + infoBox.getInfoboxIdentifier() + " trying generic request");            byte[] resp = card.getInfobox(infoBox.getInfoboxIdentifier(), -                  new PINProviderFactory(card.getReader(), gui) -                  .getCardPINProvider(), +                  new VerifyPINGUI(gui),                    infoBox.getDomainIdentifier());            if (resp == null) {              return new ErrorResponse(6001); diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/PINProviderFactory.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/PINProviderFactory.java deleted file mode 100644 index e5afe0ae..00000000 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/PINProviderFactory.java +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Copyright 2008 Federal Chancellery Austria and - * Graz University of Technology - *  - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *  - *     http://www.apache.org/licenses/LICENSE-2.0 - *  - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package at.gv.egiz.bku.smccstal; - -import at.gv.egiz.bku.gui.BKUGUIFacade; -import at.gv.egiz.smcc.CancelledException; -import at.gv.egiz.smcc.ccid.CCID; -import at.gv.egiz.smcc.PINProvider; -import at.gv.egiz.smcc.PINSpec; -import at.gv.egiz.stal.signedinfo.SignedInfoType; -import java.security.DigestException; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * don't reuse the instance if the card reader might have changed! - * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at> - */ -public class PINProviderFactory { - -  protected static final Log log = LogFactory.getLog(PINProviderFactory.class); - -  protected CCID reader; -  protected BKUGUIFacade gui; - -  /** -   * don't reuse the instance if the card reader might have changed! -   * @param reader -   * @param gui -   */ -  public PINProviderFactory(CCID reader, BKUGUIFacade gui) { -    log.trace("PINProviderFactory for " + reader.getName()); -    this.reader = reader; -    this.gui = gui; -  } - - -   -//  public static PINProviderFactory getInstance(SignatureCard forCard, -//          BKUGUIFacade gui) { -//    if (forCard.getReader().hasFeature(CCID.FEATURE_VERIFY_PIN_DIRECT) || -//            forCard.getReader().hasFeature(CCID.FEATURE_VERIFY_PIN_DIRECT)) { -//      return new PinpadPINProviderFactory(gui); -//    } else { -//      return new SoftwarePINProviderFactory(gui); -//    } -//  } - -  /** -   * don't reuse the instance if the card reader might have changed! -   * @param reader -   * @param gui -   * @return -   */ -//  public static PINProviderFactory getInstance(CCID reader, BKUGUIFacade gui) { -//    log.trace("PINProviderFactory for " + reader.getName()); -//    return new PINProviderFactory(reader, gui); -//  } - -  public PINProvider getSignaturePINProvider(SecureViewer viewer, -          SignedInfoType signedInfo) { -    if (reader.hasFeature(CCID.FEATURE_VERIFY_PIN_START) || -            reader.hasFeature(CCID.FEATURE_VERIFY_PIN_DIRECT)) { -      log.debug("pinpad signature-pin provider"); -      return new PinpadSignaturePinProvider(viewer, signedInfo); -    } else { -      log.debug("software signature-pin provider"); -      return new SoftwareSignaturePinProvider(viewer, signedInfo); -    } -  } - -  public PINProvider getCardPINProvider() { -    if (reader.hasFeature(CCID.FEATURE_VERIFY_PIN_START) || -            reader.hasFeature(CCID.FEATURE_VERIFY_PIN_DIRECT)) { -      log.debug("pinpad card-pin provider"); -      return new PinpadCardPinProvider(); -    } else { -      log.debug("software card-pin provider"); -      return new SoftwareCardPinProvider(); -    } -  } - -  class SoftwareSignaturePinProvider extends AbstractPINProvider { - -    protected SecureViewer viewer; -    protected SignedInfoType signedInfo; - -    private SoftwareSignaturePinProvider(SecureViewer viewer, -            SignedInfoType signedInfo) { -      this.viewer = viewer; -      this.signedInfo = signedInfo; -    } - -    @Override -    public char[] providePIN(PINSpec spec, int retries) -            throws CancelledException, InterruptedException { - -      gui.showSignaturePINDialog(spec, (retry) ? retries : -1, -              this, "sign", -              this, "cancel", -              this, "secureViewer"); - -      do { -        log.debug("[" + Thread.currentThread().getName() + "] wait for action"); -        waitForAction(); -        log.debug("[" + Thread.currentThread().getName() + "] received action"); - -        if ("secureViewer".equals(action)) { -          try { -            viewer.displayDataToBeSigned(signedInfo, this, "pinEntry"); -          } catch (DigestException ex) { -            log.error("Bad digest value: " + ex.getMessage()); -            gui.showErrorDialog(BKUGUIFacade.ERR_INVALID_HASH, -                    new Object[]{ex.getMessage()}, -                    this, "error"); -          } catch (Exception ex) { -            log.error("Could not display hashdata inputs: " + -                    ex.getMessage()); -            gui.showErrorDialog(BKUGUIFacade.ERR_DISPLAY_HASHDATA, -                    new Object[]{ex.getMessage()}, -                    this, "error"); -          } -        } else if ("sign".equals(action)) { -          gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, -                BKUGUIFacade.MESSAGE_WAIT); -          retry = true; -          return gui.getPin(); -        } else if ("pinEntry".equals(action)) { -          gui.showSignaturePINDialog(spec, (retry) ? retries : -1, -                  this, "sign", -                  this, "cancel", -                  this, "secureViewer"); -        } else if ("cancel".equals(action) || -                "error".equals(action)) { -          gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, -                BKUGUIFacade.MESSAGE_WAIT); -          throw new CancelledException(spec.getLocalizedName() + -                  " entry cancelled"); -        } else { -          log.error("unknown action command " + action); -        } -      } while (true); -    } -  } - -  class SoftwareCardPinProvider extends AbstractPINProvider { - -    private SoftwareCardPinProvider() { -    } - -    @Override -    public char[] providePIN(PINSpec spec, int retries) -            throws CancelledException, InterruptedException { - -      gui.showCardPINDialog(spec, (retry) ? retries : -1, -              this, "ok", -              this, "cancel"); - -      log.debug("[" + Thread.currentThread().getName() + "] wait for action"); -      waitForAction(); - -      gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, -              BKUGUIFacade.MESSAGE_WAIT); - -      if ("cancel".equals(action)) { -        throw new CancelledException(spec.getLocalizedName() + -                  " entry cancelled"); -      } -      retry = true; -      return gui.getPin(); -    } -  } - -    class PinpadSignaturePinProvider extends AbstractPINProvider { - -//    protected BKUGUIFacade gui; -    protected SecureViewer viewer; -    protected ViewerThread viewerThread; -    protected SignedInfoType signedInfo; - - -    private PinpadSignaturePinProvider(SecureViewer viewer, -            SignedInfoType signedInfo) { -      this.viewer = viewer; -      this.signedInfo = signedInfo; -    } - -    protected class ViewerThread extends Thread { - -      PINSpec pinSpec; -      int retries; - -      public ViewerThread(PINSpec pinSpec, int retries) { -        this.pinSpec = pinSpec; -        this.retries = retries; -      } - -      @Override -      public void run() { - -        try { - -          gui.showPinpadSignaturePINDialog(pinSpec, retries, -              PinpadSignaturePinProvider.this, "secureViewer"); - -          while (true) { -            log.debug("[" + Thread.currentThread().getName() + "] wait for action"); -            waitForAction(); -            log.debug("[" + Thread.currentThread().getName() + "] received action"); - -            if ("secureViewer".equals(action)) { -              viewer.displayDataToBeSigned(signedInfo, -                      PinpadSignaturePinProvider.this, "pinEntry"); -            } else if ("pinEntry".equals(action)) { -              gui.showPinpadSignaturePINDialog(pinSpec, retries, -                      PinpadSignaturePinProvider.this, "secureViewer"); -            } else { -              log.error("unsupported action command: " + action); -            } -          } - -        } catch (DigestException ex) { -          log.error("Bad digest value: " + ex.getMessage()); -          gui.showErrorDialog(BKUGUIFacade.ERR_INVALID_HASH, -                  new Object[]{ex.getMessage()}); -        } catch (InterruptedException ex) { -          log.info("pinpad secure viewer thread interrupted"); -        } catch (Exception ex) { -          log.error("Could not display hashdata inputs: " + -                  ex.getMessage()); -          gui.showErrorDialog(BKUGUIFacade.ERR_DISPLAY_HASHDATA, -                  new Object[]{ex.getMessage()}); -        } -      } -    } - -    @Override -    public char[] providePIN(PINSpec spec, int retries) -            throws CancelledException, InterruptedException { - -      if (viewerThread != null) { -        updateViewerThread(retries); -      } else { -        viewerThread = new ViewerThread(spec, -1); -        viewerThread.start(); -      } -//      if (viewerThread != null) { -//        log.trace("interrupt old secure viewer thread"); -//        viewerThread.interrupt(); -//      } -//      viewerThread = new ViewerThread(spec, (retry) ? retries : -1); -//      log.trace("start new secure viewer thread"); -//      viewerThread.start(); - -      retry = true; -      return null; -    } - -    private synchronized void updateViewerThread(int retries) { -      log.trace("update viewer thread"); -      viewerThread.retries = retries; -      action = "pinEntry"; -      actionPerformed = true; -      notify(); -    } - - -//    @Override -//    protected void finalize() throws Throwable { -//      if (viewerThread != null) { -//        viewerThread.interrupt(); -//      } -//      log.info("finalizing Pinpad SignaturePinProvider"); -//      super.finalize(); -//    } -  } - -  class PinpadCardPinProvider extends AbstractPINProvider { - -    private PinpadCardPinProvider() { -    } - -    @Override -    public char[] providePIN(PINSpec spec, int retries) -            throws CancelledException, InterruptedException { - -      showPinpadPINDialog(retries, spec); -      retry = true; -      return null; - -    } - -    private void showPinpadPINDialog(int retries, PINSpec pinSpec) { -      String title, message; -      Object[] params; -      if (retry) { -        title = BKUGUIFacade.TITLE_RETRY; -        message = BKUGUIFacade.MESSAGE_RETRIES; -        params = new Object[]{String.valueOf(retries)}; -      } else { -        title = BKUGUIFacade.TITLE_CARDPIN; -        message = BKUGUIFacade.MESSAGE_ENTERPIN_PINPAD; -        String pinSize = String.valueOf(pinSpec.getMinLength()); -        if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { -          pinSize += "-" + pinSpec.getMaxLength(); -        } -        params = new Object[]{pinSpec.getLocalizedName(), pinSize}; -      } -      gui.showMessageDialog(title, message, params); -    } -  } -} diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java index 58d7b305..5b436d16 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,6 +17,7 @@  package at.gv.egiz.bku.smccstal;  import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.bku.pin.gui.SignPINGUI;  import java.io.ByteArrayInputStream;  import java.io.IOException;  import java.io.InputStream; @@ -78,8 +79,7 @@ public class SignRequestHandler extends AbstractRequestHandler {                  KeyboxName kb = SignatureCard.KeyboxName.getKeyboxName(signReq.getKeyIdentifier());                  byte[] resp = card.createSignature(new ByteArrayInputStream(signReq.getSignedInfo()), kb, -                        new PINProviderFactory(card.getReader(), gui) -                        .getSignaturePINProvider(secureViewer, si.getValue()), signatureMethod); +                        new SignPINGUI(gui, secureViewer, si.getValue()), signatureMethod);                  if (resp == null) {                      return new ErrorResponse(6001);                  } 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 16d3efa9..bf57b0a6 100644 --- a/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java +++ b/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java @@ -16,7 +16,7 @@ import org.junit.Test;  import at.gv.egiz.bku.gui.BKUGUIFacade;
  import at.gv.egiz.bku.smccstal.AbstractSMCCSTAL;
  import at.gv.egiz.bku.smccstal.SMCCSTALRequestHandler;
 -import at.gv.egiz.smcc.ccid.CCID;
 +import at.gv.egiz.smcc.pin.gui.PINGUI;
  import at.gv.egiz.stal.ErrorResponse;
  import at.gv.egiz.stal.InfoboxReadRequest;
  import at.gv.egiz.stal.InfoboxReadResponse;
 @@ -39,7 +39,7 @@ public class AbstractSMCCSTALTest extends AbstractSMCCSTAL implements      @Override
      public byte[] createSignature(InputStream input, KeyboxName keyboxName,
 -        PINProvider provider, String alg) throws SignatureCardException {
 +        PINGUI provider, String alg) throws SignatureCardException {
        // TODO Auto-generated method stub
        return null;
      }
 @@ -58,7 +58,7 @@ public class AbstractSMCCSTALTest extends AbstractSMCCSTAL implements      }
      @Override
 -    public byte[] getInfobox(String infobox, PINProvider provider,
 +    public byte[] getInfobox(String infobox, PINGUI provider,
          String domainId) throws SignatureCardException {
        // TODO Auto-generated method stub
        return null;
 @@ -87,13 +87,6 @@ public class AbstractSMCCSTALTest extends AbstractSMCCSTAL implements        // TODO Auto-generated method stub
      }
 -
 -    @Override
 -    public CCID getReader() {
 -      // TODO Auto-generated method stub
 -      return null;
 -    }
 -
     };
      return false;
    }
 diff --git a/smccSTALExt/src/main/java/at/gv/egiz/bku/pin/gui/ManagementPINGUI.java b/smccSTALExt/src/main/java/at/gv/egiz/bku/pin/gui/ManagementPINGUI.java new file mode 100644 index 00000000..26a24609 --- /dev/null +++ b/smccSTALExt/src/main/java/at/gv/egiz/bku/pin/gui/ManagementPINGUI.java @@ -0,0 +1,88 @@ +/* + * 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.pin.gui; + +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.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.pin.gui.ModifyPINGUI; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +public class ManagementPINGUI extends ManagementPINProvider implements ModifyPINGUI { + +  protected static final Log log = LogFactory.getLog(ManagementPINGUI.class); + +  private boolean retry = false; + +  public ManagementPINGUI(PINManagementGUIFacade gui, DIALOG type) { +    super(gui, type); +  } + +  @Override +  public void modifyPINDirect(PINSpec spec, int retries) +          throws CancelledException, InterruptedException {     +    gui.showModifyPINDirect(type, spec, (retry) ? retries : -1); +    retry = true; +  } + +  @Override +  public void finishDirect() { +    gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, BKUGUIFacade.MESSAGE_WAIT); +  } + +  @Override +  public void enterCurrentPIN(PINSpec spec, int retries) { +    gui.showEnterCurrentPIN(type, spec, (retry) ? retries : -1); +    retry = true; +  } + +  @Override +  public void enterNewPIN(PINSpec spec) { +    gui.showEnterNewPIN(type, spec); +    retry = true; +  } + +  @Override +  public void confirmNewPIN(PINSpec spec) { +    gui.showConfirmNewPIN(type, spec); +    retry = true; +  } + + +  @Override +  public void validKeyPressed() { +    gui.validKeyPressed(); +  } + +  @Override +  public void correctionButtonPressed() { +    gui.correctionButtonPressed(); +  } + +  @Override +  public void allKeysCleared() { +    gui.allKeysCleared(); +  } + +  @Override +  public void finish() { +    gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, BKUGUIFacade.MESSAGE_WAIT); +  } +} diff --git a/smccSTALExt/src/main/java/at/gv/egiz/bku/pin/gui/ManagementPINProvider.java b/smccSTALExt/src/main/java/at/gv/egiz/bku/pin/gui/ManagementPINProvider.java new file mode 100644 index 00000000..8d842d13 --- /dev/null +++ b/smccSTALExt/src/main/java/at/gv/egiz/bku/pin/gui/ManagementPINProvider.java @@ -0,0 +1,89 @@ +/* + * 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.pin.gui; + +import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.bku.gui.PINManagementGUIFacade; +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.pin.gui.ModifyPINProvider; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +public class ManagementPINProvider extends AbstractPINProvider implements ModifyPINProvider { + +  protected static final Log log = LogFactory.getLog(ManagementPINProvider.class); +  protected PINManagementGUIFacade gui; +  protected PINManagementGUIFacade.DIALOG type; +  private boolean retry = false; + +  public ManagementPINProvider(PINManagementGUIFacade gui, PINManagementGUIFacade.DIALOG type) { +    this.gui = gui; +    this.type = type; +  } + +  @Override +  public char[] provideCurrentPIN(PINSpec spec, int retries) +          throws CancelledException, InterruptedException { + +    gui.showPINDialog(type, spec, (retry) ? retries : -1, +            this, "change", +            this, "cancel"); + +    log.trace("[" + Thread.currentThread().getName() + "] wait for action"); +    waitForAction(); +    log.trace("[" + Thread.currentThread().getName() + "] received action " + action); + +    gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, +            BKUGUIFacade.MESSAGE_WAIT); + +    if ("cancel".equals(action)) { +      throw new CancelledException(spec.getLocalizedName() + +              " entry cancelled"); +    } +    retry = true; +    return gui.getOldPin(); +  } + +  @Override +  public char[] provideNewPIN(PINSpec spec) +          throws CancelledException, InterruptedException { +     +    char[] pin = gui.getPin(); +    if (pin != null) { +      // change pin dialog also returns new pin +      return pin; +    } + +    gui.showPINDialog(type, spec, -1, +            this, "activate", +            this, "cancel"); + +    log.trace("[" + Thread.currentThread().getName() + "] wait for action"); +    waitForAction(); +    log.trace("[" + Thread.currentThread().getName() + "] received action " + action); + +    gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, +              BKUGUIFacade.MESSAGE_WAIT); + +    if ("cancel".equals(action)) { +      throw new CancelledException(spec.getLocalizedName() + +              " entry cancelled"); +    } +    return gui.getPin(); +  } +} diff --git a/smccSTALExt/src/main/java/at/gv/egiz/bku/smccstal/ManagementPINProviderFactory.java b/smccSTALExt/src/main/java/at/gv/egiz/bku/smccstal/ManagementPINProviderFactory.java deleted file mode 100644 index 493733b8..00000000 --- a/smccSTALExt/src/main/java/at/gv/egiz/bku/smccstal/ManagementPINProviderFactory.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright 2008 Federal Chancellery Austria and - * Graz University of Technology - *  - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *  - *     http://www.apache.org/licenses/LICENSE-2.0 - *  - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package at.gv.egiz.bku.smccstal; - -import at.gv.egiz.bku.gui.BKUGUIFacade; -import at.gv.egiz.smcc.ChangePINProvider; -import at.gv.egiz.bku.gui.PINManagementGUIFacade; -import at.gv.egiz.bku.smccstal.AbstractPINProvider; -import at.gv.egiz.bku.smccstal.PINProviderFactory; -import at.gv.egiz.smcc.CancelledException; -import at.gv.egiz.smcc.ccid.CCID; -import at.gv.egiz.smcc.PINProvider; -import at.gv.egiz.smcc.PINSpec; -import at.gv.egiz.smcc.SignatureCard; - -/** - * - * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at> - */ -public class ManagementPINProviderFactory extends PINProviderFactory { - -  public ManagementPINProviderFactory(CCID reader, PINManagementGUIFacade gui) { -    super(reader, gui); -  } -   -//  public static ManagementPINProviderFactory getInstance(SignatureCard forCard, -//          PINManagementGUIFacade gui) { -//    if (forCard.getReader().hasFeature(CCID.FEATURE_VERIFY_PIN_DIRECT)) { -//      return new PinpadPINProviderFactory(gui); -// -//    } else { -//      return new SoftwarePINProviderFactory(gui); -//    } -//  } - -  public PINProvider getVerifyPINProvider() { -    if (reader.hasFeature(CCID.FEATURE_VERIFY_PIN_START)) { -      return new PinpadGenericPinProvider(PINManagementGUIFacade.DIALOG.VERIFY); -    } else if (reader.hasFeature(CCID.FEATURE_VERIFY_PIN_DIRECT)) { -      return new PinpadGenericPinProvider(PINManagementGUIFacade.DIALOG.VERIFY); -    } else { -      return new SoftwareGenericPinProvider(PINManagementGUIFacade.DIALOG.VERIFY); -    } -  } - -  public PINProvider getActivatePINProvider() { -    if (reader.hasFeature(CCID.FEATURE_MODIFY_PIN_START)) { -      return new PinpadGenericPinProvider(PINManagementGUIFacade.DIALOG.ACTIVATE); -    } else if (reader.hasFeature(CCID.FEATURE_MODIFY_PIN_DIRECT)) { -      return new PinpadGenericPinProvider(PINManagementGUIFacade.DIALOG.ACTIVATE); -    } else { -      return new SoftwareGenericPinProvider(PINManagementGUIFacade.DIALOG.ACTIVATE); -    } -  } - -  public ChangePINProvider getChangePINProvider() { -    if (reader.hasFeature(CCID.FEATURE_MODIFY_PIN_START)) { -      return new PinpadGenericPinProvider(PINManagementGUIFacade.DIALOG.CHANGE); -    } else if (reader.hasFeature(CCID.FEATURE_MODIFY_PIN_DIRECT)) { -      return new PinpadGenericPinProvider(PINManagementGUIFacade.DIALOG.CHANGE); -    } else { -      return new ChangePinProvider(); -    } -  } - -  public PINProvider getUnblockPINProvider() { -    if (reader.hasFeature(CCID.FEATURE_VERIFY_PIN_START)) { -      return new PinpadGenericPinProvider(PINManagementGUIFacade.DIALOG.UNBLOCK); -    } else if (reader.hasFeature(CCID.FEATURE_VERIFY_PIN_DIRECT)) { -      return new PinpadGenericPinProvider(PINManagementGUIFacade.DIALOG.UNBLOCK); -    } else { -      return new SoftwareGenericPinProvider(PINManagementGUIFacade.DIALOG.UNBLOCK); -    } -  } - -  class PinpadGenericPinProvider extends AbstractPINProvider -          implements ChangePINProvider { - -    protected PINManagementGUIFacade.DIALOG type; - -    private PinpadGenericPinProvider(PINManagementGUIFacade.DIALOG type) { -      this.type = type; -    } - -    @Override -    public char[] providePIN(PINSpec spec, int retries) -            throws CancelledException, InterruptedException { - -      showPinpadPINDialog(retries, spec); -      retry = true; -      return null; -    } - -    /** -     * do not call this method without calling providePIN() -     * (no message is displayed) -     * @param spec -     * @param retries -     * @return -     */ -    @Override -    public char[] provideOldPIN(PINSpec spec, int retries) { -      return null; -    } - -    private void showPinpadPINDialog(int retries, PINSpec pinSpec) { -      String title, message; -      Object[] params; -      if (retry) { -        if (retries == 1) { -          message = BKUGUIFacade.MESSAGE_LAST_RETRY_PINPAD; -        } else { -          message = BKUGUIFacade.MESSAGE_RETRIES_PINPAD; -        } -        title = BKUGUIFacade.TITLE_RETRY; -        params = new Object[]{String.valueOf(retries)}; -      } else if (type == PINManagementGUIFacade.DIALOG.VERIFY) { -        title = PINManagementGUIFacade.TITLE_VERIFY_PIN; -        message = BKUGUIFacade.MESSAGE_ENTERPIN_PINPAD; -        params = new Object[]{pinSpec.getLocalizedName(), pinSpec.getLocalizedLength()}; -      } else if (type == PINManagementGUIFacade.DIALOG.ACTIVATE) { -        title = PINManagementGUIFacade.TITLE_ACTIVATE_PIN; -        message = PINManagementGUIFacade.MESSAGE_ACTIVATEPIN_PINPAD; -        params = new Object[]{pinSpec.getLocalizedName(), pinSpec.getLocalizedLength()}; -      } else if (type == PINManagementGUIFacade.DIALOG.CHANGE) { -        title = PINManagementGUIFacade.TITLE_CHANGE_PIN; -        message = PINManagementGUIFacade.MESSAGE_CHANGEPIN_PINPAD; -        params = new Object[]{pinSpec.getLocalizedName(), pinSpec.getLocalizedLength()}; -      } else { //if (type == DIALOG.UNBLOCK) { -        title = PINManagementGUIFacade.TITLE_UNBLOCK_PIN; -        message = PINManagementGUIFacade.MESSAGE_UNBLOCKPIN_PINPAD; -        params = new Object[]{pinSpec.getLocalizedName(), pinSpec.getLocalizedLength()}; -      } -      gui.showMessageDialog(title, message, params); -    } -  } - - -  class SoftwareGenericPinProvider extends AbstractPINProvider { - -//    protected PINManagementGUIFacade gui; -    protected PINManagementGUIFacade.DIALOG type; - -    private SoftwareGenericPinProvider(PINManagementGUIFacade.DIALOG type) { -      this.type = type; -    } - -    @Override -    public char[] providePIN(PINSpec spec, int retries) -            throws CancelledException, InterruptedException { - -      ((PINManagementGUIFacade) gui).showPINDialog(type, spec, -              (retry) ? retries : -1, -              this, "exec", -              this, "back"); - -      waitForAction(); - -      if ("exec".equals(action)) { -        gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, -                BKUGUIFacade.MESSAGE_WAIT); -        retry = true; -        return gui.getPin(); -      } else if ("back".equals(action)) { -        throw new CancelledException(); -      } else { -        log.error("unsupported command " + action); -        throw new CancelledException(); -      } -    } -  } - -  class ChangePinProvider extends AbstractPINProvider -          implements ChangePINProvider { - -//    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 { - -      ((PINManagementGUIFacade) gui).showPINDialog( -              PINManagementGUIFacade.DIALOG.CHANGE, spec, -              (retry) ? retries : -1, -              this, "exec", -              this, "back"); - -      waitForAction(); - -      if ("exec".equals(action)) { -        gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, -                BKUGUIFacade.MESSAGE_WAIT); -        retry = true; -        oldPin = ((PINManagementGUIFacade) gui).getOldPin(); -        newPin = gui.getPin(); -      } else if ("back".equals(action)) { -        throw new CancelledException(); -      } else { -        log.error("unsupported command " + action); -        throw new CancelledException(); -      } -    } -  } -} diff --git a/smccSTALExt/src/main/java/at/gv/egiz/bku/smccstal/PINManagementRequestHandler.java b/smccSTALExt/src/main/java/at/gv/egiz/bku/smccstal/PINManagementRequestHandler.java index bfeb90b0..0d49afd0 100644 --- a/smccSTALExt/src/main/java/at/gv/egiz/bku/smccstal/PINManagementRequestHandler.java +++ b/smccSTALExt/src/main/java/at/gv/egiz/bku/smccstal/PINManagementRequestHandler.java @@ -23,9 +23,11 @@ import org.apache.commons.logging.Log;  import org.apache.commons.logging.LogFactory;  import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.bku.gui.PINManagementGUI;  import at.gv.egiz.bku.gui.PINManagementGUIFacade;  import at.gv.egiz.bku.gui.PINManagementGUIFacade.STATUS; -import at.gv.egiz.bku.smccstal.AbstractRequestHandler; +import at.gv.egiz.bku.pin.gui.ManagementPINGUI; +import at.gv.egiz.bku.pin.gui.VerifyPINGUI;  import at.gv.egiz.smcc.CancelledException;  import at.gv.egiz.smcc.LockedException;  import at.gv.egiz.smcc.NotActivatedException; @@ -96,40 +98,15 @@ public class PINManagementRequestHandler extends AbstractRequestHandler {              throw new NullPointerException("no PIN selected for activation/change");            } -          ManagementPINProviderFactory ppfac = -                  new ManagementPINProviderFactory(card.getReader(), gui); -            try {              if ("activate_enterpin".equals(actionCommand)) { -              log.info("activate " + selectedPIN.getLocalizedName()); -              ((PINMgmtSignatureCard) card).activatePIN(selectedPIN, -                      ppfac.getActivatePINProvider()); -              updatePINState(selectedPIN, STATUS.ACTIV); -              gui.showMessageDialog(PINManagementGUIFacade.TITLE_ACTIVATE_SUCCESS, -                      PINManagementGUIFacade.MESSAGE_ACTIVATE_SUCCESS, -                      new Object[] {selectedPIN.getLocalizedName()}, -                      BKUGUIFacade.BUTTON_OK, this, "ok"); -              waitForAction(); +              activatePIN(selectedPIN);              } else if ("change_enterpin".equals(actionCommand)) { -              log.info("change " + selectedPIN.getLocalizedName()); -              ((PINMgmtSignatureCard) card).changePIN(selectedPIN,  -                      ppfac.getChangePINProvider()); -              updatePINState(selectedPIN, STATUS.ACTIV); -              gui.showMessageDialog(PINManagementGUIFacade.TITLE_CHANGE_SUCCESS, -                      PINManagementGUIFacade.MESSAGE_CHANGE_SUCCESS, -                      new Object[] {selectedPIN.getLocalizedName()}, -                      BKUGUIFacade.BUTTON_OK, this, "ok"); -              waitForAction(); - +              changePIN(selectedPIN);              } else if ("unblock_enterpuk".equals(actionCommand)) { -              log.info("unblock " + selectedPIN.getLocalizedName()); -              ((PINMgmtSignatureCard) card).unblockPIN(selectedPIN, -                      ppfac.getUnblockPINProvider()); +              unblockPIN(selectedPIN);              } else if ("verify_enterpin".equals(actionCommand)) { -              log.info("verify " + selectedPIN.getLocalizedName()); -              ((PINMgmtSignatureCard) card).verifyPIN(selectedPIN, -                      ppfac.getVerifyPINProvider()); -              updatePINState(selectedPIN, STATUS.ACTIV); +              verifyPIN(selectedPIN);              }            } catch (CancelledException ex) {              log.trace("cancelled"); @@ -154,29 +131,17 @@ public class PINManagementRequestHandler extends AbstractRequestHandler {                      new Object[] {selectedPIN.getLocalizedName()},                      this, null);              waitForAction(); -          } catch (PINConfirmationException ex) { -            log.error("confirmation pin does not match new " + selectedPIN.getLocalizedName()); -            gui.showErrorDialog(PINManagementGUIFacade.ERR_PIN_CONFIRMATION, -                    new Object[] {selectedPIN.getLocalizedName()}, -                    this, null); -            waitForAction(); + +            // inner loop for pinConfirmation and pinFormat ex +//          } catch (PINConfirmationException ex) { +//          } catch (PINFormatException ex) { +            } catch (PINOperationAbortedException ex) {              log.error("pin operation aborted without further details");              gui.showErrorDialog(PINManagementGUIFacade.ERR_PIN_OPERATION_ABORTED,                      new Object[] {selectedPIN.getLocalizedName()},                      this, null);              waitForAction(); -          } catch (PINFormatException ex) { -            log.error("wrong format of new " + selectedPIN.getLocalizedName()); -//            updatePINStatus(selectedPIN, STATUS.NOT_ACTIV); -            String pinSize = String.valueOf(selectedPIN.getMinLength()); -            if (selectedPIN.getMinLength() != selectedPIN.getMaxLength()) { -                pinSize += "-" + selectedPIN.getMaxLength(); -            } -            gui.showErrorDialog(PINManagementGUIFacade.ERR_PIN_FORMAT, -                    new Object[] {selectedPIN.getLocalizedName(), pinSize}, -                    this, null); -            waitForAction();            }          } // end if @@ -206,6 +171,157 @@ public class PINManagementRequestHandler extends AbstractRequestHandler {      }    } +  private void activatePIN(PINSpec selectedPIN) +          throws InterruptedException, SignatureCardException, GetPINStatusException { + +    log.info("activate " + selectedPIN.getLocalizedName()); +    ManagementPINGUI pinGUI = new ManagementPINGUI((PINManagementGUI) gui, +            PINManagementGUIFacade.DIALOG.ACTIVATE); + +    boolean reentry; +    do { +      try { +        reentry = false; +        ((PINMgmtSignatureCard) card).activatePIN(selectedPIN, pinGUI); +      } catch (PINConfirmationException ex) { +        reentry = true; +        log.error("confirmation pin does not match new " + selectedPIN.getLocalizedName()); +        gui.showErrorDialog(PINManagementGUIFacade.ERR_PIN_CONFIRMATION, +                new Object[] {selectedPIN.getLocalizedName()}, +                this, null); +        waitForAction(); +      } catch (PINFormatException ex) { +        reentry = true; +        log.error("wrong format of new " + selectedPIN.getLocalizedName()); +        String pinSize = String.valueOf(selectedPIN.getMinLength()); +        if (selectedPIN.getMinLength() != selectedPIN.getMaxLength()) { +            pinSize += "-" + selectedPIN.getMaxLength(); +        } +        gui.showErrorDialog(PINManagementGUIFacade.ERR_PIN_FORMAT, +                new Object[] {selectedPIN.getLocalizedName(), pinSize}, +                this, null); +        waitForAction(); +      } +    } while (reentry); + +    updatePINState(selectedPIN, STATUS.ACTIV); +    gui.showMessageDialog(PINManagementGUIFacade.TITLE_ACTIVATE_SUCCESS, +            PINManagementGUIFacade.MESSAGE_ACTIVATE_SUCCESS, +            new Object[]{selectedPIN.getLocalizedName()}, +            BKUGUIFacade.BUTTON_OK, this, "ok"); +    waitForAction(); +  } + +  private void verifyPIN(PINSpec selectedPIN) +          throws InterruptedException, SignatureCardException, GetPINStatusException { + +    log.info("verify " + selectedPIN.getLocalizedName()); +    VerifyPINGUI pinGUI = new VerifyPINGUI(gui); + +    boolean reentry; +    do { +      try { +        reentry = false; +        ((PINMgmtSignatureCard) card).verifyPIN(selectedPIN, pinGUI); +      } catch (PINFormatException ex) { +        reentry = true; +        log.error("wrong format of new " + selectedPIN.getLocalizedName()); +        String pinSize = String.valueOf(selectedPIN.getMinLength()); +        if (selectedPIN.getMinLength() != selectedPIN.getMaxLength()) { +            pinSize += "-" + selectedPIN.getMaxLength(); +        } +        gui.showErrorDialog(PINManagementGUIFacade.ERR_PIN_FORMAT, +                new Object[] {selectedPIN.getLocalizedName(), pinSize}, +                this, null); +        waitForAction(); +      } +    } while (reentry); + +    updatePINState(selectedPIN, STATUS.ACTIV); +  } + +  private void changePIN(PINSpec selectedPIN) +          throws SignatureCardException, GetPINStatusException, InterruptedException { + +    log.info("change " + selectedPIN.getLocalizedName()); +    ManagementPINGUI pinGUI = new ManagementPINGUI((PINManagementGUI) gui, +            PINManagementGUIFacade.DIALOG.CHANGE); + +    boolean reentry; +    do { +      try { +        reentry = false; +        ((PINMgmtSignatureCard) card).changePIN(selectedPIN, pinGUI); +      } catch (PINConfirmationException ex) { +        reentry = true; +        log.error("confirmation pin does not match new " + selectedPIN.getLocalizedName()); +        gui.showErrorDialog(PINManagementGUIFacade.ERR_PIN_CONFIRMATION, +                new Object[] {selectedPIN.getLocalizedName()}, +                this, null); +        waitForAction(); +      } catch (PINFormatException ex) { +        reentry = true; +        log.error("wrong format of new " + selectedPIN.getLocalizedName()); +        String pinSize = String.valueOf(selectedPIN.getMinLength()); +        if (selectedPIN.getMinLength() != selectedPIN.getMaxLength()) { +            pinSize += "-" + selectedPIN.getMaxLength(); +        } +        gui.showErrorDialog(PINManagementGUIFacade.ERR_PIN_FORMAT, +                new Object[] {selectedPIN.getLocalizedName(), pinSize}, +                this, null); +        waitForAction(); +      } +    } while (reentry); + +    updatePINState(selectedPIN, STATUS.ACTIV); +    gui.showMessageDialog(PINManagementGUIFacade.TITLE_CHANGE_SUCCESS, +            PINManagementGUIFacade.MESSAGE_CHANGE_SUCCESS, +            new Object[]{selectedPIN.getLocalizedName()}, +            BKUGUIFacade.BUTTON_OK, this, "ok"); +    waitForAction(); +  } + +  private void unblockPIN(PINSpec selectedPIN) +          throws SignatureCardException, GetPINStatusException, InterruptedException { + +    log.info("unblock " + selectedPIN.getLocalizedName()); +    ManagementPINGUI pinGUI = new ManagementPINGUI((PINManagementGUI) gui, +            PINManagementGUIFacade.DIALOG.UNBLOCK); + +    boolean reentry; +    do { +      try { +        reentry = false; +        ((PINMgmtSignatureCard) card).unblockPIN(selectedPIN, pinGUI); +      } catch (PINConfirmationException ex) { +        reentry = true; +        log.error("confirmation pin does not match new " + selectedPIN.getLocalizedName()); +        gui.showErrorDialog(PINManagementGUIFacade.ERR_PIN_CONFIRMATION, +                new Object[] {selectedPIN.getLocalizedName()}, +                this, null); +        waitForAction(); +      } catch (PINFormatException ex) { +        reentry = true; +        log.error("wrong format of new " + selectedPIN.getLocalizedName()); +        String pinSize = String.valueOf(selectedPIN.getMinLength()); +        if (selectedPIN.getMinLength() != selectedPIN.getMaxLength()) { +            pinSize += "-" + selectedPIN.getMaxLength(); +        } +        gui.showErrorDialog(PINManagementGUIFacade.ERR_PIN_FORMAT, +                new Object[] {selectedPIN.getLocalizedName(), pinSize}, +                this, null); +        waitForAction(); +      } +    } while (reentry); + +    updatePINState(selectedPIN, STATUS.ACTIV); +    gui.showMessageDialog(PINManagementGUIFacade.TITLE_UNBLOCK_SUCCESS, +            PINManagementGUIFacade.MESSAGE_UNBLOCK_SUCCESS, +            new Object[]{selectedPIN.getLocalizedName()}, +            BKUGUIFacade.BUTTON_OK, this, "ok"); +    waitForAction(); +  } +    @Override    public boolean requireCard() {      return true; | 
