Commit ab7ef744 authored by Tobias Wich's avatar Tobias Wich
Browse files

Merge branch 'master' into reqesidta

parents 3ca2efe7 8ed7db8f
......@@ -47,6 +47,7 @@ import org.bouncycastle.tls.TlsServerCertificate;
import org.openecard.binding.tctoken.DocumentHash;
import org.openecard.common.DynamicContext;
import org.openecard.common.ECardConstants;
import org.openecard.common.ECardException;
import org.openecard.common.I18n;
import org.openecard.common.ThreadTerminateException;
import org.openecard.common.WSHelper;
......@@ -193,9 +194,6 @@ public class PACEStep implements ProtocolStep<DIDAuthenticate, DIDAuthenticateRe
return response;
}
CHAT requiredCHAT = new CHAT(eac1Input.getRequiredCHAT());
CHAT optionalCHAT = new CHAT(eac1Input.getOptionalCHAT());
// get the PACEMarker
CardStateEntry cardState = (CardStateEntry) internalData.get(EACConstants.IDATA_CARD_STATE_ENTRY);
PACEMarkerType paceMarker = getPaceMarker(cardState, passwordType);
......@@ -204,13 +202,16 @@ public class PACEStep implements ProtocolStep<DIDAuthenticate, DIDAuthenticateRe
// Verify that the certificate description matches the terminal certificate
CardVerifiableCertificate taCert = certChain.getTerminalCertificate();
CardVerifiableCertificateVerifier.verify(taCert, certDescription);
// Verify that the required CHAT matches the terminal certificate's CHAT
// get CHAT values
CHAT taCHAT = taCert.getCHAT();
CHAT requiredCHAT = new CHAT(eac1Input.getRequiredCHAT());
CHAT optionalCHAT = new CHAT(eac1Input.getOptionalCHAT());
// Check that we got an authentication terminal terminal certificate. We abort the process in case there is
// an other role.
if (taCHAT.getRole() != CHAT.Role.AUTHENTICATION_TERMINAL) {
String msg = "Unsupported terminal type in Terminal Certificate referenced. Refernced terminal type is " +
String msg = "Unsupported terminal type in Terminal Certificate referenced. Referenced terminal type is " +
taCHAT.getRole().toString() + ".";
response.setResult(WSHelper.makeResultError(ECardConstants.Minor.App.INCORRECT_PARM, msg));
dynCtx.put(EACProtocol.AUTHENTICATION_DONE, false);
......@@ -218,6 +219,8 @@ public class PACEStep implements ProtocolStep<DIDAuthenticate, DIDAuthenticateRe
}
CHATVerifier.verfiy(taCHAT, requiredCHAT);
// enable CAN_ALLOWED value, gets deleted by the restrict afterwards if not allowed
optionalCHAT.setSpecialFunctions(CHAT.SpecialFunction.CAN_ALLOWED, true);
// remove overlapping values from optional chat
optionalCHAT.restrictAccessRights(taCHAT);
......@@ -308,11 +311,12 @@ public class PACEStep implements ProtocolStep<DIDAuthenticate, DIDAuthenticateRe
switch (minor) {
case ECardConstants.Minor.IFD.CANCELLATION_BY_USER:
case ECardConstants.Minor.SAL.CANCELLATION_BY_USER:
case ECardConstants.Minor.Disp.TIMEOUT:
needsTermination = true;
}
}
// terminate activation thread
if (needsTermination) {
// terminate activation thread if it has not been interrupted already
if (needsTermination && guiResult != ResultStatus.INTERRUPTED) {
Thread actThread = (Thread) dynCtx2.get(TR03112Keys.ACTIVATION_THREAD);
if (actThread != null) {
LOG.debug("Interrupting activation thread.");
......@@ -400,7 +404,7 @@ public class PACEStep implements ProtocolStep<DIDAuthenticate, DIDAuthenticateRe
String msg = ex.getMessage();
response.setResult(WSHelper.makeResultError(ECardConstants.Minor.SAL.EAC.DOC_VALID_FAILED, msg));
dynCtx.put(EACProtocol.AUTHENTICATION_DONE, false);
} catch (WSHelper.WSException e) {
} catch (ECardException e) {
LOG.error(e.getMessage(), e);
response.setResult(e.getResult());
dynCtx.put(EACProtocol.AUTHENTICATION_DONE, false);
......@@ -408,6 +412,14 @@ public class PACEStep implements ProtocolStep<DIDAuthenticate, DIDAuthenticateRe
LOG.error(ex.getMessage(), ex);
response.setResult(WSHelper.makeResultError(ECardConstants.Minor.App.INCORRECT_PARM, ex.getMessage()));
dynCtx.put(EACProtocol.AUTHENTICATION_DONE, false);
} catch (InterruptedException e) {
LOG.error(e.getMessage(), e);
response.setResult(WSHelper.makeResultUnknownError(e.getMessage()));
dynCtx.put(EACProtocol.AUTHENTICATION_DONE, false);
Thread guiThread = (Thread) dynCtx.get(TR03112Keys.OPEN_USER_CONSENT_THREAD);
if (guiThread != null) {
guiThread.interrupt();
}
} catch (Exception e) {
LOG.error(e.getMessage(), e);
response.setResult(WSHelper.makeResultUnknownError(e.getMessage()));
......@@ -437,7 +449,7 @@ public class PACEStep implements ProtocolStep<DIDAuthenticate, DIDAuthenticateRe
/**
* Perform all checks as described in BSI TR-03112-7 3.4.4.
*
* @param certDescription CertificateDescription of the eService Certificate
* @param certDescription CertificateDescription of the eService CV Certificate
* @param dynCtx Dynamic Context
* @return a {@link Result} set according to the results of the checks
*/
......@@ -445,9 +457,9 @@ public class PACEStep implements ProtocolStep<DIDAuthenticate, DIDAuthenticateRe
Object tokenChecks = dynCtx.get(TR03112Keys.TCTOKEN_CHECKS);
// omit these checks if explicitly disabled
if (convertToBoolean(tokenChecks)) {
boolean checkPassed = checkEserviceCertificate(certDescription, dynCtx);
boolean checkPassed = checkEidServerCertificate(certDescription, dynCtx);
if (! checkPassed) {
String msg = "Hash of eService certificate is NOT contained in the CertificateDescription.";
String msg = "Hash of eID-Server certificate is NOT contained in the CertificateDescription.";
// TODO check for the correct minor type
Result r = WSHelper.makeResultError(ECardConstants.Minor.SAL.PREREQUISITES_NOT_SATISFIED, msg);
return r;
......@@ -493,13 +505,19 @@ public class PACEStep implements ProtocolStep<DIDAuthenticate, DIDAuthenticateRe
}
}
private boolean checkEserviceCertificate(CertificateDescription certDescription, DynamicContext dynCtx) {
TlsServerCertificate certificate = (TlsServerCertificate) dynCtx.get(TR03112Keys.ESERVICE_CERTIFICATE);
if (certificate != null) {
return TR03112Utils.isInCommCertificates(certificate, certDescription.getCommCertificates(), "eService");
private boolean checkEidServerCertificate(CertificateDescription certDescription, DynamicContext dynCtx) {
Boolean sameChannel = (Boolean) dynCtx.get(TR03112Keys.SAME_CHANNEL);
if (Boolean.TRUE.equals(sameChannel)) {
LOG.debug("eID-Server certificate is not check explicitly due to attached eID-Server case.");
return true;
} else {
LOG.error("No eService TLS Certificate set in Dynamic Context.");
return false;
TlsServerCertificate certificate = (TlsServerCertificate) dynCtx.get(TR03112Keys.EIDSERVER_CERTIFICATE);
if (certificate != null) {
return TR03112Utils.isInCommCertificates(certificate, certDescription.getCommCertificates(), "eID-Server");
} else {
LOG.error("No eID-Server TLS Certificate set in Dynamic Context.");
return false;
}
}
}
......
......@@ -30,6 +30,7 @@ import org.openecard.addon.sal.ProtocolStep;
import org.openecard.binding.tctoken.TR03112Keys;
import org.openecard.common.DynamicContext;
import org.openecard.common.ECardConstants;
import org.openecard.common.ECardException;
import org.openecard.common.WSHelper;
import org.openecard.common.interfaces.Dispatcher;
import org.openecard.crypto.common.asn1.cvc.CardVerifiableCertificate;
......@@ -136,6 +137,10 @@ public class TerminalAuthenticationStep implements ProtocolStep<DIDAuthenticate,
}
response.setAuthenticationProtocolData(eac2Output.getAuthDataType());
} catch (ECardException e) {
LOG.error(e.getMessage(), e);
response.setResult(e.getResult());
dynCtx.put(EACProtocol.AUTHENTICATION_DONE, false);
} catch (Exception e) {
LOG.error(e.getMessage(), e);
response.setResult(WSHelper.makeResultUnknownError(e.getMessage()));
......
/****************************************************************************
* Copyright (C) 2019 ecsec GmbH.
* All rights reserved.
* Contact: ecsec GmbH (info@ecsec.de)
*
* This file may be used in accordance with the terms and conditions
* contained in a signed written agreement between you and ecsec GmbH.
*
***************************************************************************/
package org.openecard.sal.protocol.eac.gui;
import iso.std.iso_iec._24727.tech.schema.DIDAuthenticationDataType;
import iso.std.iso_iec._24727.tech.schema.EstablishChannel;
import iso.std.iso_iec._24727.tech.schema.EstablishChannelResponse;
import java.util.Map;
import javax.xml.parsers.ParserConfigurationException;
import org.openecard.binding.tctoken.TR03112Keys;
import org.openecard.common.DynamicContext;
import org.openecard.common.ECardConstants;
import org.openecard.common.anytype.AuthDataMap;
import org.openecard.common.anytype.AuthDataResponse;
import org.openecard.common.interfaces.Dispatcher;
import org.openecard.common.util.ByteUtils;
import org.openecard.gui.definition.PasswordField;
import org.openecard.gui.executor.ExecutionResults;
import org.openecard.gui.executor.StepAction;
import org.openecard.sal.protocol.eac.EACData;
import org.openecard.sal.protocol.eac.anytype.PACEInputType;
import org.openecard.sal.protocol.eac.anytype.PasswordID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author Tobias Wich
*/
public abstract class AbstractPasswordStepAction extends StepAction {
private static final Logger LOG = LoggerFactory.getLogger(AbstractPasswordStepAction.class);
private static final String PIN_ID_CAN = "2";
protected final EACData eacData;
protected final boolean capturePin;
protected final byte[] slotHandle;
protected final Dispatcher dispatcher;
protected final PINStep step;
protected final DynamicContext ctx;
public AbstractPasswordStepAction(EACData eacData, boolean capturePin, byte[] slotHandle, Dispatcher dispatcher,
PINStep step) {
super(step);
this.eacData = eacData;
this.capturePin = capturePin;
this.slotHandle = slotHandle;
this.dispatcher = dispatcher;
this.step = step;
this.ctx = DynamicContext.getInstance(TR03112Keys.INSTANCE_KEY);
}
protected EstablishChannelResponse performPACEWithPIN(Map<String, ExecutionResults> oldResults) {
DIDAuthenticationDataType protoData = eacData.didRequest.getAuthenticationProtocolData();
AuthDataMap paceAuthMap;
try {
paceAuthMap = new AuthDataMap(protoData);
} catch (ParserConfigurationException ex) {
LOG.error("Failed to read EAC Protocol data.", ex);
return null;
}
AuthDataResponse paceInputMap = paceAuthMap.createResponse(protoData);
if (capturePin) {
ExecutionResults executionResults = oldResults.get(getStepID());
PasswordField p = (PasswordField) executionResults.getResult(PINStep.PIN_FIELD);
char[] pinIn = p.getValue();
// let the user enter the pin again, when there is none entered
// TODO: check pin length and possibly allowed charset with CardInfo file
if (pinIn.length == 0) {
return null;
} else {
// NOTE: saving pin as string prevents later removal of the value from memory !!!
paceInputMap.addElement(PACEInputType.PIN, new String(pinIn));
}
}
// perform PACE
paceInputMap.addElement(PACEInputType.PIN_ID, PasswordID.parse(eacData.pinID).getByteAsString());
paceInputMap.addElement(PACEInputType.CHAT, eacData.selectedCHAT.toString());
String certDesc = ByteUtils.toHexString(eacData.rawCertificateDescription);
paceInputMap.addElement(PACEInputType.CERTIFICATE_DESCRIPTION, certDesc);
EstablishChannel eChannel = createEstablishChannelStructure(paceInputMap);
return (EstablishChannelResponse) dispatcher.safeDeliver(eChannel);
}
protected EstablishChannelResponse performPACEWithCAN(Map<String, ExecutionResults> oldResults) {
DIDAuthenticationDataType paceInput = new DIDAuthenticationDataType();
paceInput.setProtocol(ECardConstants.Protocol.PACE);
AuthDataMap tmp;
try {
tmp = new AuthDataMap(paceInput);
} catch (ParserConfigurationException ex) {
LOG.error("Failed to read empty Protocol data.", ex);
return null;
}
AuthDataResponse paceInputMap = tmp.createResponse(paceInput);
if (capturePin) {
ExecutionResults executionResults = oldResults.get(getStepID());
PasswordField canField = (PasswordField) executionResults.getResult(PINStep.CAN_FIELD);
String canValue = new String(canField.getValue());
if (canValue.length() != 6) {
// let the user enter the can again, when input verification failed
return null;
} else {
paceInputMap.addElement(PACEInputType.PIN, canValue);
}
}
paceInputMap.addElement(PACEInputType.PIN_ID, PIN_ID_CAN);
// perform PACE by EstablishChannelCommand
EstablishChannel eChannel = createEstablishChannelStructure(paceInputMap);
return (EstablishChannelResponse) dispatcher.safeDeliver(eChannel);
}
protected EstablishChannel createEstablishChannelStructure(AuthDataResponse paceInputMap) {
// EstablishChannel
EstablishChannel establishChannel = new EstablishChannel();
establishChannel.setSlotHandle(slotHandle);
establishChannel.setAuthenticationProtocolData(paceInputMap.getResponse());
establishChannel.getAuthenticationProtocolData().setProtocol(ECardConstants.Protocol.PACE);
return establishChannel;
}
}
/****************************************************************************
* Copyright (C) 2019 ecsec GmbH.
* All rights reserved.
* Contact: ecsec GmbH (info@ecsec.de)
*
* This file is part of the Open eCard App.
*
* GNU General Public License Usage
* This file may be used under the terms of the GNU General Public
* License version 3.0 as published by the Free Software Foundation
* and appearing in the file LICENSE.GPL included in the packaging of
* this file. Please review the following information to ensure the
* GNU General Public License version 3.0 requirements will be met:
* http://www.gnu.org/copyleft/gpl.html.
*
* Other Usage
* Alternatively, this file may be used in accordance with the terms
* and conditions contained in a signed written agreement between
* you and ecsec GmbH.
*
***************************************************************************/
package org.openecard.sal.protocol.eac.gui;
import iso.std.iso_iec._24727.tech.schema.EstablishChannelResponse;
import java.util.Map;
import org.openecard.common.ECardConstants;
import org.openecard.common.I18n;
import org.openecard.common.WSHelper;
import org.openecard.common.WSHelper.WSException;
import org.openecard.common.interfaces.Dispatcher;
import org.openecard.gui.StepResult;
import org.openecard.gui.executor.ExecutionResults;
import org.openecard.gui.executor.StepActionResult;
import org.openecard.gui.executor.StepActionResultStatus;
import org.openecard.sal.protocol.eac.EACData;
import org.openecard.sal.protocol.eac.EACProtocol;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* StepAction for capturing the user PIN on the EAC GUI.
*
* @author Tobias Wich
* @author Hans-Martin Haase
*/
public class CANStepAction extends AbstractPasswordStepAction {
private static final Logger LOG = LoggerFactory.getLogger(CANStepAction.class);
// Translation constants
private static final String ERROR_CARD_REMOVED = "action.error.card.removed";
private static final String ERROR_TITLE = "action.error.title";
private static final String ERROR_UNKNOWN = "action.error.unknown";
private final I18n lang = I18n.getTranslation("pace");
private final I18n langPin = I18n.getTranslation("pinplugin");
public CANStepAction(EACData eacData, boolean capturePin, byte[] slotHandle, Dispatcher dispatcher, PINStep step) {
super(eacData, capturePin, slotHandle, dispatcher, step);
}
@Override
public StepActionResult perform(Map<String, ExecutionResults> oldResults, StepResult result) {
try {
EstablishChannelResponse establishChannelResponse = performPACEWithPIN(oldResults);
if (establishChannelResponse.getResult().getResultMajor().equals(ECardConstants.Major.ERROR)) {
if (establishChannelResponse.getResult().getResultMinor().equals(ECardConstants.Minor.IFD.AUTHENTICATION_FAILED)) {
// repeat the step
LOG.info("Wrong CAN entered, trying again.");
return new StepActionResult(StepActionResultStatus.REPEAT);
} else {
WSHelper.checkResult(establishChannelResponse);
}
}
eacData.paceResponse = establishChannelResponse;
// PACE completed successfully, proceed with next step
ctx.put(EACProtocol.PACE_EXCEPTION, null);
return new StepActionResult(StepActionResultStatus.NEXT);
} catch (WSException ex) {
// This is for PIN Pad Readers in case the user pressed the cancel button on the reader.
if (ex.getResultMinor().equals(ECardConstants.Minor.IFD.CANCELLATION_BY_USER)) {
LOG.error("User canceled the authentication manually.", ex);
return new StepActionResult(StepActionResultStatus.CANCEL);
}
// for people which think they have to remove the card in the process
if (ex.getResultMinor().equals(ECardConstants.Minor.IFD.INVALID_SLOT_HANDLE)) {
LOG.error("The SlotHandle was invalid so probably the user removed the card or an reset occurred.", ex);
return new StepActionResult(StepActionResultStatus.REPEAT,
new ErrorStep(lang.translationForKey(ERROR_TITLE),
langPin.translationForKey(ERROR_CARD_REMOVED), ex));
}
// repeat the step
LOG.error("An unknown error occured while trying to verify the PIN.");
return new StepActionResult(StepActionResultStatus.REPEAT,
new ErrorStep(langPin.translationForKey(ERROR_TITLE),
langPin.translationForKey(ERROR_UNKNOWN), ex));
}
}
}
......@@ -44,6 +44,7 @@ import org.openecard.gui.executor.StepActionResultStatus;
import org.openecard.sal.protocol.eac.EACData;
import org.openecard.sal.protocol.eac.EACProtocol;
import org.openecard.sal.protocol.eac.anytype.PACEMarkerType;
import org.openecard.sal.protocol.eac.anytype.PasswordID;
/**
......@@ -86,27 +87,34 @@ public class CHATStepAction extends StepAction {
byte[] slotHandle = (byte[]) ctx.get(EACProtocol.SLOT_HANDLE);
Dispatcher dispatcher = (Dispatcher) ctx.get(EACProtocol.DISPATCHER);
Step pinStep;
Step nextStep;
assert(status != null);
switch (status) {
case BLOCKED:
pinStep = new ErrorStep(LANG.translationForKey("step_error_title_blocked", PIN),
nextStep = new ErrorStep(LANG.translationForKey("step_error_title_blocked", PIN),
LANG.translationForKey("step_error_pin_blocked", PIN, PIN, PUK, PIN),
WSHelper.createException(WSHelper.makeResultError(ECardConstants.Minor.IFD.PASSWORD_BLOCKED, "Password blocked.")));
break;
case DEACTIVATED:
pinStep = new ErrorStep(LANG.translationForKey("step_error_title_deactivated"),
nextStep = new ErrorStep(LANG.translationForKey("step_error_title_deactivated"),
LANG.translationForKey("step_error_pin_deactivated"),
WSHelper.createException(WSHelper.makeResultError(ECardConstants.Minor.IFD.PASSWORD_SUSPENDED, "Card deactivated.")));
break;
default:
pinStep = new PINStep(eacData, !nativePace, paceMarker, status);
PINStep pinStep = new PINStep(eacData, !nativePace, paceMarker, status);
nextStep = pinStep;
pinStep.setBackgroundTask(bTask);
StepAction pinAction = new PINStepAction(eacData, !nativePace, slotHandle, dispatcher, (PINStep) pinStep, status);
StepAction pinAction;
if (eacData.pinID == PasswordID.CAN.getByte()) {
pinStep.setStatus(EacPinStatus.RC3);
pinAction = new CANStepAction(eacData, !nativePace, slotHandle, dispatcher, pinStep);
} else {
pinAction = new PINStepAction(eacData, !nativePace, slotHandle, dispatcher, pinStep, status);
}
pinStep.setAction(pinAction);
}
return new StepActionResult(StepActionResultStatus.NEXT, pinStep);
return new StepActionResult(StepActionResultStatus.NEXT, nextStep);
} else {
// cancel can not happen, so only back is left to be handled
return new StepActionResult(StepActionResultStatus.BACK);
......@@ -142,6 +150,12 @@ public class CHATStepAction extends StepAction {
}
}
}
// change PIN ID to CAN if CAN ALLOWED is used
if (eacData.selectedCHAT.getSpecialFunctions().getOrDefault(CHAT.SpecialFunction.CAN_ALLOWED, Boolean.FALSE)) {
eacData.pinID = PasswordID.CAN.getByte();
eacData.passwordType = PasswordID.parse(eacData.pinID).getString();
}
}
/**
......
......@@ -29,6 +29,7 @@ import org.openecard.gui.definition.PasswordField;
import org.openecard.gui.definition.Step;
import org.openecard.gui.definition.Text;
import org.openecard.sal.protocol.eac.EACData;
import org.openecard.sal.protocol.eac.anytype.PasswordID;
/**
......@@ -38,7 +39,7 @@ import org.openecard.sal.protocol.eac.EACData;
* @author Tobias Wich
* @author Moritz Horsch
*/
public class PINStep extends Step {
public final class PINStep extends Step {
private static final I18n LANG_EAC = I18n.getTranslation("eac");
private static final I18n LANG_PACE = I18n.getTranslation("pace");
......@@ -60,6 +61,7 @@ public class PINStep extends Step {
private final String pinType;
private final PACEMarkerType paceMarker;
private final boolean hasAttemptsCounter;
private EacPinStatus status;
......@@ -67,6 +69,7 @@ public class PINStep extends Step {
super(STEP_ID, "Dummy-Title");
this.pinType = LANG_PACE.translationForKey(eacData.passwordType);
this.paceMarker = paceMarker;
this.hasAttemptsCounter = eacData.pinID != PasswordID.CAN.getByte();
setTitle(LANG_PACE.translationForKey(TITLE, pinType));
setDescription(LANG_PACE.translationForKey(STEP_DESCRIPTION));
setReversible(false);
......@@ -116,10 +119,12 @@ public class PINStep extends Step {
pinInputField.setMaxLength(paceMarker.getMaxLength());
getInputInfoUnits().add(pinInputField);
Text attemptCount = new Text();
attemptCount.setText(LANG_PACE.translationForKey("step_pin_retrycount", 3));
attemptCount.setID(PIN_ATTEMPTS_ID);
getInputInfoUnits().add(attemptCount);
if (hasAttemptsCounter) {
Text attemptCount = new Text();
attemptCount.setText(LANG_PACE.translationForKey("step_pin_retrycount", 3));
attemptCount.setID(PIN_ATTEMPTS_ID);
getInputInfoUnits().add(attemptCount);
}
Text notice = new Text();
notice.setText(LANG_EAC.translationForKey(NOTICE, pinType));
......@@ -136,10 +141,12 @@ public class PINStep extends Step {
notice.setText(LANG_EAC.translationForKey(NOTICE, pinType));
getInputInfoUnits().add(notice);
Text attemptCount = new Text();
attemptCount.setText(LANG_PACE.translationForKey("step_pin_retrycount", 3));
attemptCount.setID(PIN_ATTEMPTS_ID);
getInputInfoUnits().add(attemptCount);
if (hasAttemptsCounter) {
Text attemptCount = new Text();
attemptCount.setText(LANG_PACE.translationForKey("step_pin_retrycount", 3));
attemptCount.setID(PIN_ATTEMPTS_ID);
getInputInfoUnits().add(attemptCount);
}
}
protected void addCANEntry() {
......
/****************************************************************************
* Copyright (C) 2012-2018 ecsec GmbH.
* Copyright (C) 2012-2019 ecsec GmbH.
* All rights reserved.
* Contact: ecsec GmbH (info@ecsec.de)
*
......@@ -22,31 +22,19 @@
package org.openecard.sal.protocol.eac.gui;
import iso.std.iso_iec._24727.tech.schema.DIDAuthenticationDataType;
import iso.std.iso_iec._24727.tech.schema.EstablishChannel;
import iso.std.iso_iec._24727.tech.schema.EstablishChannelResponse;
import java.util.Map;
import javax.xml.parsers.ParserConfigurationException;
import org.openecard.binding.tctoken.TR03112Keys;
import org.openecard.common.DynamicContext;
import org.openecard.common.ECardConstants;
import org.openecard.common.I18n;
import org.openecard.common.WSHelper;
import org.openecard.common.WSHelper.WSException;
import org.openecard.common.anytype.AuthDataMap;
import org.openecard.common.anytype.AuthDataResponse;
import org.openecard.common.interfaces.Dispatcher;
import org.openecard.common.util.ByteUtils;
import org.openecard.gui.StepResult;
import org.openecard.gui.definition.PasswordField;
import org.openecard.gui.executor.ExecutionResults;
import org.openecard.gui.executor.StepAction;
import org.openecard.gui.executor.StepActionResult;
import org.openecard.gui.executor.StepActionResultStatus;
import org.openecard.sal.protocol.eac.EACData;
import org.openecard.sal.protocol.eac.EACProtocol;
import org.openecard.sal.protocol.eac.anytype.PACEInputType;
import org.openecard.sal.protocol.eac.anytype.PasswordID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -57,12 +45,10 @@ import org.slf4j.LoggerFactory;
* @author Tobias Wich
* @author Hans-Martin Haase
*/
public class PINStepAction extends StepAction {
public class PINStepAction extends AbstractPasswordStepAction {
private static final<