use of iso.std.iso_iec._24727.tech.schema.EstablishChannelResponse in project open-ecard by ecsec.
the class PACEProtocol method establish.
@Override
public EstablishChannelResponse establish(EstablishChannel req, Dispatcher dispatcher, UserConsent gui) {
EstablishChannelResponse response = new EstablishChannelResponse();
try {
// Get parameters for the PACE protocol
PACEInputType paceInput = new PACEInputType(req.getAuthenticationProtocolData());
byte[] pin;
byte pinID = paceInput.getPINID();
byte[] chat = paceInput.getCHAT();
if (paceInput.getPIN() == null || paceInput.getPIN().isEmpty()) {
// GUI request
GUIContentMap content = new GUIContentMap();
content.add(GUIContentMap.ELEMENT.PIN_ID, pinID);
PACEUserConsent paceUserConsent = new PACEUserConsent(gui);
paceUserConsent.show(content);
pin = ((String) content.get(GUIContentMap.ELEMENT.PIN)).getBytes(PACEConstants.PIN_CHARSET);
} else {
pin = paceInput.getPIN().getBytes(PACEConstants.PIN_CHARSET);
}
if (pin == null || pin.length == 0) {
response.setResult(WSHelper.makeResultError(ECardConstants.Minor.IFD.CANCELLATION_BY_USER, "No PIN was entered."));
return response;
}
// Read EF.CardAccess from card
byte[] slotHandle = req.getSlotHandle();
CardResponseAPDU resp = CardUtils.selectFileWithOptions(dispatcher, slotHandle, ShortUtils.toByteArray(PACEConstants.EF_CARDACCESS_FID), null, CardUtils.FCP_RESPONSE_DATA);
FCP efCardAccessFCP = new FCP(TLV.fromBER(resp.getData()));
byte[] efcadata = CardUtils.readFile(efCardAccessFCP, dispatcher, slotHandle);
// Parse SecurityInfos and get PACESecurityInfos
SecurityInfos sis = SecurityInfos.getInstance(efcadata);
EFCardAccess efca = new EFCardAccess(sis);
PACESecurityInfos psi = efca.getPACESecurityInfos();
// Start PACE
PACEImplementation pace = new PACEImplementation(dispatcher, slotHandle, psi);
pace.execute(pin, pinID, chat);
// Establish Secure Messaging channel
sm = new SecureMessaging(pace.getKeyMAC(), pace.getKeyENC());
// Create AuthenticationProtocolData (PACEOutputType)
PACEOutputType paceOutput = paceInput.getOutputType();
paceOutput.setEFCardAccess(efcadata);
paceOutput.setCurrentCAR(pace.getCurrentCAR());
paceOutput.setPreviousCAR(pace.getPreviousCAR());
paceOutput.setIDPICC(pace.getIDPICC());
paceOutput.setRetryCounter(pace.getRetryCounter());
// Create EstablishChannelResponse
response.setResult(WSHelper.makeResultOK());
response.setAuthenticationProtocolData(paceOutput.getAuthDataType());
} catch (UnsupportedEncodingException ex) {
logger.error(ex.getMessage(), ex);
response.setResult(WSHelper.makeResultError(ECardConstants.Minor.IFD.IO.UNKNOWN_PIN_FORMAT, "Cannot encode the PIN in " + PACEConstants.PIN_CHARSET + " charset."));
} catch (ProtocolException ex) {
logger.error(ex.getMessage(), ex);
response.setResult(WSHelper.makeResult(ex));
} catch (Throwable ex) {
logger.error(ex.getMessage(), ex);
response.setResult(WSHelper.makeResult(ex));
}
return response;
}
use of iso.std.iso_iec._24727.tech.schema.EstablishChannelResponse in project open-ecard by ecsec.
the class PACETest method executePACE_PIN.
@Test(enabled = false)
public void executePACE_PIN() throws UnsupportedDataTypeException, JAXBException, SAXException, WSMarshallerException {
ClientEnv env = new ClientEnv();
MessageDispatcher dispatcher = new MessageDispatcher(env);
IFD ifd = new IFD();
SwingUserConsent gui = new SwingUserConsent(new SwingDialogWrapper());
ifd.setGUI(gui);
env.setIFD(ifd);
env.setDispatcher(dispatcher);
ifd.addProtocol(ECardConstants.Protocol.PACE, new PACEProtocolFactory());
EstablishContext eCtx = new EstablishContext();
byte[] ctxHandle = ifd.establishContext(eCtx).getContextHandle();
ListIFDs listIFDs = new ListIFDs();
listIFDs.setContextHandle(ctxHandle);
String ifdName = ifd.listIFDs(listIFDs).getIFDName().get(0);
Connect connect = new Connect();
connect.setContextHandle(ctxHandle);
connect.setIFDName(ifdName);
connect.setSlot(BigInteger.ZERO);
byte[] slotHandle = ifd.connect(connect).getSlotHandle();
// PinID: 02 = CAN, 03 = PIN
String xmlCall = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<iso:EstablishChannel xmlns:iso=\"urn:iso:std:iso-iec:24727:tech:schema\">\n" + " <iso:SlotHandle>" + ByteUtils.toHexString(slotHandle) + "</iso:SlotHandle>\n" + " <iso:AuthenticationProtocolData Protocol=\"urn:oid:0.4.0.127.0.7.2.2.4\">\n" + " <iso:PinID>02</iso:PinID>\n" + " <iso:CHAT>7f4c12060904007f0007030102025305300301ffb7</iso:CHAT>\n" + // Remove PIN element to active the GUI
" <iso:PIN>142390</iso:PIN>\n" + // + " <iso:PIN>123456</iso:PIN>\n"
" </iso:AuthenticationProtocolData>\n" + "</iso:EstablishChannel>";
WSMarshaller m = WSMarshallerFactory.createInstance();
EstablishChannel eCh = (EstablishChannel) m.unmarshal(m.str2doc(xmlCall));
EstablishChannelResponse eChR = ifd.establishChannel(eCh);
LOG.info("PACE result: {}", eChR.getResult().getResultMajor());
try {
LOG.info("{}", eChR.getResult().getResultMinor());
LOG.info("{}", eChR.getResult().getResultMessage().getValue());
} catch (Exception ignore) {
}
}
use of iso.std.iso_iec._24727.tech.schema.EstablishChannelResponse in project open-ecard by ecsec.
the class PINStepAction method performPACEWithCAN.
private 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);
}
use of iso.std.iso_iec._24727.tech.schema.EstablishChannelResponse in project open-ecard by ecsec.
the class IFD method establishChannel.
@Override
public EstablishChannelResponse establishChannel(EstablishChannel parameters) {
byte[] slotHandle = parameters.getSlotHandle();
try {
SingleThreadChannel channel = cm.getSlaveChannel(slotHandle);
TerminalInfo termInfo = new TerminalInfo(cm, channel);
DIDAuthenticationDataType protoParam = parameters.getAuthenticationProtocolData();
String protocol = protoParam.getProtocol();
// check if it is PACE and try to perform native implementation
// get pace capabilities
List<PACECapabilities.PACECapability> paceCapabilities = termInfo.getPACECapabilities();
List<String> supportedProtos = TerminalInfo.buildPACEProtocolList(paceCapabilities);
// i don't care which type is supported, i try it anyways
if (!supportedProtos.isEmpty() && supportedProtos.get(0).startsWith(protocol)) {
// yeah, PACE seems to be supported by the reader, big win
PACEInputType paceParam = new PACEInputType(protoParam);
// extract variables needed for pace
byte pinID = paceParam.getPINID();
// optional elements
byte[] chat = paceParam.getCHAT();
String pin = paceParam.getPIN();
byte[] certDesc = paceParam.getCertificateDescription();
// prepare pace data structures
// TODO: add supplied PIN
EstablishPACERequest estPaceReq = new EstablishPACERequest(pinID, chat, null, certDesc);
ExecutePACERequest execPaceReq = new ExecutePACERequest(ExecutePACERequest.Function.EstablishPACEChannel, estPaceReq.toBytes());
// TODO: check if this additional check is really necessary
if (estPaceReq.isSupportedType(paceCapabilities)) {
byte[] reqData = execPaceReq.toBytes();
LOG.debug("executeCtrlCode request: {}", ByteUtils.toHexString(reqData));
// execute pace
Map<Integer, Integer> features = termInfo.getFeatureCodes();
byte[] resData = channel.transmitControlCommand(features.get(PCSCFeatures.EXECUTE_PACE), reqData);
LOG.debug("Response of executeCtrlCode: {}", ByteUtils.toHexString(resData));
// evaluate response
ExecutePACEResponse execPaceRes = new ExecutePACEResponse(resData);
if (execPaceRes.isError()) {
return WSHelper.makeResponse(EstablishChannelResponse.class, execPaceRes.getResult());
}
EstablishPACEResponse estPaceRes = new EstablishPACEResponse(execPaceRes.getData());
// get values and prepare response
PACEOutputType authDataResponse = paceParam.getOutputType();
// mandatory fields
authDataResponse.setRetryCounter(estPaceRes.getRetryCounter());
authDataResponse.setEFCardAccess(estPaceRes.getEFCardAccess());
// optional fields
if (estPaceRes.hasCurrentCAR()) {
authDataResponse.setCurrentCAR(estPaceRes.getCurrentCAR());
}
if (estPaceRes.hasPreviousCAR()) {
authDataResponse.setPreviousCAR(estPaceRes.getPreviousCAR());
}
if (estPaceRes.hasIDICC()) {
authDataResponse.setIDPICC(estPaceRes.getIDICC());
}
// create response type and return
EstablishChannelResponse response = WSHelper.makeResponse(EstablishChannelResponse.class, WSHelper.makeResultOK());
response.setAuthenticationProtocolData(authDataResponse.getAuthDataType());
return response;
}
}
// check out available software protocols
if (this.protocolFactories.contains(protocol)) {
ProtocolFactory factory = this.protocolFactories.get(protocol);
Protocol protoImpl = factory.createInstance();
EstablishChannelResponse response = protoImpl.establish(parameters, env.getDispatcher(), this.gui);
// register protocol instance for secure messaging when protocol was processed successful
if (response.getResult().getResultMajor().equals(ECardConstants.Major.OK)) {
channel.addSecureMessaging(protoImpl);
}
return response;
}
// if this point is reached a native implementation is not present, try registered protocols
Result r = WSHelper.makeResultUnknownError("No such protocol available in this IFD.");
return WSHelper.makeResponse(EstablishChannelResponse.class, r);
} catch (Throwable t) {
return WSHelper.makeResponse(EstablishChannelResponse.class, WSHelper.makeResult(t));
}
}
use of iso.std.iso_iec._24727.tech.schema.EstablishChannelResponse in project open-ecard by ecsec.
the class CANStepAction method perform.
@Override
public StepActionResult perform(Map<String, ExecutionResults> oldResults, StepResult result) {
if (result.isBack()) {
return new StepActionResult(StepActionResultStatus.BACK);
}
if (!state.equals(RecognizedState.PIN_suspended)) {
return new StepActionResult(StepActionResultStatus.NEXT);
}
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 new StepActionResult(StepActionResultStatus.CANCEL);
}
AuthDataResponse paceInputMap = tmp.createResponse(paceInput);
if (capturePin) {
ExecutionResults executionResults = oldResults.get(getStepID());
if (!verifyUserInput(executionResults)) {
// let the user enter the can again, when input verification failed
return new StepActionResult(StepActionResultStatus.REPEAT, createReplacementStep(false, true));
} else {
paceInputMap.addElement(PACEInputType.PIN, can);
}
}
paceInputMap.addElement(PACEInputType.PIN_ID, PIN_ID_CAN);
// perform PACE by EstablishChannelCommand
EstablishChannel establishChannel = new EstablishChannel();
establishChannel.setSlotHandle(conHandle.getSlotHandle());
establishChannel.setAuthenticationProtocolData(paceInputMap.getResponse());
establishChannel.getAuthenticationProtocolData().setProtocol(ECardConstants.Protocol.PACE);
try {
EstablishChannelResponse ecr = (EstablishChannelResponse) dispatcher.safeDeliver(establishChannel);
WSHelper.checkResult(ecr);
// pace was successfully performed, so get to the next step
String title = lang.translationForKey(PINSTEP_TITLE);
int retryCounter = 1;
Step replacementStep = new ChangePINStep("pin-entry", title, capturePin, retryCounter, false, false);
StepAction pinAction = new PINStepAction(capturePin, conHandle, dispatcher, replacementStep, retryCounter);
replacementStep.setAction(pinAction);
return new StepActionResult(StepActionResultStatus.NEXT, replacementStep);
} catch (WSException ex) {
LOG.info("Wrong CAN entered, trying again");
return new StepActionResult(StepActionResultStatus.REPEAT, createReplacementStep(true, false));
}
}
Aggregations