diff options
18 files changed, 445 insertions, 457 deletions
diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java index ffdc230d..6b083e16 100644 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java @@ -32,6 +32,10 @@ public interface PINManagementGUIFacade extends BKUGUIFacade { 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_UNBLOCK_PIN = "title.unblock.pin"; + public static final String TITLE_ACTIVATE_SUCCESS = "title.activate.success"; + public static final String TITLE_CHANGE_SUCCESS = "title.change.success"; + public static final String MESSAGE_ACTIVATE_SUCCESS = "message.activate.success"; + public static final String MESSAGE_CHANGE_SUCCESS = "message.change.success"; public static final String MESSAGE_PINMGMT = "message.pin.mgmt"; public static final String MESSAGE_ACTIVATE_PIN = "message.activate.pin"; public static final String MESSAGE_CHANGE_PIN = "message.change.pin"; diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PINManagementRequestHandler.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PINManagementRequestHandler.java index 851bff21..c8472c97 100644 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PINManagementRequestHandler.java +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PINManagementRequestHandler.java @@ -32,8 +32,6 @@ import at.gv.egiz.stal.ext.PINManagementResponse; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; import javax.smartcardio.Card; import javax.smartcardio.CardChannel; import javax.smartcardio.CardException; @@ -50,11 +48,6 @@ public class PINManagementRequestHandler extends AbstractRequestHandler { protected static final Log log = LogFactory.getLog(PINManagementRequestHandler.class); -// protected ResourceBundle messages; - -// public PINManagementRequestHandler(ResourceBundle messages) { -// this.messages = messages; -// } @Override public STALResponse handleRequest(STALRequest request) throws InterruptedException { if (request instanceof PINManagementRequest) { @@ -86,8 +79,14 @@ public class PINManagementRequestHandler extends AbstractRequestHandler { gui.showUnblockPINDialog(selectedPIN, this, "unblock", this, "back"); } else if ("activate".equals(actionCommand)) { try { - byte[] pin = encodePIN(gui.getPin()); - activatePIN(selectedPIN.getKID(), selectedPIN.getContextAID(), pin); + card.activatePIN(selectedPIN.getKID(), + selectedPIN.getContextAID(), + String.valueOf(gui.getPin())); + gui.showMessageDialog(PINManagementGUIFacade.TITLE_ACTIVATE_SUCCESS, + PINManagementGUIFacade.MESSAGE_ACTIVATE_SUCCESS, + new Object[] {selectedPIN.getLocalizedName()}, + this, "ok"); + waitForAction(); showPINManagementDialog(gui); } catch (SignatureCardException ex) { log.error("failed to activate " + selectedPIN.getLocalizedName() + ": " + ex.getMessage()); @@ -97,9 +96,15 @@ public class PINManagementRequestHandler extends AbstractRequestHandler { } } else if ("change".equals(actionCommand)) { try { - byte[] oldPin = encodePIN(gui.getOldPin()); //new byte[]{(byte) 0x25, (byte) 0x40, (byte) 0x01}; - byte[] pin = encodePIN(gui.getPin()); //new byte[]{(byte) 0x25, (byte) 0x40}; - changePIN(selectedPIN.getKID(), selectedPIN.getContextAID(), oldPin, pin); + card.changePIN(selectedPIN.getKID(), + selectedPIN.getContextAID(), + String.valueOf(gui.getOldPin()), + String.valueOf(gui.getPin())); + gui.showMessageDialog(PINManagementGUIFacade.TITLE_CHANGE_SUCCESS, + PINManagementGUIFacade.MESSAGE_CHANGE_SUCCESS, + new Object[] {selectedPIN.getLocalizedName()}, + this, "ok"); + waitForAction(); showPINManagementDialog(gui); } catch (VerificationFailedException ex) { log.error("failed to change " + selectedPIN.getLocalizedName() + ": " + ex.getMessage()); @@ -131,137 +136,6 @@ public class PINManagementRequestHandler extends AbstractRequestHandler { return true; } - /** - * pin.length < 4bit - * @param kid - * @param contextAID - * @param pin - * @throws at.gv.egiz.smcc.SignatureCardException - */ - private void activatePIN(byte kid, byte[] contextAID, byte[] pin) throws SignatureCardException { - Card icc = card.getCard(); - try { - icc.beginExclusive(); - CardChannel channel = icc.getBasicChannel(); - - if (contextAID != null) { - CommandAPDU selectAPDU = new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, contextAID); - ResponseAPDU responseAPDU = channel.transmit(selectAPDU); - if (responseAPDU.getSW() != 0x9000) { - icc.endExclusive(); - String msg = "Failed to activate PIN " + SMCCHelper.toString(new byte[]{kid}) + - ": Failed to select AID " + SMCCHelper.toString(contextAID) + - ": " + SMCCHelper.toString(responseAPDU.getBytes()); - log.error(msg); - throw new SignatureCardException(msg); - } - } - - if (pin.length > 7) { - icc.endExclusive(); - log.error("PIN too long"); - throw new SignatureCardException("PIN too long"); - } - byte length = (byte) (0x20 | pin.length * 2); - - byte[] apdu = new byte[]{ - (byte) 0x00, (byte) 0x24, (byte) 0x01, kid, (byte) 0x08, - (byte) length, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF}; - for (int i = 0; i < pin.length; i++) { - apdu[i + 6] = pin[i]; - } - - CommandAPDU verifyAPDU = new CommandAPDU(apdu); - ResponseAPDU responseAPDU = channel.transmit(verifyAPDU); - - if (responseAPDU.getSW() != 0x9000) { - icc.endExclusive(); - String msg = "Failed to activate PIN " + SMCCHelper.toString(new byte[]{kid}) + ": " + SMCCHelper.toString(responseAPDU.getBytes()); - log.error(msg); - throw new SignatureCardException(msg); - } - icc.endExclusive(); - } catch (CardException ex) { - log.error("Failed to activate PIN: " + ex.getMessage()); - throw new SignatureCardException(ex.getMessage(), ex); - } finally { - try { - icc.endExclusive(); - } catch (CardException ex) { - log.trace("failed to end exclusive card access"); - } - } - } - - private void changePIN(byte kid, byte[] contextAID, byte[] oldPIN, byte[] newPIN) throws SignatureCardException, VerificationFailedException { - Card icc = card.getCard(); - try { - icc.beginExclusive(); - CardChannel channel = icc.getBasicChannel(); - - if (contextAID != null) { - CommandAPDU selectAPDU = new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, contextAID); - ResponseAPDU responseAPDU = channel.transmit(selectAPDU); - if (responseAPDU.getSW() != 0x9000) { - icc.endExclusive(); - String msg = "Failed to change PIN " + SMCCHelper.toString(new byte[]{kid}) + - ": Failed to select AID " + SMCCHelper.toString(contextAID) + - ": " + SMCCHelper.toString(responseAPDU.getBytes()); - log.error(msg); - throw new SignatureCardException(msg); - } - } - - if (oldPIN.length > 7 || newPIN.length > 7) { - icc.endExclusive(); - log.error("PIN too long"); - throw new SignatureCardException("PIN too long"); - } - byte oldLength = (byte) (0x20 | oldPIN.length * 2); - byte newLength = (byte) (0x20 | newPIN.length * 2); - - byte[] apdu = new byte[]{ - (byte) 0x00, (byte) 0x24, (byte) 0x00, kid, (byte) 0x10, - oldLength, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, - newLength, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF}; - for (int i = 0; i < oldPIN.length; i++) { - apdu[i + 6] = oldPIN[i]; - } - for (int i = 0; i < newPIN.length; i++) { - apdu[i + 14] = newPIN[i]; - } - - CommandAPDU verifyAPDU = new CommandAPDU(apdu); - ResponseAPDU responseAPDU = channel.transmit(verifyAPDU); - - if (responseAPDU.getSW1() == 0x63 && responseAPDU.getSW2() >> 4 == 0xc) { - icc.endExclusive(); - int retries = responseAPDU.getSW2() & 0x0f; - log.error("Wrong PIN, " + retries + " tries left"); - throw new VerificationFailedException(retries); - } - if (responseAPDU.getSW() != 0x9000) { - icc.endExclusive(); - String msg = "Failed to change PIN " - + SMCCHelper.toString(new byte[]{kid}) + ": " - + SMCCHelper.toString(responseAPDU.getBytes()); - log.error(msg); - throw new SignatureCardException(msg); - } - - - } catch (CardException ex) { - log.error("Failed to change PIN: " + ex.getMessage()); - throw new SignatureCardException(ex.getMessage(), ex); - } finally { - try { - icc.endExclusive(); - } catch (CardException ex) { - log.trace("failed to end exclusive card access"); - } - } - } - public Map<PINSpec, STATUS> getPINStatuses() throws SignatureCardException { Card icc = card.getCard(); try { @@ -321,16 +195,6 @@ public class PINManagementRequestHandler extends AbstractRequestHandler { } } - private byte[] encodePIN(char[] pinChars) { - int length = (int) Math.ceil(pinChars.length/2); - byte[] pin = new byte[length]; - for (int i = 0; i < length; i++) { - pin[i] = (byte) (16*Character.digit(pinChars[i*2], 16) + Character.digit(pinChars[i*2+1], 16)); - } -// log.trace("***** " + SMCCHelper.toString(pin) + " ******"); - return pin; - } - private void showPINManagementDialog(PINManagementGUIFacade gui) { try { Map<PINSpec, STATUS> pins = getPINStatuses(); diff --git a/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties b/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties index b6099db6..430f85b5 100644 --- a/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties +++ b/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties @@ -18,11 +18,15 @@ 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.activate.success=<html>Erfolg</html> +title.change.success=<html>Erfolg</html> message.pin.mgmt=<html>Die Karte verf\u00FCgt \u00FCber {0} PINs</html> message.activate.pin=<html>{0} eingeben und best\u00E4tigen</html> message.change.pin=<html>{0} eingeben und best\u00E4tigen</html> message.unblock.pin=<html>PUK zu {0} eingeben</html> +message.activate.success=<html>{0} wurde erfolgreich aktiviert.</html> +message.change.success=<html>{0} wurde erfolgreich ge\u00E4ndert.</html> label.activation=<html>e-card Aktivierungsprozess</html> label.activation.step=<html>Schritt {0}</html> diff --git a/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties b/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties index 40332826..98d18633 100644 --- a/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties +++ b/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties @@ -18,11 +18,15 @@ title.pin.mgmt=<html>PIN Management</html> title.activate.pin=<html>Activate 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> message.pin.mgmt=<html>The smartcard has {0} PINs</html> message.activate.pin=<html>Enter and confirm {0}</html> message.change.pin=<html>Enter and confirm {0}</html> message.unblock.pin=<html>Enter PUK for {0}</html> +message.activate.success=<html>{0} successfully activated</html> +message.change.success=<html>{0} successfully changed</html> label.activation=<html>e-card activation process</html> label.activation.step=<html>Step {0}</html> 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 ae91670a..be5e3fc8 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 @@ -127,7 +127,9 @@ public interface BKUGUIFacade { public void showHashDataInputDialog(List<HashDataInput> signedReferences, ActionListener okListener, String okCommand); - public void showErrorDialog(String errorMsgKey, Object[] errorMsgParams, ActionListener okListener, String actionCommand); + public void showErrorDialog(String errorMsgKey, Object[] errorMsgParams, ActionListener okListener, String okCommand); public void showErrorDialog(String errorMsgKey, Object[] errorMsgParams); + + public void showMessageDialog(String titleKey, String msgKey, Object[] msgParams, ActionListener okListener, String okCommand); } 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 ca597701..d6c96627 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 @@ -19,8 +19,10 @@ package at.gv.egiz.bku.gui; import at.gv.egiz.smcc.PINSpec; import at.gv.egiz.stal.HashDataInput; +import java.awt.Color; import java.awt.Container; import java.awt.Cursor; +import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; @@ -882,77 +884,110 @@ public class BKUGUIImpl implements BKUGUIFacade { } @Override - public void showErrorDialog(final String errorMsgKey, final Object[] errorMsgParams, final ActionListener okListener, final String okCommand) { + public void showErrorDialog( + final String errorMsgKey, final Object[] errorMsgParams, + final ActionListener okListener, final String okCommand) { - log.debug("scheduling error dialog"); - + showMessageDialog(TITLE_ERROR, ERROR_COLOR, + errorMsgKey, errorMsgParams, okListener, okCommand); + } + + @Override + public void showErrorDialog( + final String errorMsgKey, final Object[] errorMsgParams) { + + showMessageDialog(TITLE_ERROR, ERROR_COLOR, + errorMsgKey, errorMsgParams, null, null); + } + + @Override + public void showMessageDialog( + final String titleKey, + final String msgKey, final Object[] msgParams, + final ActionListener okListener, final String okCommand) { + + showMessageDialog(titleKey, null, + msgKey, msgParams, okListener, okCommand); + } + + private void showMessageDialog( + final String titleKey, final Color titleColor, + final String msgKey, final Object[] msgParams, + final ActionListener okListener, final String okCommand) { + + log.debug("scheduling message dialog"); + SwingUtilities.invokeLater(new Runnable() { @Override public void run() { - log.debug("show error dialog"); - + log.debug("show message dialog"); + mainPanel.removeAll(); buttonPanel.removeAll(); if (renderHeaderPanel) { - titleLabel.setText(getMessage(TITLE_ERROR)); + titleLabel.setText(getMessage(titleKey)); } - helpListener.setHelpTopic(errorMsgKey); - - String errorMsgPattern = getMessage(errorMsgKey); - String errorMsg = MessageFormat.format(errorMsgPattern, errorMsgParams); - - JLabel errorMsgLabel = new JLabel(); - errorMsgLabel.setFont(errorMsgLabel.getFont().deriveFont(errorMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); - errorMsgLabel.setText(errorMsg); + helpListener.setHelpTopic(msgKey); + + String msgPattern = getMessage(msgKey); + String msg = MessageFormat.format(msgPattern, msgParams); + + 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.ParallelGroup mainHorizontal = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING); GroupLayout.SequentialGroup mainVertical = mainPanelLayout.createSequentialGroup(); - + if (!renderHeaderPanel) { - JLabel errorTitleLabel = new JLabel(); - errorTitleLabel.setFont(errorTitleLabel.getFont().deriveFont(errorTitleLabel.getFont().getStyle() | java.awt.Font.BOLD)); - errorTitleLabel.setText(getMessage(TITLE_ERROR)); - errorTitleLabel.setForeground(ERROR_COLOR); - + JLabel titleLabel = new JLabel(); + titleLabel.setFont(titleLabel.getFont().deriveFont(titleLabel.getFont().getStyle() | Font.BOLD)); + titleLabel.setText(getMessage(titleKey)); + if (titleColor != null) { + titleLabel.setForeground(titleColor); + } + mainHorizontal .addGroup(mainPanelLayout.createSequentialGroup() - .addComponent(errorTitleLabel) + .addComponent(titleLabel) .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) .addComponent(helpLabel)); mainVertical .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(errorTitleLabel) + .addComponent(titleLabel) .addComponent(helpLabel)); } - + mainPanelLayout.setHorizontalGroup(mainHorizontal - .addComponent(errorMsgLabel)); + .addComponent(msgLabel)); mainPanelLayout.setVerticalGroup(mainVertical - .addComponent(errorMsgLabel)); - - JButton okButton = new JButton(); - okButton.setFont(okButton.getFont().deriveFont(okButton.getFont().getStyle() & ~java.awt.Font.BOLD)); - okButton.setText(getMessage(BUTTON_OK)); - okButton.setActionCommand(okCommand); - okButton.addActionListener(okListener); + .addComponent(msgLabel)); - GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); - buttonPanel.setLayout(buttonPanelLayout); + if (okListener != null && okCommand != null) { + JButton okButton = new JButton(); + okButton.setFont(okButton.getFont().deriveFont(okButton.getFont().getStyle() & ~java.awt.Font.BOLD)); + okButton.setText(getMessage(BUTTON_OK)); + okButton.setActionCommand(okCommand); + okButton.addActionListener(okListener); - buttonPanelLayout.setHorizontalGroup( - buttonPanelLayout.createSequentialGroup() - .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(okButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)); - buttonPanelLayout.setVerticalGroup( - buttonPanelLayout.createSequentialGroup() - .addComponent(okButton)); + GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); + buttonPanel.setLayout(buttonPanelLayout); + + buttonPanelLayout.setHorizontalGroup( + buttonPanelLayout.createSequentialGroup() + .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(okButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)); + buttonPanelLayout.setVerticalGroup( + buttonPanelLayout.createSequentialGroup() + .addComponent(okButton)); + } contentPanel.validate(); } @@ -960,68 +995,6 @@ public class BKUGUIImpl implements BKUGUIFacade { } @Override - public void showErrorDialog(final String errorMsgKey, final Object[] errorMsgParams) { - - log.debug("scheduling error dialog"); - - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - - log.debug("show error dialog"); - - mainPanel.removeAll(); - buttonPanel.removeAll(); - - if (renderHeaderPanel) { - titleLabel.setText(getMessage(TITLE_ERROR)); - } - - helpListener.setHelpTopic(errorMsgKey); - - String errorMsgPattern = getMessage(errorMsgKey); - String errorMsg = MessageFormat.format(errorMsgPattern, errorMsgParams); - - JLabel errorMsgLabel = new JLabel(); - errorMsgLabel.setFont(errorMsgLabel.getFont().deriveFont(errorMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); - errorMsgLabel.setText(errorMsg); - - GroupLayout mainPanelLayout = new GroupLayout(mainPanel); - mainPanel.setLayout(mainPanelLayout); - - - GroupLayout.ParallelGroup mainHorizontal = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING); - GroupLayout.SequentialGroup mainVertical = mainPanelLayout.createSequentialGroup(); - - if (!renderHeaderPanel) { - JLabel errorTitleLabel = new JLabel(); - errorTitleLabel.setFont(errorTitleLabel.getFont().deriveFont(errorTitleLabel.getFont().getStyle() | java.awt.Font.BOLD)); - errorTitleLabel.setText(getMessage(TITLE_ERROR)); - errorTitleLabel.setForeground(ERROR_COLOR); - - mainHorizontal - .addGroup(mainPanelLayout.createSequentialGroup() - .addComponent(errorTitleLabel) - .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) - .addComponent(helpLabel)); - mainVertical - .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(errorTitleLabel) - .addComponent(helpLabel)); - } - - mainPanelLayout.setHorizontalGroup(mainHorizontal - .addComponent(errorMsgLabel)); - mainPanelLayout.setVerticalGroup(mainVertical - .addComponent(errorMsgLabel)); - - contentPanel.validate(); - } - }); - } - - @Override public void showWaitDialog(final String waitMessage) { log.debug("scheduling wait dialog"); diff --git a/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/ResultServlet.java b/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/ResultServlet.java index 12707117..7855b73c 100644 --- a/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/ResultServlet.java +++ b/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/ResultServlet.java @@ -31,6 +31,7 @@ import org.apache.commons.logging.LogFactory; import at.gv.egiz.bku.binding.HTTPBindingProcessor; import at.gv.egiz.bku.binding.HttpUtil; import at.gv.egiz.bku.binding.IdFactory; +import at.gv.egiz.bku.conf.Configurator; import at.gv.egiz.bku.utils.NullOutputStream; /** @@ -40,7 +41,6 @@ import at.gv.egiz.bku.utils.NullOutputStream; public class ResultServlet extends SpringBKUServlet { private final static Log log = LogFactory.getLog(ResultServlet.class); - public final static String USER_AGENT_PROPERTY_KEY = "UserAgent"; private String encoding = "UTF-8"; private String expiredPage = "./expiredError.jsp"; @@ -116,15 +116,16 @@ public class ResultServlet extends SpringBKUServlet { return; } resp.setStatus(bp.getResponseCode()); +// log.info("ALLOW CACHING OF RESULT PAGE"); resp.setHeader("Cache-Control", "no-store"); // HTTP 1.1 resp.setHeader("Pragma", "no-cache"); // HTTP 1.0 resp.setDateHeader("Expires", 0); - if (configurator.getProperty(USER_AGENT_PROPERTY_KEY) != null) { + if (configurator.getProperty(Configurator.USERAGENT_CONFIG_P) != null) { resp.setHeader(HttpUtil.HTTP_HEADER_USER_AGENT, configurator - .getProperty(USER_AGENT_PROPERTY_KEY)); + .getProperty(Configurator.USERAGENT_CONFIG_P)); } else { resp.setHeader(HttpUtil.HTTP_HEADER_USER_AGENT, - "citizen-card-environment/1.2 MOCCA Unknown"); + Configurator.USERAGENT_DEFAULT); } for (Iterator<String> it = bp.getResponseHeaders().keySet().iterator(); it .hasNext();) { diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrl.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrl.java index 7b682136..aaeacd98 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrl.java @@ -16,6 +16,7 @@ */ package at.gv.egiz.bku.binding; +import at.gv.egiz.bku.conf.Configurator; import java.net.MalformedURLException; import java.net.URL; import java.util.Properties; @@ -82,7 +83,7 @@ public class DataUrl { public static void setConfiguration(Properties props) { configuration = props; if (configuration != null) { - String className = configuration.getProperty(DataUrlConnection.DATAURLCONNECTION_CONFIG_P); + String className = configuration.getProperty(Configurator.DATAURLCONNECTION_CONFIG_P); if (className != null) { try { log.info("set DataURLConnection class: " + className); diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnection.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnection.java index 21407cc3..f954a017 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnection.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnection.java @@ -34,12 +34,6 @@ import at.gv.egiz.bku.slcommands.SLResult; */ public interface DataUrlConnection { - public final static String USERAGENT_CONFIG_P = "UserAgent"; - public static final String USERAGENT_DEFAULT = "citizen-card-environment/1.2 MOCCA/UNKNOWN"; - public static final String USERAGENT_BASE = "citizen-card-environment/1.2 MOCCA/"; - - public static final String DATAURLCONNECTION_CONFIG_P = "DataURLConnectionImplClass"; - public static final String FORMPARAM_RESPONSETYPE = "ResponseType"; public static final String DEFAULT_RESPONSETYPE = "HTTP-Security-Layer-RESPONSE"; public static final String FORMPARAM_XMLRESPONSE = "XMLResponse"; diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnectionImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnectionImpl.java index d9a9454e..4c235456 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnectionImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnectionImpl.java @@ -43,6 +43,7 @@ import org.apache.commons.logging.LogFactory; import at.gv.egiz.bku.binding.multipart.InputStreamPartSource; import at.gv.egiz.bku.binding.multipart.SLResultPart; +import at.gv.egiz.bku.conf.Configurator; import at.gv.egiz.bku.slcommands.SLResult; import at.gv.egiz.bku.slcommands.SLResult.SLResultType; import at.gv.egiz.bku.slexceptions.SLRuntimeException; @@ -225,12 +226,12 @@ public class DataUrlConnectionImpl implements DataUrlConnectionSPI { boundary = "--" + IdFactory.getInstance().createId().toString(); requestHttpHeaders = new HashMap<String, String>(); if ((config != null) - && (config.getProperty(USERAGENT_CONFIG_P) != null)) { + && (config.getProperty(Configurator.USERAGENT_CONFIG_P) != null)) { requestHttpHeaders.put(HttpUtil.HTTP_HEADER_USER_AGENT, config - .getProperty(USERAGENT_CONFIG_P)); + .getProperty(Configurator.USERAGENT_CONFIG_P)); } else { requestHttpHeaders - .put(HttpUtil.HTTP_HEADER_USER_AGENT, USERAGENT_DEFAULT); + .put(HttpUtil.HTTP_HEADER_USER_AGENT, Configurator.USERAGENT_DEFAULT); } requestHttpHeaders.put(HttpUtil.HTTP_HEADER_CONTENT_TYPE, diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/LegacyDataUrlConnectionImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/LegacyDataUrlConnectionImpl.java index ef9dd199..cfccb7f1 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/LegacyDataUrlConnectionImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/LegacyDataUrlConnectionImpl.java @@ -1,6 +1,7 @@ package at.gv.egiz.bku.binding; +import at.gv.egiz.bku.conf.Configurator; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -38,7 +39,7 @@ import at.gv.egiz.bku.utils.binding.Protocol; */ public class LegacyDataUrlConnectionImpl implements DataUrlConnectionSPI { - private final static Log log = LogFactory.getLog(DataUrlConnectionImpl.class); + private final static Log log = LogFactory.getLog(LegacyDataUrlConnectionImpl.class); public final static Protocol[] SUPPORTED_PROTOCOLS = { Protocol.HTTP, Protocol.HTTPS }; @@ -212,13 +213,13 @@ public class LegacyDataUrlConnectionImpl implements DataUrlConnectionSPI { this.url = url; requestHttpHeaders = new HashMap<String, String>(); if ((config != null) - && (config.getProperty(USERAGENT_CONFIG_P) != null)) { - log.debug("setting User-Agent header: " + config.getProperty(USERAGENT_CONFIG_P)); + && (config.getProperty(Configurator.USERAGENT_CONFIG_P) != null)) { + log.debug("setting User-Agent header: " + config.getProperty(Configurator.USERAGENT_CONFIG_P)); requestHttpHeaders.put(HttpUtil.HTTP_HEADER_USER_AGENT, config - .getProperty(USERAGENT_CONFIG_P)); + .getProperty(Configurator.USERAGENT_CONFIG_P)); } else { requestHttpHeaders - .put(HttpUtil.HTTP_HEADER_USER_AGENT, USERAGENT_DEFAULT); + .put(HttpUtil.HTTP_HEADER_USER_AGENT, Configurator.USERAGENT_DEFAULT); } requestHttpHeaders.put(HttpUtil.HTTP_HEADER_CONTENT_TYPE, diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/conf/Configurator.java b/bkucommon/src/main/java/at/gv/egiz/bku/conf/Configurator.java index a6c70d2c..6213ffcf 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/conf/Configurator.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/conf/Configurator.java @@ -49,6 +49,13 @@ public abstract class Configurator { private Log log = LogFactory.getLog(Configurator.class);
+ public final static String USERAGENT_CONFIG_P = "UserAgent";
+ public static final String DATAURLCONNECTION_CONFIG_P = "DataURLConnectionImplClass";
+
+ public static final String USERAGENT_DEFAULT = "citizen-card-environment/1.2 MOCCA/UNKNOWN";
+ public static final String USERAGENT_BASE = "citizen-card-environment/1.2 MOCCA/";
+
+
protected Properties properties;
protected CertValidator certValidator;
@@ -203,22 +210,22 @@ public abstract class Configurator { }
public void configureVersion() {
- if (properties.getProperty(DataUrlConnection.USERAGENT_CONFIG_P) == null) {
+ if (properties.getProperty(USERAGENT_CONFIG_P) == null) {
Properties p = new Properties();
try {
InputStream is = getManifest();
if (is != null) {
p.load(getManifest());
String version = p.getProperty("Implementation-Build");
- properties.setProperty(DataUrlConnection.USERAGENT_CONFIG_P,
- DataUrlConnection.USERAGENT_BASE + version);
+ properties.setProperty(USERAGENT_CONFIG_P,
+ USERAGENT_BASE + version);
log.debug("Setting user agent to: "
+ properties
- .getProperty(DataUrlConnection.USERAGENT_CONFIG_P));
+ .getProperty(USERAGENT_CONFIG_P));
} else {
log.warn("Cannot read manifest");
- properties.setProperty(DataUrlConnection.USERAGENT_CONFIG_P,
- DataUrlConnection.USERAGENT_DEFAULT);
+ properties.setProperty(USERAGENT_CONFIG_P,
+ USERAGENT_DEFAULT);
}
} catch (IOException e) {
log.error(e);
diff --git a/bkucommon/src/test/java/at/gv/egiz/stal/dummy/DummySTAL.java b/bkucommon/src/test/java/at/gv/egiz/stal/dummy/DummySTAL.java index 77dd7e4f..8adeadee 100644 --- a/bkucommon/src/test/java/at/gv/egiz/stal/dummy/DummySTAL.java +++ b/bkucommon/src/test/java/at/gv/egiz/stal/dummy/DummySTAL.java @@ -14,149 +14,141 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package at.gv.egiz.stal.dummy;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.KeyStore;
-import java.security.PrivateKey;
-import java.security.Signature;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.Locale;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import at.gv.egiz.stal.ErrorResponse;
-import at.gv.egiz.stal.InfoboxReadRequest;
-import at.gv.egiz.stal.InfoboxReadResponse;
-import at.gv.egiz.stal.STAL;
-import at.gv.egiz.stal.STALRequest;
-import at.gv.egiz.stal.STALResponse;
-import at.gv.egiz.stal.SignRequest;
-import at.gv.egiz.stal.SignResponse;
-
-public class DummySTAL implements STAL {
-
- static Log log = LogFactory.getLog(DummySTAL.class);
-
- protected X509Certificate cert = null;
- protected PrivateKey privateKey = null;
-
- public DummySTAL() {
- try {
+package at.gv.egiz.stal.dummy; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.Signature; +import java.security.cert.CertificateEncodingException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; +import java.util.Locale; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.stal.ErrorResponse; +import at.gv.egiz.stal.InfoboxReadRequest; +import at.gv.egiz.stal.InfoboxReadResponse; +import at.gv.egiz.stal.STAL; +import at.gv.egiz.stal.STALRequest; +import at.gv.egiz.stal.STALResponse; +import at.gv.egiz.stal.SignRequest; +import at.gv.egiz.stal.SignResponse; + +public class DummySTAL implements STAL { + + static Log log = LogFactory.getLog(DummySTAL.class); + + protected X509Certificate cert = null; + protected PrivateKey privateKey = null; + + public DummySTAL() { + try { KeyStore ks = KeyStore.getInstance("pkcs12"); InputStream ksStream = getClass().getClassLoader().getResourceAsStream( - "at/gv/egiz/bku/slcommands/impl/Cert.p12");
- ks.load(ksStream, "1622".toCharArray());
- for (Enumeration<String> aliases = ks.aliases(); aliases
- .hasMoreElements();) {
- String alias = aliases.nextElement();
- log.debug("Found alias " + alias + " in keystore");
- if (ks.isKeyEntry(alias)) {
- log.debug("Found key entry for alias: " + alias);
- privateKey = (PrivateKey) ks.getKey(alias, "1622".toCharArray());
- cert = (X509Certificate) ks.getCertificate(alias);
- System.out.println(cert);
- }
- }
- } catch (Exception e) {
- log.error(e);
- }
-
- }
-
- @Override
- public List<STALResponse> handleRequest(List<? extends STALRequest> requestList) {
-
- List<STALResponse> responses = new ArrayList<STALResponse>();
- for (STALRequest request : requestList) {
-
- log.debug("Got STALRequest " + request + ".");
-
- if (request instanceof InfoboxReadRequest) {
-
- String infoboxIdentifier = ((InfoboxReadRequest) request)
- .getInfoboxIdentifier();
- InputStream stream = getClass().getClassLoader().getResourceAsStream(
- "at/gv/egiz/stal/dummy/infoboxes4/" + infoboxIdentifier + ".bin");
-
- STALResponse response;
- if (stream != null) {
-
- log.debug("Infobox " + infoboxIdentifier + " found.");
-
- byte[] infobox;
- try {
- ByteArrayOutputStream buffer = new ByteArrayOutputStream();
- int b;
- while ((b = stream.read()) != -1) {
- buffer.write(b);
- }
- infobox = buffer.toByteArray();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
-
- InfoboxReadResponse infoboxReadResponse = new InfoboxReadResponse();
- infoboxReadResponse.setInfoboxValue(infobox);
- response = infoboxReadResponse;
-
- } else if ((infoboxIdentifier.equals("SecureSignatureKeypair")) ||(infoboxIdentifier.equals("CertifiedKeypair"))) {
- try {
- InfoboxReadResponse infoboxReadResponse = new InfoboxReadResponse();
- infoboxReadResponse.setInfoboxValue(cert.getEncoded());
- response = infoboxReadResponse;
- } catch (CertificateEncodingException e) {
- log.error(e);
- response = new ErrorResponse();
- }
- } else {
-
- log.debug("Infobox " + infoboxIdentifier + " not found.");
-
- response = new ErrorResponse();
- }
- responses.add(response);
-
- } else if (request instanceof SignRequest) {
- try {
-
- SignRequest signReq = (SignRequest) request;
- Signature s = Signature.getInstance("SHA1withRSA");
- s.initSign(privateKey);
- s.update(signReq.getSignedInfo());
- byte[] sigVal = s.sign();
- SignResponse resp = new SignResponse();
- resp.setSignatureValue(sigVal);
- responses.add(resp);
- } catch (Exception e) {
- log.error(e);
- responses.add(new ErrorResponse());
- }
-
- } else {
-
- log.debug("Request not implemented.");
-
- responses.add(new ErrorResponse());
- }
-
- }
-
- return responses;
- }
-
- @Override
- public void setLocale(Locale locale) {
- // TODO Auto-generated method stub
-
- }
-
-
-}
+ "at/gv/egiz/bku/slcommands/impl/Cert.p12"); + ks.load(ksStream, "1622".toCharArray()); + for (Enumeration<String> aliases = ks.aliases(); aliases + .hasMoreElements();) { + String alias = aliases.nextElement(); + log.debug("Found alias " + alias + " in keystore"); + if (ks.isKeyEntry(alias)) { + log.debug("Found key entry for alias: " + alias); + privateKey = (PrivateKey) ks.getKey(alias, "1622".toCharArray()); + cert = (X509Certificate) ks.getCertificate(alias); + System.out.println(cert); + } + } + } catch (Exception e) { + log.error(e); + } + + } + + @Override + public List<STALResponse> handleRequest(List<? extends STALRequest> requestList) { + + List<STALResponse> responses = new ArrayList<STALResponse>(); + for (STALRequest request : requestList) { + + log.debug("Got STALRequest " + request + "."); + + if (request instanceof InfoboxReadRequest) { + + String infoboxIdentifier = ((InfoboxReadRequest) request) + .getInfoboxIdentifier(); + InputStream stream = getClass().getClassLoader().getResourceAsStream( + "at/gv/egiz/stal/dummy/infoboxes4/" + infoboxIdentifier + ".bin"); + + STALResponse response; + if (stream != null) { + + log.debug("Infobox " + infoboxIdentifier + " found."); + + byte[] infobox; + try { + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + int b; + while ((b = stream.read()) != -1) { + buffer.write(b); + } + infobox = buffer.toByteArray(); + } catch (IOException e) { + throw new RuntimeException(e); + } + + InfoboxReadResponse infoboxReadResponse = new InfoboxReadResponse(); + infoboxReadResponse.setInfoboxValue(infobox); + response = infoboxReadResponse; + + } else if ((infoboxIdentifier.equals("SecureSignatureKeypair")) ||(infoboxIdentifier.equals("CertifiedKeypair"))) { + try { + InfoboxReadResponse infoboxReadResponse = new InfoboxReadResponse(); + infoboxReadResponse.setInfoboxValue(cert.getEncoded()); + response = infoboxReadResponse; + } catch (CertificateEncodingException e) { + log.error(e); + response = new ErrorResponse(); + } + } else { + + log.debug("Infobox " + infoboxIdentifier + " not found."); + + response = new ErrorResponse(); + } + responses.add(response); + + } else if (request instanceof SignRequest) { + try { + + SignRequest signReq = (SignRequest) request; + Signature s = Signature.getInstance("SHA1withRSA"); + s.initSign(privateKey); + s.update(signReq.getSignedInfo()); + byte[] sigVal = s.sign(); + SignResponse resp = new SignResponse(); + resp.setSignatureValue(sigVal); + responses.add(resp); + } catch (Exception e) { + log.error(e); + responses.add(new ErrorResponse()); + } + + } else { + + log.debug("Request not implemented."); + + responses.add(new ErrorResponse()); + } + + } + + return responses; + } +} 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 86223854..57925240 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java @@ -28,6 +28,7 @@ // package at.gv.egiz.smcc; +import at.gv.egiz.smcc.util.SMCCHelper; import java.nio.charset.Charset; import javax.smartcardio.CardChannel; @@ -104,9 +105,12 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { public ACOSCard() { super("at/gv/egiz/smcc/ACOSCard"); - pinSpecs.add(PINSPEC_INF, new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("inf.pin.name"), KID_PIN_INF, null)); - pinSpecs.add(PINSPEC_DEC, new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("dec.pin.name"), KID_PIN_DEC, null)); - pinSpecs.add(PINSPEC_SIG, new PINSpec(6, 10, "[0-9]", getResourceBundle().getString("sig.pin.name"), KID_PIN_SIG, null)); + pinSpecs.add(PINSPEC_INF, + new PINSpec(0, 8, "[0-9]", getResourceBundle().getString("inf.pin.name"), KID_PIN_INF, AID_DEC)); + pinSpecs.add(PINSPEC_DEC, + new PINSpec(0, 8, "[0-9]", getResourceBundle().getString("dec.pin.name"), KID_PIN_DEC, AID_DEC)); + pinSpecs.add(PINSPEC_SIG, + new PINSpec(0, 8, "[0-9]", getResourceBundle().getString("sig.pin.name"), KID_PIN_SIG, AID_SIG)); } /* (non-Javadoc) @@ -334,14 +338,13 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { CardChannel channel = getCardChannel(); - byte[] asciiPIN = pin.getBytes(Charset.forName("ASCII")); - byte[] encodedPIN = new byte[8]; - System.arraycopy(asciiPIN, 0, encodedPIN, 0, Math.min(asciiPIN.length, - encodedPIN.length)); - ResponseAPDU resp; try { - resp = transmit(channel, new CommandAPDU(0x00, 0x20, 0x00, kid, encodedPIN), false); + if (pin != null) { + resp = transmit(channel, new CommandAPDU(0x00, 0x20, 0x00, kid, encodePINBlock(pin)), false); + } else { + resp = transmit(channel, new CommandAPDU(0x00, 0x20, 0x00, kid), false); + } } catch (CardException ex) { log.error("smart card communication failed: " + ex.getMessage()); throw new SignatureCardException("smart card communication failed: " + ex.getMessage(), ex); @@ -419,7 +422,28 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { } } + @Override public String toString() { return "a-sign premium"; } + + /** + * ASCII encoded pin, padded with 0x00 + * @param pin + * @return a 8 byte pin block + */ + @Override + public byte[] encodePINBlock(String pin) { + byte[] asciiPIN = pin.getBytes(Charset.forName("ASCII")); + byte[] encodedPIN = new byte[8]; + System.arraycopy(asciiPIN, 0, encodedPIN, 0, Math.min(asciiPIN.length, + encodedPIN.length)); +// System.out.println("ASCII encoded PIN block: " + SMCCHelper.toString(encodedPIN)); + return encodedPIN; + } + + @Override + public void activatePIN(byte kid, byte[] contextAID, String pin) throws SignatureCardException { + throw new SignatureCardException("PIN activation not supported by this card"); + } } 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 cb068725..63301bd1 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java @@ -28,14 +28,13 @@ // package at.gv.egiz.smcc; +import at.gv.egiz.smcc.util.SMCCHelper; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Locale; -import java.util.Map; import java.util.ResourceBundle; import javax.smartcardio.ATR; @@ -443,4 +442,54 @@ public abstract class AbstractSignatureCard implements SignatureCard { public List<PINSpec> getPINSpecs() { return pinSpecs; } + + public void changePIN(byte kid, byte[] contextAID, String oldPIN, String newPIN) throws SignatureCardException, VerificationFailedException { + Card icc = getCard(); + try { + icc.beginExclusive(); + CardChannel channel = icc.getBasicChannel(); + + if (contextAID != null) { + ResponseAPDU responseAPDU = transmit(channel, + new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, contextAID)); + if (responseAPDU.getSW() != 0x9000) { + icc.endExclusive(); + String msg = "Failed to change PIN " + SMCCHelper.toString(new byte[]{kid}) + + ": Failed to select AID " + SMCCHelper.toString(contextAID) + + ": " + SMCCHelper.toString(responseAPDU.getBytes()); + log.error(msg); + throw new SignatureCardException(msg); + } + } + + byte[] cmd = new byte[16]; + System.arraycopy(encodePINBlock(oldPIN), 0, cmd, 0, 8); + System.arraycopy(encodePINBlock(newPIN), 0, cmd, 8, 8); + + ResponseAPDU responseAPDU = transmit(channel, + new CommandAPDU(0x00, 0x24, 0x00, kid, cmd), false); + + icc.endExclusive(); + + if (responseAPDU.getSW1() == 0x63 && responseAPDU.getSW2() >> 4 == 0xc) { + int retries = responseAPDU.getSW2() & 0x0f; + log.error("Failed VERIFY PIN, " + retries + " tries left"); + throw new VerificationFailedException(retries); + } + if (responseAPDU.getSW() != 0x9000) { + String msg = "Failed to change PIN " + + SMCCHelper.toString(new byte[]{kid}) + ": " + + SMCCHelper.toString(responseAPDU.getBytes()); + log.error(msg); + throw new SignatureCardException(msg); + } + + } catch (CardException ex) { + log.error("Failed to change PIN: " + ex.getMessage()); + throw new SignatureCardException(ex.getMessage(), ex); + } + } + + abstract byte[] encodePINBlock(String pin); + } 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 ae43629e..b1288f74 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java @@ -28,9 +28,9 @@ // package at.gv.egiz.smcc; -import java.math.BigInteger; +import at.gv.egiz.smcc.util.SMCCHelper; import java.util.Arrays; - +import javax.smartcardio.Card; import javax.smartcardio.CardChannel; import javax.smartcardio.CardException; import javax.smartcardio.CommandAPDU; @@ -162,8 +162,14 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard */ public STARCOSCard() { super("at/gv/egiz/smcc/STARCOSCard"); - pinSpecs.add(PINSPEC_CARD, new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("card.pin.name"), KID_PIN_CARD, null)); - pinSpecs.add(PINSPEC_SS, new PINSpec(6, 10, "[0-9]", getResourceBundle().getString("sig.pin.name"), KID_PIN_SS, AID_DF_SS)); + pinSpecs.add(PINSPEC_CARD, + new PINSpec(4, 12, "[0-9]", + getResourceBundle().getString("card.pin.name"), + KID_PIN_CARD, null)); + pinSpecs.add(PINSPEC_SS, + new PINSpec(6, 12, "[0-9]", + getResourceBundle().getString("sig.pin.name"), + KID_PIN_SS, AID_DF_SS)); } @Override @@ -491,21 +497,8 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard if (pin == null) { resp = transmit(channel, new CommandAPDU(0x00, 0x20, 0x00, kid)); } else { - // PIN length in bytes - int len = (int) Math.ceil(pin.length() / 2); - // BCD encode PIN and marshal PIN block - byte[] pinBytes = new BigInteger(pin, 16).toByteArray(); - byte[] pinBlock = new byte[8]; - if (len < pinBytes.length) { - System.arraycopy(pinBytes, pinBytes.length - len, pinBlock, 1, len); - } else { - System.arraycopy(pinBytes, 0, pinBlock, len - pinBytes.length + 1, - pinBytes.length); - } - pinBlock[0] = (byte) (0x20 + len * 2); - Arrays.fill(pinBlock, len + 1, 8, (byte) 0xff); - + byte[] pinBlock = encodePINBlock(pin); resp = transmit(channel, new CommandAPDU(0x00, 0x20, 0x00, kid, pinBlock), false); } @@ -553,6 +546,65 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard return "e-card"; } - + /** + * BCD encodes the pin, pads with 0xFF and prepends the pins length + * @param pin + * @return a 8 byte pin block consisting of length byte (0x2X), + * the BCD encoded pin and a 0xFF padding + */ + @Override + public byte[] encodePINBlock(String pin) { + char[] pinChars = pin.toCharArray(); + int numDigits = pinChars.length; + int numBytes = (int) Math.ceil(numDigits/2.0); + + byte[] pinBlock = new byte[8]; + pinBlock[0] = (byte) (0x20 | numDigits); + + for (int i = 0; i < numBytes; i++) { + int p1 = 16*Character.digit(pinChars[i*2], 16); + int p2 = (i*2+1 < numDigits) ? Character.digit(pinChars[i*2+1], 16) : 0xf; + pinBlock[i+1] = (byte) (p1 + p2); + } + Arrays.fill(pinBlock, numBytes + 1, pinBlock.length, (byte) 0xff); +// log.trace("BCD encoded PIN block: " + SMCCHelper.toString(pinBlock)); + + return pinBlock; + } + + public void activatePIN(byte kid, byte[] contextAID, String pin) throws SignatureCardException { + Card icc = getCard(); + try { + icc.beginExclusive(); + CardChannel channel = icc.getBasicChannel(); + + if (contextAID != null) { + ResponseAPDU responseAPDU = transmit(channel, + new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, contextAID)); + if (responseAPDU.getSW() != 0x9000) { + icc.endExclusive(); + String msg = "Failed to activate PIN " + SMCCHelper.toString(new byte[]{kid}) + + ": Failed to select AID " + SMCCHelper.toString(contextAID) + + ": " + SMCCHelper.toString(responseAPDU.getBytes()); + log.error(msg); + throw new SignatureCardException(msg); + } + } + + ResponseAPDU responseAPDU = transmit(channel, + new CommandAPDU(0x00, 0x24, 0x01, kid, encodePINBlock(pin)), false); + + icc.endExclusive(); + + if (responseAPDU.getSW() != 0x9000) { + String msg = "Failed to activate PIN " + SMCCHelper.toString(new byte[]{kid}) + ": " + SMCCHelper.toString(responseAPDU.getBytes()); + log.error(msg); + throw new SignatureCardException(msg); + } + } catch (CardException ex) { + log.error("Failed to activate PIN: " + ex.getMessage()); + throw new SignatureCardException(ex.getMessage(), ex); + } + } } 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 8dc4ac2a..57aeb994 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java @@ -403,4 +403,12 @@ public class SWCard implements SignatureCard { return new ArrayList<PINSpec>(); } + @Override + public void changePIN(byte kid, byte[] contextAID, String oldPIN, String newPIN) throws SignatureCardException, VerificationFailedException { + } + + @Override + public void activatePIN(byte kid, byte[] contextAID, String pin) throws SignatureCardException { + } + } 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 1e5e09c8..a88593bc 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java @@ -31,7 +31,6 @@ package at.gv.egiz.smcc; import java.util.List; import java.util.Locale; -import java.util.Map; import javax.smartcardio.Card; import javax.smartcardio.CardTerminal; @@ -135,11 +134,19 @@ public interface SignatureCard { */ public int verifyPIN(String pin, byte kid) throws LockedException, NotActivatedException, SignatureCardException; + public void changePIN(byte kid, byte[] contextAID, + String oldPIN, String newPIN) + throws SignatureCardException, VerificationFailedException; + + public void activatePIN(byte kid, byte[] contextAID, + String pin) + throws SignatureCardException; + /** * Sets the local for evtl. required callbacks (e.g. PINSpec) * @param locale must not be null; */ public void setLocale(Locale locale); - + } |